Skip to contentSkip to conversation

kconfig: Introduce cc-option-str

PATCH In review Kees Cook 4 participants 12 messages Sep 19 – Sep 24

Subsystems (3)
lore
Share & tools
lore

Kees Cook

author
#0 lore raw

cover kconfig: Introduce cc-option-str

Hi,

While reviewing the recent build speedup series[1], it became clear that we needed a general solution in kconfig to avoid repeating detected toolchain options. Implement cc-option-str and ld-option-str, and while at it, create "def_string" and friends to match "def_bool".

-Kees

[1] https://lore.kernel.org/all/20260918054058.GA384222@ax162/

Kees Cook (3):
kconfig: Add "def_string", "def_int" and "def_hex"
kconfig: Replace "cc-option-bit" with "cc-option-str"
kconfig: Add "ld-option-str"

 scripts/kconfig/tests/def_type/Kconfig        | 28 ++++++++++++++++++
 scripts/kconfig/tests/def_type/guard_n.config |  1 +
 scripts/kconfig/tests/def_type/guard_y.config |  1 +
 scripts/kconfig/tests/def_type/__init__.py    | 18 ++++++++++++
 .../kconfig/tests/def_type/expected_guard_n   |  9 ++++++
 .../kconfig/tests/def_type/expected_guard_y   | 11 +++++++
 scripts/Kconfig.include                       | 29 +++++++++++++++----
 scripts/kconfig/kconfig-sym-check.pl          |  2 +-
 scripts/kconfig/lexer.l                       |  3 ++
 scripts/kconfig/parser.y                      |  6 ++++
 Documentation/kbuild/kconfig-language.rst     | 13 ++++++++-
 11 files changed, 114 insertions(+), 7 deletions(-)
 create mode 100644 scripts/kconfig/tests/def_type/Kconfig
 create mode 100644 scripts/kconfig/tests/def_type/guard_n.config
 create mode 100644 scripts/kconfig/tests/def_type/guard_y.config
 create mode 100644 scripts/kconfig/tests/def_type/__init__.py
 create mode 100644 scripts/kconfig/tests/def_type/expected_guard_n
 create mode 100644 scripts/kconfig/tests/def_type/expected_guard_y
Signature · 1 line
2.34.1
author
#1 lore raw

PATCH 1/3 kconfig: Add "def_string", "def_int" and "def_hex"

Kconfig has offered "def_bool" and "def_tristate" as a shorthand for a type definition plus a default since before the git era, but has never offered the equivalent for the other three types. Conor Dooley ran into this gap[1] when fixing a symbol that had been given the wrong type:

Unfortunately, there is no such thing as "def_string", but in this case we can use "default" to propagate the value of ...

Nothing in the grammar requires the restriction. The rule that consumes a default is already type agnostic. Add the three missing types. No changes are needed to existing diagnostics. E.g. declaring a symbol "bool" and then assigning it with "def_string" still reports

warning: ignoring type redefinition of 'CONFLICT' from 'bool' to 'string'

Added tests for the types.

Build tested ARCH=x86_64 with GCC 16.2.0. Tests pass with "make testconfig".

---
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Julian Braha <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Cc: Shuah Khan <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Masahiro Yamada <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Nicolas Pitre <[email protected]>
Cc: Krzysztof Kozlowski <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Andrew Jones <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>

---
 scripts/kconfig/tests/def_type/Kconfig        | 28 +++++++++++++++++++
 scripts/kconfig/tests/def_type/guard_n.config |  1 +
 scripts/kconfig/tests/def_type/guard_y.config |  1 +
 scripts/kconfig/tests/def_type/__init__.py    | 18 ++++++++++++
 .../kconfig/tests/def_type/expected_guard_n   |  9 ++++++
 .../kconfig/tests/def_type/expected_guard_y   | 11 ++++++++
 scripts/kconfig/kconfig-sym-check.pl          |  2 +-
 scripts/kconfig/lexer.l                       |  3 ++
 scripts/kconfig/parser.y                      |  6 ++++
 Documentation/kbuild/kconfig-language.rst     | 13 ++++++++-
 10 files changed, 90 insertions(+), 2 deletions(-)
 create mode 100644 scripts/kconfig/tests/def_type/Kconfig
 create mode 100644 scripts/kconfig/tests/def_type/guard_n.config
 create mode 100644 scripts/kconfig/tests/def_type/guard_y.config
 create mode 100644 scripts/kconfig/tests/def_type/__init__.py
 create mode 100644 scripts/kconfig/tests/def_type/expected_guard_n
 create mode 100644 scripts/kconfig/tests/def_type/expected_guard_y
