Unverified Commit 76df6815 authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Nathan Chancellor
Browse files

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: default avatarNicolas Pitre <nico@fluxnic.net>
[Graham Roff: Rewrote commit message, updated patch, added tests]
Signed-off-by: default avatarGraham Roff <grahamr@qti.qualcomm.com>
Acked-by: default avatarRandy 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: default avatarNathan Chancellor <nathan@kernel.org>
parent 5ce3218d
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -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"
+1 −1
Original line number Diff line number Diff line
@@ -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);
+11 −1
Original line number Diff line number Diff line
@@ -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);
}

+3 −3
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
# 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
Loading