zephyr/scripts/kconfig/kconfig.py
Ulf Magnusson f425c0aa27 scripts: kconfig: Disable the "FOO set more than once" warning
Some prj.conf files seem to deliberately override settings from the
board configuration (e.g. samples/bluetooth/hci_usb/prj.conf, with
GPIO=y). Disable the warning about a symbol being assigned more than
once to avoid warnings for those cases.

A list similar to WARNING_WHITELIST could be added later if more
warnings need to be disabled.

Also refactor the warning checking code a bit to get rid of some not's.

Suggested by Sebastian Bøe.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2018-06-13 14:06:38 +02:00

152 lines
5.3 KiB
Python
Executable file

#!/usr/bin/env python3
# Modified from: https://github.com/ulfalizer/Kconfiglib/blob/master/examples/merge_config.py
import argparse
import sys
from kconfiglib import Kconfig, Symbol, BOOL, STRING, TRISTATE, TRI_TO_STR
# Warnings that won't be turned into errors (but that will still be printed),
# identified by a substring of the warning. The warning texts from Kconfiglib
# are guaranteed to not change.
WARNING_WHITELIST = (
# Warning generated when a symbol with unsatisfied dependencies is being
# selected. These should be investigated, but whitelist them for now.
"unsatisfied direct dependencies",
# Assignments to certain undefined symbols. These are only defined for ARC
# and x86, respectively, but are set in some "shared" .conf files.
"undefined symbol ARC_INIT", # Issue #7977
"undefined symbol SSE", # Issue #7978
)
def fatal(warning):
# Returns True if 'warning' is not whitelisted and should be turned into an
# error
for wl_warning in WARNING_WHITELIST:
if wl_warning in warning:
return False
# Only allow enabled (printed) warnings to be fatal
return enabled(warning)
def enabled(warning):
# Returns True if 'warning' should be printed
# Some prj.conf files seem to deliberately override settings from the board
# configuration (e.g. samples/bluetooth/hci_usb/prj.conf, with GPIO=y).
# Disable the warning about a symbol being assigned more than once.
return "set more than once" not in warning
def main():
parse_args()
print("Parsing Kconfig tree in {}".format(args.kconfig_root))
kconf = Kconfig(args.kconfig_root, warn_to_stderr=False)
# Enable warnings for assignments to undefined symbols
kconf.enable_undef_warnings()
# 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.
print("Using {} as base".format(args.conf_fragments[0]))
for config in args.conf_fragments[1:]:
print("Merging {}".format(config))
# Create a merged configuration by loading the fragments with replace=False
for config in args.conf_fragments:
kconf.load_config(config, replace=False)
# 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:
verify_assigned_value(sym)
# We could roll this into the loop below, but it's nice to always print all
# warnings, even if one of them turns out to be fatal
for warning in kconf.warnings:
if enabled(warning):
print(warning, file=sys.stderr)
# Turn all warnings except for explicity whitelisted ones into errors. In
# particular, this will turn assignments to undefined Kconfig variables
# into errors.
#
# A warning is generated by this script whenever a symbol gets a different
# value than the one it was assigned. Keep that one as just a warning for
# now as well.
for warning in kconf.warnings:
if fatal(warning):
sys.exit("Error: Aborting due to non-whitelisted Kconfig "
"warning '{}'.\nNote: If this warning doesn't point "
"to an actual problem, you can add it to the "
"whitelist at the top of {}."
.format(warning, sys.argv[0]))
# Write the merged configuration
kconf.write_config(args.dotconfig)
# Write the C header
kconf.write_autoconf(args.autoconf)
def verify_assigned_value(sym):
# Verifies that the value assigned to 'sym' "took" (matches the value the
# symbol actually got), printing a warning otherwise
# 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 its dependencies in the 'menuconfig' interface (see the "
"Application Development Primer section of the manual), or in "
"the Kconfig reference at "
"http://docs.zephyrproject.org/reference/kconfig/CONFIG_{}.html "
"(which is updated regularly from the master branch)"
.format(name_and_loc(sym), user_value, sym.str_value, sym.name),
file=sys.stderr)
def name_and_loc(sym):
# Helper for printing the name and Kconfig file location(s) for a symbol
if not sym.nodes:
return sym.name + " (undefined)"
return "{} (defined at {})".format(
sym.name,
", ".join("{}:{}".format(node.filename, node.linenr)
for node in sym.nodes))
def parse_args():
global args
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument("kconfig_root")
parser.add_argument("dotconfig")
parser.add_argument("autoconf")
parser.add_argument("conf_fragments", metavar='conf', type=str, nargs='+')
args = parser.parse_args()
if __name__ == "__main__":
main()