scripts: kconfig: kconfiglib: introduce configdefault
Introduce the `configdefault` keyword as a Kconfig extension. This new keyword allows `default` values to be applied to externally defined symbols without needing to respecify dependencies, or weakening the existing dependencies. This is primarily useful in downstream repositories that wish to define default configurations such as: ``` config MY_COMPANY_APPS bool "Apply defaults for internal applications" configdefault BT default y if MY_COMPANY_APPS configdefault MCUMGR default y if MY_COMPANY_APPS && BT ``` Obtaining the same functionality with `config` (without weakening the symbol dependencies) requires finding the original definition and duplicating any `depends on` and surrounding `if` statements. This is a non-trivial exercise that needs to be manually rechecked on each Zephyr update. `configdefault` simplifies this process by acting as if the `default` statement was present at any one of the original definitions of the symbol. Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
parent
c8df08d681
commit
79e467c92a
|
@ -1096,6 +1096,8 @@ class Kconfig(object):
|
|||
|
||||
# Do various menu tree post-processing
|
||||
self._finalize_node(self.top_node, self.y)
|
||||
for s in self.syms.values():
|
||||
self._finalize_sym(s)
|
||||
|
||||
self.unique_defined_syms = _ordered_unique(self.defined_syms)
|
||||
self.unique_choices = _ordered_unique(self.choices)
|
||||
|
@ -2305,6 +2307,7 @@ class Kconfig(object):
|
|||
sym.kconfig = self
|
||||
sym.name = name
|
||||
sym.is_constant = False
|
||||
sym.configdefaults = []
|
||||
sym.rev_dep = sym.weak_rev_dep = sym.direct_dep = self.n
|
||||
|
||||
if self._parsing_kconfigs:
|
||||
|
@ -2324,6 +2327,7 @@ class Kconfig(object):
|
|||
sym.kconfig = self
|
||||
sym.name = name
|
||||
sym.is_constant = True
|
||||
sym.configdefaults = []
|
||||
sym.rev_dep = sym.weak_rev_dep = sym.direct_dep = self.n
|
||||
|
||||
if self._parsing_kconfigs:
|
||||
|
@ -2913,7 +2917,7 @@ class Kconfig(object):
|
|||
while self._next_line():
|
||||
t0 = self._tokens[0]
|
||||
|
||||
if t0 is _T_CONFIG or t0 is _T_MENUCONFIG:
|
||||
if t0 in [_T_CONFIG, _T_MENUCONFIG, _T_CONFIGDEFAULT]:
|
||||
# The tokenizer allocates Symbol objects for us
|
||||
sym = self._tokens[1]
|
||||
|
||||
|
@ -2929,6 +2933,7 @@ class Kconfig(object):
|
|||
node.kconfig = self
|
||||
node.item = sym
|
||||
node.is_menuconfig = t0 is _T_MENUCONFIG
|
||||
node.is_configdefault = t0 is _T_CONFIGDEFAULT
|
||||
node.prompt = node.help = node.list = None
|
||||
node.parent = parent
|
||||
node.filename = self.filename
|
||||
|
@ -2939,6 +2944,14 @@ class Kconfig(object):
|
|||
|
||||
self._parse_props(node)
|
||||
|
||||
if node.is_configdefault:
|
||||
if (node.prompt or
|
||||
node.dep != self.y or
|
||||
len(node.ranges) > 0 or
|
||||
len(node.selects) > 0 or
|
||||
len(node.implies) > 0):
|
||||
self._parse_error("configdefault can only contain `default`")
|
||||
|
||||
if node.is_menuconfig and not node.prompt:
|
||||
self._warn("the menuconfig symbol {} has no prompt"
|
||||
.format(sym.name_and_loc))
|
||||
|
@ -3551,6 +3564,23 @@ class Kconfig(object):
|
|||
# Post-parsing menu tree processing, including dependency propagation and
|
||||
# implicit submenu creation
|
||||
#
|
||||
def _finalize_sym(self, sym):
|
||||
# Finalizes symbol definitions
|
||||
#
|
||||
# - Applies configdefault node defaults to final symbols
|
||||
#
|
||||
# sym:
|
||||
# The symbol to finalize.
|
||||
|
||||
inserted = 0
|
||||
for (idx, defaults) in sym.configdefaults:
|
||||
for d in defaults:
|
||||
# Add the defaults to the node, with the requirement that
|
||||
# direct dependencies are respected. The original order
|
||||
# of the default statements between nodes is preserved.
|
||||
default = (d[0], self._make_and(sym.direct_dep, d[1]))
|
||||
sym.defaults.insert(inserted + idx, default)
|
||||
inserted += 1
|
||||
|
||||
def _finalize_node(self, node, visible_if):
|
||||
# Finalizes a menu node and its children:
|
||||
|
@ -3697,6 +3727,14 @@ class Kconfig(object):
|
|||
|
||||
sym = node.item
|
||||
|
||||
if node.is_configdefault:
|
||||
# Store any defaults for later application after the complete tree
|
||||
# is known. The current length of of the default array is stored so
|
||||
# the configdefaults can be inserted in the order they originally
|
||||
# appeared.
|
||||
sym.configdefaults.append((len(sym.defaults), node.defaults))
|
||||
return
|
||||
|
||||
# See the Symbol class docstring
|
||||
sym.direct_dep = self._make_or(sym.direct_dep, node.dep)
|
||||
|
||||
|
@ -4249,6 +4287,7 @@ class Symbol(object):
|
|||
"_write_to_conf",
|
||||
"choice",
|
||||
"defaults",
|
||||
"configdefaults",
|
||||
"direct_dep",
|
||||
"env_var",
|
||||
"implies",
|
||||
|
@ -5613,6 +5652,7 @@ class MenuNode(object):
|
|||
"help",
|
||||
"include_path",
|
||||
"is_menuconfig",
|
||||
"is_configdefault",
|
||||
"item",
|
||||
"kconfig",
|
||||
"linenr",
|
||||
|
@ -5814,8 +5854,13 @@ class MenuNode(object):
|
|||
sc = self.item
|
||||
|
||||
if sc.__class__ is Symbol:
|
||||
lines = [("menuconfig " if self.is_menuconfig else "config ")
|
||||
+ sc.name]
|
||||
if self.is_menuconfig:
|
||||
t = "menuconfig "
|
||||
elif self.is_configdefault:
|
||||
t = "configdefault "
|
||||
else:
|
||||
t = "config "
|
||||
lines = [t + sc.name]
|
||||
else:
|
||||
lines = ["choice " + sc.name if sc.name else "choice"]
|
||||
|
||||
|
@ -6860,6 +6905,7 @@ except AttributeError:
|
|||
_T_CLOSE_PAREN,
|
||||
_T_COMMENT,
|
||||
_T_CONFIG,
|
||||
_T_CONFIGDEFAULT,
|
||||
_T_DEFAULT,
|
||||
_T_DEFCONFIG_LIST,
|
||||
_T_DEF_BOOL,
|
||||
|
@ -6903,7 +6949,7 @@ except AttributeError:
|
|||
_T_TRISTATE,
|
||||
_T_UNEQUAL,
|
||||
_T_VISIBLE,
|
||||
) = range(1, 51)
|
||||
) = range(1, 52)
|
||||
|
||||
# Keyword to token map, with the get() method assigned directly as a small
|
||||
# optimization
|
||||
|
@ -6915,6 +6961,7 @@ _get_keyword = {
|
|||
"choice": _T_CHOICE,
|
||||
"comment": _T_COMMENT,
|
||||
"config": _T_CONFIG,
|
||||
"configdefault": _T_CONFIGDEFAULT,
|
||||
"def_bool": _T_DEF_BOOL,
|
||||
"def_hex": _T_DEF_HEX,
|
||||
"def_int": _T_DEF_INT,
|
||||
|
|
Loading…
Reference in a new issue