Skip to content

Commit

Permalink
Warn if a symbol with unsatisfied deps is selected
Browse files Browse the repository at this point in the history
Mirrors a warning in the C implementation. Make it a bit more
informative and simpler to decode for people who aren't super familiar
with Kconfig.

The warning is printed when/if the symbol is evaluated, e.g. when
writing a .config or C header or accessing Symbol.str/tri_value. It is
not printed if the symbol value has already been calculated and is
cached and up-to-date, which avoids warning spam.

Example:

  config Y_SYMBOL_1
  	def_bool y

  config Y_SYMBOL_2
  	def_bool y

  config SELECTED
  	bool
  	depends on !Y_SYMBOL_1

  config SELECTING_1
  	def_bool y
  	select SELECTED

  # Skipped in warning, because n
  config SELECTING_2
  	def_bool n
  	select SELECTED

  config SELECTING_3
  	def_bool y
  	select SELECTED if Y_SYMBOL_1
  	depends on Y_SYMBOL_2

  # Defined in multiple locations
  config SELECTING_3

Generated warning:

  warning: SELECTED (defined at Kconfig:7) has unsatisfied direct dependencies (!Y_SYMBOL_1), but is currently being selected by the following symbols:
  SELECTING_3 (value: y, defined at Kconfig:20, Kconfig:26), with direct dependencies "y" (value: y) and select condition Y_SYMBOL_1 && Y_SYMBOL_2 (value: y)
  SELECTING_1 (value: y, defined at Kconfig:11), with direct dependencies "y" (value: y)

Real-world example from test suite:

  warning: NOT_COHERENT_CACHE (defined at arch/powerpc/platforms/Kconfig.cputype:381) has unsatisfied direct dependencies (4xx || PPC_8xx || E200 || PPC_MPC512x || GAMECUBE_COMMON), but is currently being selected by the following symbols:
  AMIGAONE (value: y, defined at arch/powerpc/platforms/amigaone/Kconfig:2), with direct dependencies 6xx && BROKEN_ON_SMP (value: y) and select condition 6xx && BROKEN_ON_SMP (value: y)
  • Loading branch information
ulfalizer committed Jan 24, 2018
1 parent 3169eb8 commit 0087b40
Showing 1 changed file with 72 additions and 0 deletions.
72 changes: 72 additions & 0 deletions kconfiglib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1942,6 +1942,7 @@ def _parse_properties(self, node, visible_if_deps):
(target, self._make_and(cond, node.dep)))

# Modify the dependencies of the selected symbol
# Warning: See _warn_select_unsatisfied_deps()
target.rev_dep = \
self._make_or(target.rev_dep,
self._make_and(node.item,
Expand Down Expand Up @@ -2582,6 +2583,9 @@ def tri_value(self):
val = max(rev_dep_val, val)
self._write_to_conf = True

if not expr_value(self.direct_dep):
self._warn_select_unsatisfied_deps()

# m is promoted to y for (1) bool symbols and (2) symbols with a
# weak_rev_dep (from imply) of y
if val == 1 and \
Expand Down Expand Up @@ -2976,6 +2980,74 @@ def _rec_invalidate_if_has_prompt(self):
self.kconfig._warn(self.name + " has no prompt, meaning user "
"values have no effect on it")

def _warn_select_unsatisfied_deps(self):
"""
Helper for printing an informative warning when a symbol with
unsatisfied direct dependencies (dependencies from 'depends on', ifs,
and menus) is selected by some other symbol
"""
def location_str(sym):
return "defined at " + \
", ".join("{}:{}".format(node.filename, node.linenr)
for node in sym.nodes)

warn_msg = "{} ({}) has unsatisfied direct dependencies ({}), but " \
"is currently being selected by the following symbols:" \
.format(self.name,
location_str(self),
expr_str(self.direct_dep))

# Returns a warning string if 'select' is actually selecting us, and
# the empty string otherwise
def check_select(select):
# No 'nonlocal' in Python 2. Just return the string to append to
# warn_msg instead.
select_val = expr_value(select)
if not select_val:
# Only include selects that are not n
return ""

if isinstance(select, tuple):
# (AND, <sym>, <condition>)
selecting_sym = select[1]
else:
# <sym>
selecting_sym = select

msg = "\n{} (value: {}, {}), with direct dependencies {} " \
"(value: {})" \
.format(selecting_sym.name,
selecting_sym.str_value,
location_str(selecting_sym),
expr_str(selecting_sym.direct_dep),
TRI_TO_STR[expr_value(selecting_sym.direct_dep)])

if isinstance(select, tuple):
msg += " and select condition {} (value: {})" \
.format(expr_str(select[2]),
TRI_TO_STR[expr_value(select[2])])

return msg

expr = self.rev_dep
while 1:
# This relies on us using the following format for the select
# expression (which is nice in that it preserves the order of the
# selecting symbols):
#
# (OR, (OR, (OR, <expr 1>, <expr 2>), <expr 3>), <expr 4>)
#
# We could do fancier expression processing later if needed.
if isinstance(expr, tuple) and expr[0] == OR:
warn_msg += check_select(expr[2])
# Go to the next select
expr = expr[1]
else:
warn_msg += check_select(expr)
break

self.kconfig._warn(warn_msg)

class Choice(object):
"""
Represents a choice statement:
Expand Down

0 comments on commit 0087b40

Please sign in to comment.