mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 03:44:45 +01:00
kconfig: Support conditional deps using "depends on X if Y"
Extend the "depends on" syntax to support conditional dependencies using "depends on X if Y". While functionally equivalent to "depends on X || (Y == n)", "depends on X if Y" is much more readable and makes the kconfig language uniform in supporting the "if <expr>" suffix. This also improves readability for "optional" dependencies, which are the subset of conditional dependencies where X is Y. Previously such optional dependencies had to be expressed as the counterintuitive "depends on X || !X", now this can be represented as "depends on X if X". The change is implemented by converting the "X if Y" syntax into the "X || (Y == n)" syntax during "depends on" token processing. Signed-off-by: Nicolas Pitre <nico@fluxnic.net> [Graham Roff: Rewrote commit message, updated patch, added tests] Signed-off-by: Graham Roff <grahamr@qti.qualcomm.com> Acked-by: Randy Dunlap <rdunlap@infradead.org> Link: https://patch.msgid.link/20251215-kconfig_conditional_deps-v3-1-59519af0a5df@qti.qualcomm.com [nathan: Minor adjustments to spacing] Signed-off-by: Nathan Chancellor <nathan@kernel.org>
This commit is contained in:
parent
5ce3218d4f
commit
76df6815da
12 changed files with 130 additions and 8 deletions
|
|
@ -118,7 +118,7 @@ applicable everywhere (see syntax).
|
|||
This is a shorthand notation for a type definition plus a value.
|
||||
Optionally dependencies for this default value can be added with "if".
|
||||
|
||||
- dependencies: "depends on" <expr>
|
||||
- dependencies: "depends on" <expr> ["if" <expr>]
|
||||
|
||||
This defines a dependency for this menu entry. If multiple
|
||||
dependencies are defined, they are connected with '&&'. Dependencies
|
||||
|
|
@ -134,6 +134,16 @@ applicable everywhere (see syntax).
|
|||
bool "foo"
|
||||
default y
|
||||
|
||||
The dependency definition itself may be conditional by appending "if"
|
||||
followed by an expression. For example::
|
||||
|
||||
config FOO
|
||||
tristate
|
||||
depends on BAR if BAZ
|
||||
|
||||
meaning that FOO is constrained by the value of BAR only if BAZ is
|
||||
also set.
|
||||
|
||||
- reverse dependencies: "select" <symbol> ["if" <expr>]
|
||||
|
||||
While normal dependencies reduce the upper limit of a symbol (see
|
||||
|
|
@ -602,8 +612,14 @@ Some drivers are able to optionally use a feature from another module
|
|||
or build cleanly with that module disabled, but cause a link failure
|
||||
when trying to use that loadable module from a built-in driver.
|
||||
|
||||
The most common way to express this optional dependency in Kconfig logic
|
||||
uses the slightly counterintuitive::
|
||||
The recommended way to express this optional dependency in Kconfig logic
|
||||
uses the conditional form::
|
||||
|
||||
config FOO
|
||||
tristate "Support for foo hardware"
|
||||
depends on BAR if BAR
|
||||
|
||||
This slightly counterintuitive style is also widely used::
|
||||
|
||||
config FOO
|
||||
tristate "Support for foo hardware"
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ void menu_warn(const struct menu *menu, const char *fmt, ...);
|
|||
struct menu *menu_add_menu(void);
|
||||
void menu_end_menu(void);
|
||||
void menu_add_entry(struct symbol *sym, enum menu_type type);
|
||||
void menu_add_dep(struct expr *dep);
|
||||
void menu_add_dep(struct expr *dep, struct expr *cond);
|
||||
void menu_add_visibility(struct expr *dep);
|
||||
struct property *menu_add_prompt(enum prop_type type, const char *prompt,
|
||||
struct expr *dep);
|
||||
|
|
|
|||
|
|
@ -127,8 +127,18 @@ static struct expr *rewrite_m(struct expr *e)
|
|||
return e;
|
||||
}
|
||||
|
||||
void menu_add_dep(struct expr *dep)
|
||||
void menu_add_dep(struct expr *dep, struct expr *cond)
|
||||
{
|
||||
if (cond) {
|
||||
/*
|
||||
* We have "depends on X if Y" and we want:
|
||||
* Y != n --> X
|
||||
* Y == n --> y
|
||||
* That simplifies to: (X || (Y == n))
|
||||
*/
|
||||
dep = expr_alloc_or(dep,
|
||||
expr_trans_compare(cond, E_EQUAL, &symbol_no));
|
||||
}
|
||||
current_entry->dep = expr_alloc_and(current_entry->dep, dep);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ if_entry: T_IF expr T_EOL
|
|||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:if\n", cur_filename, cur_lineno);
|
||||
menu_add_entry(NULL, M_IF);
|
||||
menu_add_dep($2);
|
||||
menu_add_dep($2, NULL);
|
||||
$$ = menu_add_menu();
|
||||
};
|
||||
|
||||
|
|
@ -422,9 +422,9 @@ help: help_start T_HELPTEXT
|
|||
|
||||
/* depends option */
|
||||
|
||||
depends: T_DEPENDS T_ON expr T_EOL
|
||||
depends: T_DEPENDS T_ON expr if_expr T_EOL
|
||||
{
|
||||
menu_add_dep($3);
|
||||
menu_add_dep($3, $4);
|
||||
printd(DEBUG_PARSE, "%s:%d:depends on\n", cur_filename, cur_lineno);
|
||||
};
|
||||
|
||||
|
|
|
|||
32
scripts/kconfig/tests/conditional_dep/Kconfig
Normal file
32
scripts/kconfig/tests/conditional_dep/Kconfig
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Test Kconfig file for conditional dependencies.
|
||||
|
||||
# Enable module support for tristate testing
|
||||
config MODULES
|
||||
bool "Enable loadable module support"
|
||||
modules
|
||||
default y
|
||||
|
||||
config FOO
|
||||
bool "FOO symbol"
|
||||
|
||||
config BAR
|
||||
bool "BAR symbol"
|
||||
|
||||
config TEST_BASIC
|
||||
bool "Test basic conditional dependency"
|
||||
depends on FOO if BAR
|
||||
default y
|
||||
|
||||
config TEST_COMPLEX
|
||||
bool "Test complex conditional dependency"
|
||||
depends on (FOO && BAR) if (FOO || BAR)
|
||||
default y
|
||||
|
||||
config BAZ
|
||||
tristate "BAZ symbol"
|
||||
|
||||
config TEST_OPTIONAL
|
||||
tristate "Test simple optional dependency"
|
||||
depends on BAZ if BAZ
|
||||
default y
|
||||
14
scripts/kconfig/tests/conditional_dep/__init__.py
Normal file
14
scripts/kconfig/tests/conditional_dep/__init__.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
"""
|
||||
Correctly handle conditional dependencies.
|
||||
"""
|
||||
|
||||
def test(conf):
|
||||
assert conf.oldconfig('test_config1') == 0
|
||||
assert conf.config_matches('expected_config1')
|
||||
|
||||
assert conf.oldconfig('test_config2') == 0
|
||||
assert conf.config_matches('expected_config2')
|
||||
|
||||
assert conf.oldconfig('test_config3') == 0
|
||||
assert conf.config_matches('expected_config3')
|
||||
11
scripts/kconfig/tests/conditional_dep/expected_config1
Normal file
11
scripts/kconfig/tests/conditional_dep/expected_config1
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Main menu
|
||||
#
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_FOO=y
|
||||
CONFIG_BAR=y
|
||||
CONFIG_TEST_BASIC=y
|
||||
CONFIG_TEST_COMPLEX=y
|
||||
CONFIG_BAZ=m
|
||||
CONFIG_TEST_OPTIONAL=m
|
||||
9
scripts/kconfig/tests/conditional_dep/expected_config2
Normal file
9
scripts/kconfig/tests/conditional_dep/expected_config2
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Main menu
|
||||
#
|
||||
CONFIG_MODULES=y
|
||||
# CONFIG_FOO is not set
|
||||
CONFIG_BAR=y
|
||||
CONFIG_BAZ=y
|
||||
CONFIG_TEST_OPTIONAL=y
|
||||
11
scripts/kconfig/tests/conditional_dep/expected_config3
Normal file
11
scripts/kconfig/tests/conditional_dep/expected_config3
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Main menu
|
||||
#
|
||||
CONFIG_MODULES=y
|
||||
# CONFIG_FOO is not set
|
||||
# CONFIG_BAR is not set
|
||||
CONFIG_TEST_BASIC=y
|
||||
CONFIG_TEST_COMPLEX=y
|
||||
# CONFIG_BAZ is not set
|
||||
CONFIG_TEST_OPTIONAL=y
|
||||
6
scripts/kconfig/tests/conditional_dep/test_config1
Normal file
6
scripts/kconfig/tests/conditional_dep/test_config1
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Basic check that everything can be configured if selected.
|
||||
CONFIG_FOO=y
|
||||
CONFIG_BAR=y
|
||||
CONFIG_BAZ=m
|
||||
# Ensure that TEST_OPTIONAL=y with BAZ=m is converted to TEST_OPTIONAL=m
|
||||
CONFIG_TEST_OPTIONAL=y
|
||||
7
scripts/kconfig/tests/conditional_dep/test_config2
Normal file
7
scripts/kconfig/tests/conditional_dep/test_config2
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# If FOO is not selected, then TEST_BASIC should fail the conditional
|
||||
# dependency since BAR is set.
|
||||
# TEST_COMPLEX will fail dependency as it depends on both FOO and BAR
|
||||
# if either of those is selected.
|
||||
CONFIG_FOO=n
|
||||
CONFIG_BAR=y
|
||||
CONFIG_BAZ=y
|
||||
6
scripts/kconfig/tests/conditional_dep/test_config3
Normal file
6
scripts/kconfig/tests/conditional_dep/test_config3
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# If FOO is not selected, but BAR is also not selected, then TEST_BASIC
|
||||
# should pass since the dependency on FOO is conditional on BAR.
|
||||
# TEST_COMPLEX should be also set since neither FOO nor BAR are selected
|
||||
# so it has no dependencies.
|
||||
CONFIG_FOO=n
|
||||
CONFIG_BAR=n
|
||||
Loading…
Add table
Add a link
Reference in a new issue