scripts/kconfig/tests/def_type/Kconfig new file +28 -0
new file mode 100644
index 000000000000..fbee37a63179
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0
+# The def_<type> shorthands: a type definition plus a default value.
+
+config MODULES
+	bool "Enable loadable module support"
+	modules
+	default y
+
+config GUARD
+	bool "Guard symbol"
+
+config DEF_BOOL
+	def_bool GUARD
+
+config DEF_TRISTATE
+	def_tristate m if GUARD
+
+config DEF_STRING
+	def_string "guarded" if GUARD
+	default "fallback"
+
+config DEF_INT
+	def_int 64 if GUARD
+	default 32
+
+config DEF_HEX
+	def_hex 0xdead if GUARD
+	default 0x0
scripts/kconfig/tests/def_type/guard_n.config new file +1 -0
new file mode 100644
index 000000000000..ed9ad6c1a2d4
@@ -0,0 +1 @@
+# CONFIG_GUARD is not set
scripts/kconfig/tests/def_type/guard_y.config new file +1 -0
new file mode 100644
index 000000000000..afe35b084542
@@ -0,0 +1 @@
+CONFIG_GUARD=y
scripts/kconfig/tests/def_type/__init__.py new file +18 -0
new file mode 100644
index 000000000000..1ebaf5da07c8
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Set a symbol's type and its default value in one line.
+
+"def_bool", "def_tristate", "def_string", "def_int" and "def_hex" are
+shorthand for a type definition plus a "default" property.  Check that
+each one sets the type, and that an "if" on the shorthand does not
+disturb the usual default cascade: the shorthand is only the first arm
+of the list, so a later "default" still applies when its condition is
+not met.
+"""
+
+def test(conf):
+    assert conf.olddefconfig(dot_config='guard_y.config') == 0
+    assert conf.config_matches('expected_guard_y')
+
+    assert conf.olddefconfig(dot_config='guard_n.config') == 0
+    assert conf.config_matches('expected_guard_n')
scripts/kconfig/tests/def_type/expected_guard_n new file +9 -0
new file mode 100644
index 000000000000..14719720a8b9
@@ -0,0 +1,9 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+CONFIG_MODULES=y
+# CONFIG_GUARD is not set
+CONFIG_DEF_STRING="fallback"
+CONFIG_DEF_INT=32
+CONFIG_DEF_HEX=0x0
scripts/kconfig/tests/def_type/expected_guard_y new file +11 -0
new file mode 100644
index 000000000000..b2844072d0b8
@@ -0,0 +1,11 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+CONFIG_MODULES=y
+CONFIG_GUARD=y
+CONFIG_DEF_BOOL=y
+CONFIG_DEF_TRISTATE=m
+CONFIG_DEF_STRING="guarded"
+CONFIG_DEF_INT=64
+CONFIG_DEF_HEX=0xdead
scripts/kconfig/kconfig-sym-check.pl +1 -1
index daa5285fdefc..c8dd07f8b27c 100755
@@ -90,7 +90,7 @@ foreach my $file (@files) {
 			next;
 		}
 
-		if (/^\s*(default|def_bool|def_tristate|select|depends\s+on|imply|visible\s+if|range|if|bool|tristate|int|hex|string|prompt)\s+(.+)\s*$/) {
+		if (/^\s*(default|def_bool|def_tristate|def_string|def_int|def_hex|select|depends\s+on|imply|visible\s+if|range|if|bool|tristate|int|hex|string|prompt)\s+(.+)\s*$/) {
 			my $s = $2;
 			$s =~ s/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'//g;
 			$s =~ s/#.*//;
scripts/kconfig/lexer.l +3 -0
index a6155422b4a6..1fa521199d4a 100644
@@ -105,6 +105,9 @@ n	[A-Za-z0-9_-]
 "comment"		return T_COMMENT;
 "config"		return T_CONFIG;
 "def_bool"		return T_DEF_BOOL;
+"def_hex"		return T_DEF_HEX;
+"def_int"		return T_DEF_INT;
+"def_string"		return T_DEF_STRING;
 "def_tristate"		return T_DEF_TRISTATE;
 "default"		return T_DEFAULT;
 "depends"		return T_DEPENDS;
scripts/kconfig/parser.y +6 -0
index 5fb6f07b6ad2..2174baf2b3fd 100644
@@ -53,6 +53,9 @@ struct menu *current_menu, *current_entry, *current_choice;
 %token T_CONFIG
 %token T_DEFAULT
 %token T_DEF_BOOL
+%token T_DEF_HEX
+%token T_DEF_INT
+%token T_DEF_STRING
 %token T_DEF_TRISTATE
 %token T_DEPENDS
 %token T_ENDCHOICE
@@ -309,6 +312,9 @@ type:
 default:
 	  T_DEFAULT		{ $$ = S_UNKNOWN; }
 	| T_DEF_BOOL		{ $$ = S_BOOLEAN; }
+	| T_DEF_HEX		{ $$ = S_HEX; }
+	| T_DEF_INT		{ $$ = S_INT; }
+	| T_DEF_STRING		{ $$ = S_STRING; }
 	| T_DEF_TRISTATE	{ $$ = S_TRISTATE; }
 
 /* if entry */
Documentation/kbuild/kconfig-language.rst +12 -1
index d9338407c1c6..00402d43e0dc 100644
@@ -113,11 +113,22 @@ applicable everywhere (see syntax).
 
 - type definition + default value::
 
-	"def_bool"/"def_tristate" <expr> ["if" <expr>]
+	"def_bool" <expr> ["if" <expr>]
+	"def_tristate" <expr> ["if" <expr>]
+	"def_string" <expr> ["if" <expr>]
+	"def_int" <expr> ["if" <expr>]
+	"def_hex" <expr> ["if" <expr>]
 
   This is a shorthand notation for a type definition plus a value.
   Optionally dependencies for this default value can be added with "if".
 
+  The shorthand supplies the type once, and is otherwise an ordinary
+  default: it is the first entry of the list described above, so any
+  further "default" entries still apply when its "if" is not met. Since
+  that leaves the type definition inside one arm of a list, spelling the
+  type out on its own line reads better for a symbol with several
+  defaults.
+
 - dependencies: "depends on" <expr> ["if" <expr>]
 
   This defines a dependency for this menu entry. If multiple
Signature · 1 line
2.34.1
reviewer Tested-by Reviewed-by on v1 1/3
#2 lore raw

Re: [PATCH 1/3] kconfig: Add "def_string", "def_int" and "def_hex"

Hi Kees,

Quoted 3 lines · Kees Cook

Kconfig has offered "def_bool" and "def_tristate" as a shorthand for a type definition plus a default since before the git era, but has never offered the equivalent for the other three types. Conor Dooley ran into

CC'd Conor.

Quoted 11 lines

this gap[1] when fixing a symbol that had been given the wrong type:

Unfortunately, there is no such thing as "def_string", but in this case we can use "default" to propagate the value of ...

Nothing in the grammar requires the restriction. The rule that consumes a default is already type agnostic. Add the three missing types. No changes are needed to existing diagnostics. E.g. declaring a symbol "bool" and then assigning it with "def_string" still reports

warning: ignoring type redefinition of 'CONFLICT' from 'bool' to 'string'

I like this change, as the Kconfiglib implementation of Kconfig used by Zephyr already extended the language to add this [1], so it unifies the ecosystem a bit.

But... I must say that I think def_bool / def_tristate is possibly the worst part of the language. First, because the condition only applies to a part of the statement (unintuitive). For example:

def_bool 'y' if X

the X condition here only applies to the value of y, but not to the type declaration of bool. Besides hurting readability, I can imagine a user making a mistake by attempting something like this:

def_bool 'y' if X
def_tristate 'y' if !X

thinking that they're making the type conditional. Of course, the interpreter warns if this is attempted, so you won't actually find any of these in the tree.

The second problem, is that since the order of defaults matters and conditions can shadow each other, def_<type> makes it harder for users to get defaults right. In the past, I've seen several config options with bugged defaults due to 'default' + 'def_<type>' [2][3][4].

Yet, all this adds for users, is avoiding typing four letters: "ault".

But since this def_bool / def_tristate is already used *everywhere* throughout the tree, I don't think it's realistic to remove it, and would be better to support the other types.

Quoted 8 lines

Added tests for the types.

Build tested ARCH=x86_64 with GCC 16.2.0. Tests pass with "make testconfig".

Quoted 128 lines

---
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Julian Braha <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Cc: Shuah Khan <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Masahiro Yamada <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Nicolas Pitre <[email protected]>
Cc: Krzysztof Kozlowski <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Andrew Jones <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>

---
 scripts/kconfig/tests/def_type/Kconfig        | 28 +++++++++++++++++++
 scripts/kconfig/tests/def_type/guard_n.config |  1 +
 scripts/kconfig/tests/def_type/guard_y.config |  1 +
 scripts/kconfig/tests/def_type/__init__.py    | 18 ++++++++++++
 .../kconfig/tests/def_type/expected_guard_n   |  9 ++++++
 .../kconfig/tests/def_type/expected_guard_y   | 11 ++++++++
 scripts/kconfig/kconfig-sym-check.pl          |  2 +-
 scripts/kconfig/lexer.l                       |  3 ++
 scripts/kconfig/parser.y                      |  6 ++++
 Documentation/kbuild/kconfig-language.rst     | 13 ++++++++-
 10 files changed, 90 insertions(+), 2 deletions(-)
 create mode 100644 scripts/kconfig/tests/def_type/Kconfig
 create mode 100644 scripts/kconfig/tests/def_type/guard_n.config
 create mode 100644 scripts/kconfig/tests/def_type/guard_y.config
 create mode 100644 scripts/kconfig/tests/def_type/__init__.py
 create mode 100644 scripts/kconfig/tests/def_type/expected_guard_n
 create mode 100644 scripts/kconfig/tests/def_type/expected_guard_y
scripts/kconfig/tests/def_type/Kconfig new file +28 -0
new file mode 100644
index 000000000000..fbee37a63179
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0
+# The def_<type> shorthands: a type definition plus a default value.
+
+config MODULES
+	bool "Enable loadable module support"
+	modules
+	default y
+
+config GUARD
+	bool "Guard symbol"
+
+config DEF_BOOL
+	def_bool GUARD
+
+config DEF_TRISTATE
+	def_tristate m if GUARD
+
+config DEF_STRING
+	def_string "guarded" if GUARD
+	default "fallback"
+
+config DEF_INT
+	def_int 64 if GUARD
+	default 32
+
+config DEF_HEX
+	def_hex 0xdead if GUARD
+	default 0x0
scripts/kconfig/tests/def_type/guard_n.config new file +1 -0
new file mode 100644
index 000000000000..ed9ad6c1a2d4
@@ -0,0 +1 @@
+# CONFIG_GUARD is not set
scripts/kconfig/tests/def_type/guard_y.config new file +1 -0
new file mode 100644
index 000000000000..afe35b084542
@@ -0,0 +1 @@
+CONFIG_GUARD=y
scripts/kconfig/tests/def_type/__init__.py new file +18 -0
new file mode 100644
index 000000000000..1ebaf5da07c8
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Set a symbol's type and its default value in one line.
+
+"def_bool", "def_tristate", "def_string", "def_int" and "def_hex" are
+shorthand for a type definition plus a "default" property.  Check that
+each one sets the type, and that an "if" on the shorthand does not
+disturb the usual default cascade: the shorthand is only the first arm
+of the list, so a later "default" still applies when its condition is
+not met.
+"""
+
+def test(conf):
+    assert conf.olddefconfig(dot_config='guard_y.config') == 0
+    assert conf.config_matches('expected_guard_y')
+
+    assert conf.olddefconfig(dot_config='guard_n.config') == 0
+    assert conf.config_matches('expected_guard_n')
scripts/kconfig/tests/def_type/expected_guard_n new file +9 -0
new file mode 100644
index 000000000000..14719720a8b9
@@ -0,0 +1,9 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+CONFIG_MODULES=y
+# CONFIG_GUARD is not set
+CONFIG_DEF_STRING="fallback"
+CONFIG_DEF_INT=32
+CONFIG_DEF_HEX=0x0
scripts/kconfig/tests/def_type/expected_guard_y new file +1 -0
new file mode 100644
index 000000000000..b2844072d0b8
@@ -0,0 +1,11 @@
+#

