7 changed files with 326 additions and 333 deletions
@ -0,0 +1,139 @@
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3 |
||||
# |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
# |
||||
# diffconfig - a tool to compare .config files. |
||||
# |
||||
# originally written in 2006 by Matt Mackall |
||||
# (at least, this was in his bloatwatch source code) |
||||
# last worked on 2008 by Tim Bird |
||||
# |
||||
# Source https://github.com/zephyrproject-rtos/zephyr/blob/zephyr-v2.3.0/scripts/kconfig/diffconfig |
||||
# |
||||
# Modified to include negated values during merge_style |
||||
|
||||
import sys, os |
||||
|
||||
def usage(): |
||||
print("""Usage: diffconfig [-h] [-m] [<config1> <config2>] |
||||
|
||||
Diffconfig is a simple utility for comparing two .config files. |
||||
Using standard diff to compare .config files often includes extraneous and |
||||
distracting information. This utility produces sorted output with only the |
||||
changes in configuration values between the two files. |
||||
|
||||
Added and removed items are shown with a leading plus or minus, respectively. |
||||
Changed items show the old and new values on a single line. |
||||
|
||||
If -m is specified, then output will be in "merge" style, which has the |
||||
changed and new values in kernel config option format. |
||||
|
||||
If no config files are specified, .config and .config.old are used. |
||||
|
||||
Example usage: |
||||
$ diffconfig .config config-with-some-changes |
||||
-EXT2_FS_XATTR n |
||||
-EXT2_FS_XIP n |
||||
CRAMFS n -> y |
||||
EXT2_FS y -> n |
||||
LOG_BUF_SHIFT 14 -> 16 |
||||
PRINTK_TIME n -> y |
||||
""") |
||||
sys.exit(0) |
||||
|
||||
# returns a dictionary of name/value pairs for config items in the file |
||||
def readconfig(config_file): |
||||
d = {} |
||||
for line in config_file: |
||||
line = line[:-1] |
||||
if line[:7] == "CONFIG_": |
||||
name, val = line[7:].split("=", 1) |
||||
d[name] = val |
||||
if line[-11:] == " is not set": |
||||
d[line[9:-11]] = "n" |
||||
return d |
||||
|
||||
def print_config(op, config, value, new_value): |
||||
global merge_style |
||||
|
||||
if merge_style: |
||||
if op=="-" and value=="y": |
||||
print("CONFIG_%s=n" % (config)) |
||||
elif new_value: |
||||
if new_value=="n": |
||||
print("# CONFIG_%s is not set" % config) |
||||
else: |
||||
print("CONFIG_%s=%s" % (config, new_value)) |
||||
else: |
||||
if op=="-": |
||||
print("-%s %s" % (config, value)) |
||||
elif op=="+": |
||||
print("+%s %s" % (config, new_value)) |
||||
else: |
||||
print(" %s %s -> %s" % (config, value, new_value)) |
||||
|
||||
def main(): |
||||
global merge_style |
||||
|
||||
# parse command line args |
||||
if ("-h" in sys.argv or "--help" in sys.argv): |
||||
usage() |
||||
|
||||
merge_style = 0 |
||||
if "-m" in sys.argv: |
||||
merge_style = 1 |
||||
sys.argv.remove("-m") |
||||
|
||||
argc = len(sys.argv) |
||||
if not (argc==1 or argc == 3): |
||||
print("Error: incorrect number of arguments or unrecognized option") |
||||
usage() |
||||
|
||||
if argc == 1: |
||||
# if no filenames given, assume .config and .config.old |
||||
build_dir="" |
||||
if "KBUILD_OUTPUT" in os.environ: |
||||
build_dir = os.environ["KBUILD_OUTPUT"]+"/" |
||||
configa_filename = build_dir + ".config.old" |
||||
configb_filename = build_dir + ".config" |
||||
else: |
||||
configa_filename = sys.argv[1] |
||||
configb_filename = sys.argv[2] |
||||
|
||||
try: |
||||
a = readconfig(open(configa_filename)) |
||||
b = readconfig(open(configb_filename)) |
||||
except (IOError): |
||||
e = sys.exc_info()[1] |
||||
print("I/O error[%s]: %s\n" % (e.args[0],e.args[1])) |
||||
usage() |
||||
|
||||
# print items in a but not b (accumulate, sort and print) |
||||
old = [] |
||||
for config in a: |
||||
if config not in b: |
||||
old.append(config) |
||||
old.sort() |
||||
for config in old: |
||||
print_config("-", config, a[config], None) |
||||
del a[config] |
||||
|
||||
# print items that changed (accumulate, sort, and print) |
||||
changed = [] |
||||
for config in a: |
||||
if a[config] != b[config]: |
||||
changed.append(config) |
||||
else: |
||||
del b[config] |
||||
changed.sort() |
||||
for config in changed: |
||||
print_config("->", config, a[config], b[config]) |
||||
del b[config] |
||||
|
||||
# now print items in b but not in a |
||||
# (items from b that were in a were removed above) |
||||
new = sorted(b.keys()) |
||||
for config in new: |
||||
print_config("+", config, None, b[config]) |
||||
|
||||
main() |
@ -0,0 +1,121 @@
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# This script functions similarly to scripts/kconfig/merge_config.sh from the |
||||
# kernel tree, merging multiple configurations fragments to produce a complete |
||||
# .config, with unspecified values filled in as for alldefconfig. |
||||
# |
||||
# The generated .config respects symbol dependencies, and a warning is printed |
||||
# if any symbol gets a different value from the assigned value. |
||||
# |
||||
# For a real-world merging example based on this script, see |
||||
# https://github.com/zephyrproject-rtos/zephyr/blob/master/scripts/kconfig/kconfig.py. |
||||
# |
||||
# Here's a demo: |
||||
# |
||||
# Kconfig contents: |
||||
# |
||||
# config FOO |
||||
# bool "FOO" |
||||
# |
||||
# config BAR |
||||
# bool "BAR" |
||||
# |
||||
# config BAZ |
||||
# string "BAZ" |
||||
# |
||||
# config QAZ |
||||
# bool "QAZ" if n |
||||
# |
||||
# |
||||
# conf1 contents: |
||||
# |
||||
# CONFIG_FOO=y |
||||
# |
||||
# |
||||
# conf2 contents: |
||||
# |
||||
# CONFIG_BAR=y |
||||
# |
||||
# |
||||
# conf3 contents: |
||||
# |
||||
# # Assigned twice (would generate warning if 'warn_assign_override' was |
||||
# # True) |
||||
# # CONFIG_FOO is not set |
||||
# |
||||
# # Ops... this symbol doesn't exist |
||||
# CONFIG_OPS=y |
||||
# |
||||
# CONFIG_BAZ="baz string" |
||||
# |
||||
# |
||||
# conf4 contents: |
||||
# |
||||
# CONFIG_QAZ=y |
||||
# |
||||
# |
||||
# Running: |
||||
# |
||||
# $ python(3) merge_config.py Kconfig merged conf1 conf2 conf3 conf4 |
||||
# Merged configuration 'conf1' |
||||
# Merged configuration 'conf2' |
||||
# conf3:5: warning: attempt to assign the value 'y' to the undefined symbol OPS |
||||
# Merged configuration 'conf3' |
||||
# Merged configuration 'conf4' |
||||
# Configuration saved to 'merged' |
||||
# warning: QAZ (defined at Kconfig:10) was assigned the value 'y' but got the value 'n' -- check dependencies |
||||
# $ cat merged |
||||
# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) |
||||
# # CONFIG_FOO is not set |
||||
# CONFIG_BAR=y |
||||
# CONFIG_BAZ="baz string" |
||||
|
||||
from __future__ import print_function |
||||
import sys |
||||
|
||||
from kconfiglib import Kconfig, BOOL, TRISTATE, TRI_TO_STR |
||||
|
||||
|
||||
if len(sys.argv) < 4: |
||||
sys.exit("usage: merge_config.py Kconfig merged_config config1 [config2 ...]") |
||||
|
||||
kconf = Kconfig(sys.argv[1], suppress_traceback=True) |
||||
|
||||
# Enable warnings for assignments to undefined symbols |
||||
kconf.warn_assign_undef = True |
||||
|
||||
# (This script uses alldefconfig as the base. Other starting states could be |
||||
# set up here as well. The approach in examples/allnoconfig_simpler.py could |
||||
# provide an allnoconfig starting state for example.) |
||||
|
||||
# Disable warnings generated for multiple assignments to the same symbol within |
||||
# a (set of) configuration files. Assigning a symbol multiple times might be |
||||
# done intentionally when merging configuration files. |
||||
kconf.warn_assign_override = False |
||||
kconf.warn_assign_redun = False |
||||
|
||||
# Create a merged configuration by loading the fragments with replace=False. |
||||
# load_config() and write_config() returns a message to print. |
||||
for config in sys.argv[3:]: |
||||
print(kconf.load_config(config, replace=False)) |
||||
|
||||
# Write the merged configuration |
||||
print(kconf.write_config(sys.argv[2])) |
||||
|
||||
# Print warnings for symbols whose actual value doesn't match the assigned |
||||
# value |
||||
for sym in kconf.defined_syms: |
||||
# Was the symbol assigned to? |
||||
if sym.user_value is not None: |
||||
# Tristate values are represented as 0, 1, 2. Having them as |
||||
# "n", "m", "y" is more convenient here, so convert. |
||||
if sym.type in (BOOL, TRISTATE): |
||||
user_value = TRI_TO_STR[sym.user_value] |
||||
else: |
||||
user_value = sym.user_value |
||||
|
||||
if user_value != sym.str_value: |
||||
print("warning: {} was assigned the value '{}' but got the " |
||||
"value '{}' -- check dependencies".format( |
||||
sym.name_and_loc, user_value, sym.str_value), |
||||
file=sys.stderr) |
Loading…
Reference in new issue