Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Nicolas Pitre and committed by
Nathan Chancellor
76df6815 5ce3218d

+130 -8
+19 -3
Documentation/kbuild/kconfig-language.rst
··· 118 118 This is a shorthand notation for a type definition plus a value. 119 119 Optionally dependencies for this default value can be added with "if". 120 120 121 - - dependencies: "depends on" <expr> 121 + - dependencies: "depends on" <expr> ["if" <expr>] 122 122 123 123 This defines a dependency for this menu entry. If multiple 124 124 dependencies are defined, they are connected with '&&'. Dependencies ··· 133 133 depends on BAR 134 134 bool "foo" 135 135 default y 136 + 137 + The dependency definition itself may be conditional by appending "if" 138 + followed by an expression. For example:: 139 + 140 + config FOO 141 + tristate 142 + depends on BAR if BAZ 143 + 144 + meaning that FOO is constrained by the value of BAR only if BAZ is 145 + also set. 136 146 137 147 - reverse dependencies: "select" <symbol> ["if" <expr>] 138 148 ··· 612 602 or build cleanly with that module disabled, but cause a link failure 613 603 when trying to use that loadable module from a built-in driver. 614 604 615 - The most common way to express this optional dependency in Kconfig logic 616 - uses the slightly counterintuitive:: 605 + The recommended way to express this optional dependency in Kconfig logic 606 + uses the conditional form:: 607 + 608 + config FOO 609 + tristate "Support for foo hardware" 610 + depends on BAR if BAR 611 + 612 + This slightly counterintuitive style is also widely used:: 617 613 618 614 config FOO 619 615 tristate "Support for foo hardware"
+1 -1
scripts/kconfig/lkc.h
··· 82 82 struct menu *menu_add_menu(void); 83 83 void menu_end_menu(void); 84 84 void menu_add_entry(struct symbol *sym, enum menu_type type); 85 - void menu_add_dep(struct expr *dep); 85 + void menu_add_dep(struct expr *dep, struct expr *cond); 86 86 void menu_add_visibility(struct expr *dep); 87 87 struct property *menu_add_prompt(enum prop_type type, const char *prompt, 88 88 struct expr *dep);
+11 -1
scripts/kconfig/menu.c
··· 127 127 return e; 128 128 } 129 129 130 - void menu_add_dep(struct expr *dep) 130 + void menu_add_dep(struct expr *dep, struct expr *cond) 131 131 { 132 + if (cond) { 133 + /* 134 + * We have "depends on X if Y" and we want: 135 + * Y != n --> X 136 + * Y == n --> y 137 + * That simplifies to: (X || (Y == n)) 138 + */ 139 + dep = expr_alloc_or(dep, 140 + expr_trans_compare(cond, E_EQUAL, &symbol_no)); 141 + } 132 142 current_entry->dep = expr_alloc_and(current_entry->dep, dep); 133 143 } 134 144
+3 -3
scripts/kconfig/parser.y
··· 323 323 { 324 324 printd(DEBUG_PARSE, "%s:%d:if\n", cur_filename, cur_lineno); 325 325 menu_add_entry(NULL, M_IF); 326 - menu_add_dep($2); 326 + menu_add_dep($2, NULL); 327 327 $$ = menu_add_menu(); 328 328 }; 329 329 ··· 422 422 423 423 /* depends option */ 424 424 425 - depends: T_DEPENDS T_ON expr T_EOL 425 + depends: T_DEPENDS T_ON expr if_expr T_EOL 426 426 { 427 - menu_add_dep($3); 427 + menu_add_dep($3, $4); 428 428 printd(DEBUG_PARSE, "%s:%d:depends on\n", cur_filename, cur_lineno); 429 429 }; 430 430
+32
scripts/kconfig/tests/conditional_dep/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Test Kconfig file for conditional dependencies. 3 + 4 + # Enable module support for tristate testing 5 + config MODULES 6 + bool "Enable loadable module support" 7 + modules 8 + default y 9 + 10 + config FOO 11 + bool "FOO symbol" 12 + 13 + config BAR 14 + bool "BAR symbol" 15 + 16 + config TEST_BASIC 17 + bool "Test basic conditional dependency" 18 + depends on FOO if BAR 19 + default y 20 + 21 + config TEST_COMPLEX 22 + bool "Test complex conditional dependency" 23 + depends on (FOO && BAR) if (FOO || BAR) 24 + default y 25 + 26 + config BAZ 27 + tristate "BAZ symbol" 28 + 29 + config TEST_OPTIONAL 30 + tristate "Test simple optional dependency" 31 + depends on BAZ if BAZ 32 + default y
+14
scripts/kconfig/tests/conditional_dep/__init__.py
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + """ 3 + Correctly handle conditional dependencies. 4 + """ 5 + 6 + def test(conf): 7 + assert conf.oldconfig('test_config1') == 0 8 + assert conf.config_matches('expected_config1') 9 + 10 + assert conf.oldconfig('test_config2') == 0 11 + assert conf.config_matches('expected_config2') 12 + 13 + assert conf.oldconfig('test_config3') == 0 14 + assert conf.config_matches('expected_config3')
+11
scripts/kconfig/tests/conditional_dep/expected_config1
··· 1 + # 2 + # Automatically generated file; DO NOT EDIT. 3 + # Main menu 4 + # 5 + CONFIG_MODULES=y 6 + CONFIG_FOO=y 7 + CONFIG_BAR=y 8 + CONFIG_TEST_BASIC=y 9 + CONFIG_TEST_COMPLEX=y 10 + CONFIG_BAZ=m 11 + CONFIG_TEST_OPTIONAL=m
+9
scripts/kconfig/tests/conditional_dep/expected_config2
··· 1 + # 2 + # Automatically generated file; DO NOT EDIT. 3 + # Main menu 4 + # 5 + CONFIG_MODULES=y 6 + # CONFIG_FOO is not set 7 + CONFIG_BAR=y 8 + CONFIG_BAZ=y 9 + CONFIG_TEST_OPTIONAL=y
+11
scripts/kconfig/tests/conditional_dep/expected_config3
··· 1 + # 2 + # Automatically generated file; DO NOT EDIT. 3 + # Main menu 4 + # 5 + CONFIG_MODULES=y 6 + # CONFIG_FOO is not set 7 + # CONFIG_BAR is not set 8 + CONFIG_TEST_BASIC=y 9 + CONFIG_TEST_COMPLEX=y 10 + # CONFIG_BAZ is not set 11 + CONFIG_TEST_OPTIONAL=y
+6
scripts/kconfig/tests/conditional_dep/test_config1
··· 1 + # Basic check that everything can be configured if selected. 2 + CONFIG_FOO=y 3 + CONFIG_BAR=y 4 + CONFIG_BAZ=m 5 + # Ensure that TEST_OPTIONAL=y with BAZ=m is converted to TEST_OPTIONAL=m 6 + CONFIG_TEST_OPTIONAL=y
+7
scripts/kconfig/tests/conditional_dep/test_config2
··· 1 + # If FOO is not selected, then TEST_BASIC should fail the conditional 2 + # dependency since BAR is set. 3 + # TEST_COMPLEX will fail dependency as it depends on both FOO and BAR 4 + # if either of those is selected. 5 + CONFIG_FOO=n 6 + CONFIG_BAR=y 7 + CONFIG_BAZ=y
+6
scripts/kconfig/tests/conditional_dep/test_config3
··· 1 + # If FOO is not selected, but BAR is also not selected, then TEST_BASIC 2 + # should pass since the dependency on FOO is conditional on BAR. 3 + # TEST_COMPLEX should be also set since neither FOO nor BAR are selected 4 + # so it has no dependencies. 5 + CONFIG_FOO=n 6 + CONFIG_BAR=n