Skip to content

Commit ced27d6

Browse files
committed
Add Kbuild toolchain test functions support
This implements 9 Kbuild preprocessor functions for toolchain capability detection, enabling parsing of modern Linux kernel Kconfig files (since version 4.18): - success/failure/if-success: Shell command result testing - cc-option/cc-option-bit: C compiler flag support detection - ld-option: Linker option support detection - as-instr/as-option: Assembler capability detection - rustc-option: Rust compiler option detection This resolves parsing errors when processing kernel Kconfig files that use toolchain detection macros like \$(as-instr,tpause %ecx) and nested function calls like \$(success,test -z "\$(shell,...)").
1 parent d82d17a commit ced27d6

File tree

4 files changed

+531
-0
lines changed

4 files changed

+531
-0
lines changed

KBUILD.md

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# Kbuild Toolchain Functions
2+
3+
Kconfiglib implements Kbuild toolchain detection functions used by the Linux kernel since version 4.18.
4+
These preprocessor functions enable runtime detection of compiler, assembler, and linker capabilities,
5+
allowing kernel configurations to adapt to different toolchain versions.
6+
7+
## Background
8+
9+
The [Kconfig preprocessor](https://docs.kernel.org/kbuild/kconfig-macro-language.html) introduced
10+
in Linux 4.18 provides functions for toolchain capability detection. These are defined in
11+
`scripts/Kconfig.include` and enable conditional configuration based on available toolchain features.
12+
13+
For comprehensive Kconfig syntax documentation, see the
14+
[Kconfig Language](https://docs.kernel.org/kbuild/kconfig-language.html) specification.
15+
16+
## Implemented Functions
17+
18+
### Control Flow
19+
20+
`$(if-success,command,then-val,else-val)`
21+
: Executes command via shell; returns `then-val` on success (exit 0), `else-val` otherwise.
22+
23+
`$(success,command)`
24+
: Returns `y` if command succeeds, `n` otherwise. Equivalent to `$(if-success,command,y,n)`.
25+
26+
`$(failure,command)`
27+
: Returns `n` if command succeeds, `y` otherwise. Inverse of `success`.
28+
29+
### Compiler Detection
30+
31+
`$(cc-option,flag[,fallback])`
32+
: Tests if C compiler supports a flag. Returns `y` or `n`.
33+
34+
`$(cc-option-bit,flag)`
35+
: Tests if C compiler supports a flag. Returns the flag itself or empty string.
36+
Primarily used in variable assignments.
37+
38+
### Assembler Detection
39+
40+
`$(as-instr,instruction[,extra-flags])`
41+
: Tests if assembler supports a specific instruction. Returns `y` or `n`.
42+
43+
`$(as-option,flag[,fallback])`
44+
: Tests if assembler (via CC) supports a flag. Returns `y` or `n`.
45+
46+
### Linker Detection
47+
48+
`$(ld-option,flag)`
49+
: Tests if linker supports a flag. Returns `y` or `n`.
50+
51+
### Rust Support
52+
53+
`$(rustc-option,flag)`
54+
: Tests if Rust compiler supports a flag. Returns `y` or `n`.
55+
56+
## Usage Examples
57+
58+
### Basic Capability Detection
59+
60+
```
61+
# Compiler feature detection
62+
config CC_HAS_ASM_GOTO
63+
def_bool $(success,$(CC) -Werror -x c /dev/null -S -o /dev/null)
64+
65+
config STACKPROTECTOR
66+
bool "Stack Protector buffer overflow detection"
67+
depends on $(cc-option,-fstack-protector)
68+
```
69+
70+
### Assembler Instruction Detection
71+
72+
```
73+
# x86 instruction set extensions
74+
config AS_TPAUSE
75+
def_bool $(as-instr,tpause %ecx)
76+
help
77+
Requires binutils >= 2.31.1 or LLVM >= 7
78+
79+
config AS_AVX512
80+
def_bool $(as-instr,vpmovm2b %k1$(comma)%zmm5)
81+
```
82+
83+
### Nested Functions
84+
85+
```
86+
# Validate linker availability
87+
ld-info := $(shell,$(LD) --version | head -n1)
88+
$(error-if,$(success,test -z "$(ld-info)"),Linker not supported)
89+
```
90+
91+
### Variable Assignments
92+
93+
```
94+
# Architecture-specific flags
95+
m32-flag := $(cc-option-bit,-m32)
96+
m64-flag := $(cc-option-bit,-m64)
97+
98+
config HAS_32BIT
99+
def_bool "$(m32-flag)" != ""
100+
```
101+
102+
## Implementation
103+
104+
### Design
105+
106+
Functions are implemented in `kconfiglib.py` following these principles:
107+
108+
- Uniform interface through the `_functions` dictionary
109+
- No special-case handling
110+
- Python 2.7+ and 3.2+ compatibility using standard library only
111+
- Graceful error handling (missing tools return `n`)
112+
113+
### Environment Variables
114+
115+
Functions respect standard build variables:
116+
- `CC` (default: `gcc`)
117+
- `LD` (default: `ld`)
118+
- `RUSTC` (default: `rustc`)
119+
120+
### Performance
121+
122+
Functions execute shell commands during Kconfig parsing, which can be slow.
123+
For applications that parse configurations repeatedly, consider implementing
124+
caching or using `allow_empty_macros=True` to skip toolchain detection.
125+
126+
## Testing
127+
128+
Four test suites validate the implementation:
129+
130+
`test_issue111.py`
131+
: Validates basic toolchain function parsing.
132+
133+
`test_issue109.py`
134+
: Tests nested function calls and complex expressions.
135+
136+
`test_kbuild_complete.py`
137+
: Comprehensive suite with 35+ test cases covering all functions, edge cases, and error conditions.
138+
139+
`test_kernel_compat.py`
140+
: Real-world kernel Kconfig snippets from init/Kconfig, arch/x86/Kconfig, etc.
141+
142+
Run all tests:
143+
```bash
144+
python3 test_basic_parsing.py && \
145+
python3 test_issue111.py && \
146+
python3 test_issue109.py && \
147+
python3 test_kbuild_complete.py && \
148+
python3 test_kernel_compat.py
149+
```
150+
151+
## Compatibility
152+
153+
### Kernel Versions
154+
155+
Required for:
156+
- Linux kernel 4.18+
157+
- RHEL 8+, CentOS 8 Stream
158+
- Recent Fedora, Ubuntu, Debian kernels
159+
- Mainline kernel development
160+
161+
### Toolchains
162+
163+
Tested with:
164+
- GCC 9+, Clang 10+
165+
- binutils 2.31+
166+
- rustc 1.60+ (optional)
167+
168+
## Real-World Examples
169+
170+
From `arch/x86/Kconfig.cpu`:
171+
```
172+
config AS_TPAUSE
173+
def_bool $(as-instr,tpause %ecx)
174+
help
175+
Supported by binutils >= 2.31.1 and LLVM >= V7
176+
177+
config AS_SHA1_NI
178+
def_bool $(as-instr,sha1msg1 %xmm0$(comma)%xmm1)
179+
```
180+
181+
From `init/Kconfig`:
182+
```
183+
config CC_HAS_ASM_GOTO
184+
def_bool $(success,$(CC) -Werror -x c /dev/null -S -o /dev/null)
185+
```
186+
187+
From `arch/Kconfig`:
188+
```
189+
config SHADOW_CALL_STACK
190+
bool "Shadow Call Stack"
191+
depends on $(cc-option,-fsanitize=shadow-call-stack -ffixed-x18)
192+
```
193+
194+
## See Also
195+
196+
- [Kconfig Language](https://docs.kernel.org/kbuild/kconfig-language.html) - Complete syntax specification
197+
- [Kconfig Macro Language](https://docs.kernel.org/kbuild/kconfig-macro-language.html) - Preprocessor documentation
198+
- [scripts/Kconfig.include](https://github.com/torvalds/linux/blob/master/scripts/Kconfig.include) - Upstream implementation

0 commit comments

Comments
 (0)