scripts/kconfig/tests/def_type/expected_guard_y line 11

Quoted 10 lines
scripts/kconfig/tests/def_type/expected_guard_y new file +10 -0
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+CONFIG_MODULES=y
+CONFIG_GUARD=y
+CONFIG_DEF_BOOL=y
+CONFIG_DEF_TRISTATE=m
+CONFIG_DEF_STRING="guarded"
+CONFIG_DEF_INT=64
+CONFIG_DEF_HEX=0xdead

The added test is great.

Quoted 69 lines
scripts/kconfig/kconfig-sym-check.pl +1 -1
index daa5285fdefc..c8dd07f8b27c 100755
@@ -90,7 +90,7 @@ foreach my $file (@files) {
 			next;
 		}
 
-		if (/^\s*(default|def_bool|def_tristate|select|depends\s+on|imply|visible\s+if|range|if|bool|tristate|int|hex|string|prompt)\s+(.+)\s*$/) {
+		if (/^\s*(default|def_bool|def_tristate|def_string|def_int|def_hex|select|depends\s+on|imply|visible\s+if|range|if|bool|tristate|int|hex|string|prompt)\s+(.+)\s*$/) {
 			my $s = $2;
 			$s =~ s/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'//g;
 			$s =~ s/#.*//;
scripts/kconfig/lexer.l +3 -0
index a6155422b4a6..1fa521199d4a 100644
@@ -105,6 +105,9 @@ n	[A-Za-z0-9_-]
 "comment"		return T_COMMENT;
 "config"		return T_CONFIG;
 "def_bool"		return T_DEF_BOOL;
+"def_hex"		return T_DEF_HEX;
+"def_int"		return T_DEF_INT;
+"def_string"		return T_DEF_STRING;
 "def_tristate"		return T_DEF_TRISTATE;
 "default"		return T_DEFAULT;
 "depends"		return T_DEPENDS;
scripts/kconfig/parser.y +6 -0
index 5fb6f07b6ad2..2174baf2b3fd 100644
@@ -53,6 +53,9 @@ struct menu *current_menu, *current_entry, *current_choice;
 %token T_CONFIG
 %token T_DEFAULT
 %token T_DEF_BOOL
+%token T_DEF_HEX
+%token T_DEF_INT
+%token T_DEF_STRING
 %token T_DEF_TRISTATE
 %token T_DEPENDS
 %token T_ENDCHOICE
@@ -309,6 +312,9 @@ type:
 default:
 	  T_DEFAULT		{ $$ = S_UNKNOWN; }
 	| T_DEF_BOOL		{ $$ = S_BOOLEAN; }
+	| T_DEF_HEX		{ $$ = S_HEX; }
+	| T_DEF_INT		{ $$ = S_INT; }
+	| T_DEF_STRING		{ $$ = S_STRING; }
 	| T_DEF_TRISTATE	{ $$ = S_TRISTATE; }
 
 /* if entry */
Documentation/kbuild/kconfig-language.rst +5 -1
index d9338407c1c6..00402d43e0dc 100644
@@ -113,11 +113,22 @@ applicable everywhere (see syntax).
 
 - type definition + default value::
 
-	"def_bool"/"def_tristate" <expr> ["if" <expr>]
+	"def_bool" <expr> ["if" <expr>]
+	"def_tristate" <expr> ["if" <expr>]
+	"def_string" <expr> ["if" <expr>]
+	"def_int" <expr> ["if" <expr>]
+	"def_hex" <expr> ["if" <expr>]
 
   This is a shorthand notation for a type definition plus a value.
   Optionally dependencies for this default value can be added with "if".
 

Documentation/kbuild/kconfig-language.rst applicable everywhere (see syntax). · line 134

Quoted 10 lines
Documentation/kbuild/kconfig-language.rst +7 -0
+  The shorthand supplies the type once, and is otherwise an ordinary
+  default: it is the first entry of the list described above, so any
+  further "default" entries still apply when its "if" is not met. Since
+  that leaves the type definition inside one arm of a list, spelling the
+  type out on its own line reads better for a symbol with several
+  defaults.
+
 - dependencies: "depends on" <expr> ["if" <expr>]
 
   This defines a dependency for this menu entry. If multiple

[1] https://docs.zephyrproject.org/latest/build/kconfig/extensions.html
[2]
https://lore.kernel.org/all/[email protected]/
[3]
https://lore.kernel.org/all/[email protected]/
[4]
https://lore.kernel.org/linux-s390/[email protected]/

- Julian Braha

author
#3 lore raw

Re: [PATCH 1/3] kconfig: Add "def_string", "def_int" and "def_hex"

Quoted 6 lines · Julian Braha

On 9/19/26 01:59, Kees Cook wrote:
[...]
the X condition here only applies to the value of y, but not to the type declaration of bool. Besides hurting readability, I can imagine a user making a mistake by attempting something like this:

Quoted 6 lines

def_bool 'y' if X
def_tristate 'y' if !X

thinking that they're making the type conditional. Of course, the interpreter warns if this is attempted, so you won't actually find any of these in the tree.

Yeah, _this_ case is warned on, so no real issue there.

Quoted 4 lines

The second problem, is that since the order of defaults matters and conditions can shadow each other, def_<type> makes it harder for users to get defaults right. In the past, I've seen several config options with bugged defaults due to 'default' + 'def_<type>' [2][3][4].

This is the one I, too, got worried about. From your example:

config GUEST_STATE_BUFFER_TEST
- def_tristate n
+ def_tristate KUNIT_ALL_TESTS
prompt "Enable Guest State Buffer unit tests" depends on KUNIT
depends on KVM_BOOK3S_HV_POSSIBLE
- default KUNIT_ALL_TESTS
help

Is there a way to detect this state? (I assume as a follow-up; it's a general problem.)

Quoted 4 lines
Quoted 1 line

Thanks!

Signature · 1 line
Kees Cook
reviewer
#4 lore raw

Re: [PATCH 1/3] kconfig: Add "def_string", "def_int" and "def_hex"

Quoted 16 lines · Kees Cook
Quoted 4 lines

The second problem, is that since the order of defaults matters and conditions can shadow each other, def_<type> makes it harder for users to get defaults right. In the past, I've seen several config options with bugged defaults due to 'default' + 'def_<type>' [2][3][4].

This is the one I, too, got worried about. From your example:

config GUEST_STATE_BUFFER_TEST

(quoted diff) +1 -2
-	def_tristate n
+	def_tristate KUNIT_ALL_TESTS
 	prompt "Enable Guest State Buffer unit tests"
 	depends on KUNIT
 	depends on KVM_BOOK3S_HV_POSSIBLE
-	default KUNIT_ALL_TESTS
 	help
Quoted 2 lines

Is there a way to detect this state? (I assume as a follow-up; it's a general problem.)

Unfortunately there's no way to avoid some false alarms when checking these due to macros.

Example:

    config TUNE_CPU
        string
        depends on POWERPC64_CPU
        default "-mtune=power10" if $(cc-option,-mtune=power10)
        default "-mtune=power9"  if $(cc-option,-mtune=power9)
        default "-mtune=power8"  if $(cc-option,-mtune=power8)

These macros get evaluated during preprocessing, which is ahead of when the parse tree is finished and analysis can run.

Though a check for it is included in kconfirm (if merged) [1], and I've also been thinking about making this part of an optional KCONFIG_LINT setting, where some false positives could be acceptable.

[1]
https://lore.kernel.org/all/[email protected]/

- Julian Braha

author
#5 lore raw

PATCH 2/3 kconfig: Replace "cc-option-bit" with "cc-option-str"

In reply to Kees Cook

$(cc-option-bit) returns the flag it was given when the compiler accepts it, and an empty string otherwise. It was originally only used internally for machine bit flags, but it is generally useful[1].

Rename it to $(cc-option-str), which says what it returns rather than what it was first used for, and extract the probe logic from the existing $(cc-option) macro to reuse it. Additionally add support for an optional fallback, much like the Kbuild cc-option macro. This can be used as:

	config CC_OPT_FOO
		def_string "$(cc-option-str,-fnew-option,-fold-option)"

If the fallback is omitted, it is just an empty string.

Build tested ARCH=x86_64 defconfig with GCC 16.2.0.

Assisted-by LLM

---
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Julian Braha <[email protected]>
Cc: Matthew Maurer <[email protected]>
Cc: Miguel Ojeda <[email protected]>
Cc: Masahiro Yamada <[email protected]>
Cc: "Borislav Petkov (AMD)" <[email protected]>
Cc: Gary Guo <[email protected]>
Cc: "Thomas Weißschuh" <[email protected]>
Cc: <[email protected]>

---
 scripts/Kconfig.include | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
scripts/Kconfig.include +13 -4
index fc10671c297c..4ef2b64e97be 100644
@@ -23,9 +23,19 @@ success = $(if-success,$(1),y,n)
 # Return n if <command> exits with 0, y otherwise
 failure = $(if-success,$(1),n,y)
 
+# $(cc-probe,<flag>)
+# The command $(cc-option) and $(cc-option-str) test <flag> with. Not meant
+# to be called directly; use one of those two instead.
+cc-probe = trap "rm -rf .tmp_$$" EXIT; mkdir .tmp_$$; $(CC) -Werror $(CLANG_FLAGS) $(1) -c -x c /dev/null -o .tmp_$$/tmp.o
+
 # $(cc-option,<flag>)
 # Return y if the compiler supports <flag>, n otherwise
-cc-option = $(success,trap "rm -rf .tmp_$$" EXIT; mkdir .tmp_$$; $(CC) -Werror $(CLANG_FLAGS) $(1) -c -x c /dev/null -o .tmp_$$/tmp.o)
+cc-option = $(success,$(cc-probe,$(1)))
+
+# $(cc-option-str,<flag>[,<fallback>])
+# Return <flag> if the compiler supports it, <fallback> otherwise.
+# <fallback> defaults to an empty string and is returned untested.
+cc-option-str = $(if-success,$(cc-probe,$(1)),$(1),$(2))
 
 # $(ld-option,<flag>)
 # Return y if the linker supports <flag>, n otherwise
@@ -61,9 +71,8 @@ ld-version := $(shell,set -- $(ld-info) && echo $2)
 # machine bit flags
 #  $(m32-flag): -m32 if the compiler supports it, or an empty string otherwise.
 #  $(m64-flag): -m64 if the compiler supports it, or an empty string otherwise.
-cc-option-bit = $(if-success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null,$(1))
-m32-flag := $(cc-option-bit,-m32)
-m64-flag := $(cc-option-bit,-m64)
+m32-flag := $(cc-option-str,-m32)
+m64-flag := $(cc-option-str,-m64)
 
 # Test whether the compiler can link userspace applications
 cc_can_link_user = $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(1))
Signature · 1 line
2.34.1
reviewer Tested-by Reviewed-by on v1 2/3
#6 lore raw

Re: [PATCH 2/3] kconfig: Replace "cc-option-bit" with "cc-option-str"

Quoted 12 lines · Kees Cook

$(cc-option-bit) returns the flag it was given when the compiler accepts it, and an empty string otherwise. It was originally only used internally for machine bit flags, but it is generally useful[1].

Rename it to $(cc-option-str), which says what it returns rather than what it was first used for, and extract the probe logic from the existing $(cc-option) macro to reuse it. Additionally add support for an optional fallback, much like the Kbuild cc-option macro. This can be used as:

	config CC_OPT_FOO
		def_string "$(cc-option-str,-fnew-option,-fold-option)"
Quoted 6 lines

If the fallback is omitted, it is just an empty string.

Build tested ARCH=x86_64 defconfig with GCC 16.2.0.

Assisted-by LLM
author
#7 lore raw

PATCH 3/3 kconfig: Add "ld-option-str"

In reply to Kees Cook

Add the linker counterpart to $(cc-option-str), sharing a $(ld-probe) with $(ld-option) the way the compiler macros share $(cc-probe). Like $(cc-option-str), it can now be used as:

	config LD_OPT_FOO
		def_string "$(ld-option-str,--new-option,--old-option)"

An omitted fallback expands to the empty string.

Build tested ARCH=x86_64 defconfig with GCC 16.2.0, and checked against GNU ld 2.47.

Assisted-by LLM

---
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Julian Braha <[email protected]>
Cc: Matthew Maurer <[email protected]>
Cc: Masahiro Yamada <[email protected]>
Cc: Miguel Ojeda <[email protected]>
Cc: "Thomas Weißschuh" <[email protected]>
Cc: Gary Guo <[email protected]>
Cc: <[email protected]>

---
 scripts/Kconfig.include | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
scripts/Kconfig.include +11 -1
index 4ef2b64e97be..622d21e6953f 100644
@@ -37,9 +37,19 @@ cc-option = $(success,$(cc-probe,$(1)))
 # <fallback> defaults to an empty string and is returned untested.
 cc-option-str = $(if-success,$(cc-probe,$(1)),$(1),$(2))
 
+# $(ld-probe,<flag>)
+# The command $(ld-option) and $(ld-option-str) test <flag> with. Not meant
+# to be called directly; use one of those two instead.
+ld-probe = $(LD) -v $(1)
+
 # $(ld-option,<flag>)
 # Return y if the linker supports <flag>, n otherwise
-ld-option = $(success,$(LD) -v $(1))
+ld-option = $(success,$(ld-probe,$(1)))
+
+# $(ld-option-str,<flag>[,<fallback>])
+# Return <flag> if the linker supports it, <fallback> otherwise.
+# <fallback> defaults to an empty string and is returned untested.
+ld-option-str = $(if-success,$(ld-probe,$(1)),$(1),$(2))
 
 # $(as-instr,<instr>)
 # Return y if the assembler supports <instr>, n otherwise
Signature · 1 line
2.34.1
reviewer Tested-by Reviewed-by on v1 3/3
#8 lore raw

Re: [PATCH 3/3] kconfig: Add "ld-option-str"

Quoted 7 lines · Kees Cook

Add the linker counterpart to $(cc-option-str), sharing a $(ld-probe) with $(ld-option) the way the compiler macros share $(cc-probe). Like $(cc-option-str), it can now be used as:

	config LD_OPT_FOO
		def_string "$(ld-option-str,--new-option,--old-option)"
Quoted 7 lines

An omitted fallback expands to the empty string.

Build tested ARCH=x86_64 defconfig with GCC 16.2.0, and checked against GNU ld 2.47.

Assisted-by LLM
#9 lore raw
In reply to Kees Cook
Quoted 7 lines · Kees Cook

Hi,

While reviewing the recent build speedup series[1], it became clear that we needed a general solution in kconfig to avoid repeating detected toolchain options. Implement cc-option-str and ld-option-str, and while at it, create "def_string" and friends to match "def_bool".

Quoted 8 lines

-Kees

[1] https://lore.kernel.org/all/20260918054058.GA384222@ax162/

Kees Cook (3):
kconfig: Add "def_string", "def_int" and "def_hex"
kconfig: Replace "cc-option-bit" with "cc-option-str"
kconfig: Add "ld-option-str"

Thanks, exactly what I had in mind. This seems reasonable to me and passes my basic testing. I will let folks chime in for a few days then apply this to kbuild-next so that Lorenzo can use it as part of the speed up series.

Signature · 2 lines
Cheers,
Nathan
#10 lore raw
Quoted 17 lines · Nathan Chancellor
Quoted 7 lines · Kees Cook

Hi,

While reviewing the recent build speedup series[1], it became clear that we needed a general solution in kconfig to avoid repeating detected toolchain options. Implement cc-option-str and ld-option-str, and while at it, create "def_string" and friends to match "def_bool".

Quoted 8 lines

-Kees

[1] https://lore.kernel.org/all/20260918054058.GA384222@ax162/

Kees Cook (3):
kconfig: Add "def_string", "def_int" and "def_hex"
kconfig: Replace "cc-option-bit" with "cc-option-str"
kconfig: Add "ld-option-str"

Quoted 4 lines

Thanks, exactly what I had in mind. This seems reasonable to me and passes my basic testing. I will let folks chime in for a few days then apply this to kbuild-next so that Lorenzo can use it as part of the speed up series.

Agreed, I will base my local v4 on it and send that (obviously once I've gone through review commentary etc.) once things have settled and rebase the series on kbuild-next!

since I sent v3 on thurs I'll likely aim for weds/thurs next week for v4 but I'll wait until this series is in place before I do it obviously! :)

Quoted 4 lines

--
Cheers,
Nathan

--
Cheers, Lorenzo

#11 lore raw
In reply to Kees Cook
Quoted 10 lines · Kees Cook

kconfig: Introduce cc-option-str

Hi,

While reviewing the recent build speedup series[1], it became clear that we needed a general solution in kconfig to avoid repeating detected toolchain options. Implement cc-option-str and ld-option-str, and while at it, create "def_string" and friends to match "def_bool".

[...]

Applied to

https://git.kernel.org/pub/scm/linux/kernel/git/kbuild/linux.git kbuild-next-unstable

Thanks!

[1/3] kconfig: Add "def_string", "def_int" and "def_hex"

      https://git.kernel.org/kbuild/c/651fb291c4c86
[2/3] kconfig: Replace "cc-option-bit" with "cc-option-str"
      https://git.kernel.org/kbuild/c/889a621272f9b
[3/3] kconfig: Add "ld-option-str"
      https://git.kernel.org/kbuild/c/cfcc465018818

Please look out for regression or issue reports or other follow up comments, as they may result in the patch/series getting dropped or reverted. Patches applied to an "unstable" branch are accepted pending wider testing in -next and any post-commit review; they will generally be moved to the main branch in a week if no issues are found.

Best regards,

Signature · 2 lines
Cheers,
Nathan