[PATCH v5 01/14] tools build: Fix feature checks to touch target files on success

From: Ian Rogers

Date: Fri May 15 2026 - 15:42:17 EST


In tools/build/feature/Makefile, test-clang-bpf-co-re.bin and
test-bpftool-skeletons.bin redirected grep output but never touched or
created the $@ target file upon success.

Because the target file was never created on disk, Kbuild could never cache
the result of the check. Consequently, Make treated the prerequisite as
missing and continuously re-executed the Clang BPF backend and bpftool
feature checks on every single sub-make evaluation during build startup.

Refactor both feature check recipes to group the shell pipeline within
curly braces and redirect both stdout and stderr to .make.output before
touching $@ purely upon success (> $(@:.bin=.make.output) 2>&1 && touch $@).
Grouping the pipeline ({ cmd1 | cmd2; }) ensures that compiler stderr is
successfully captured in .make.output rather than escaping to the parent
shell. This perfectly matches standard Kbuild feature check conventions,
allowing Make to cache positive detections and avoid redundant sub-make
forks during incremental builds. Add test-bpftool-skeletons.bin to the
FILES list so that make clean correctly purges the generated binary. For
test-clang-bpf-co-re.bin, add explicit source file prerequisite
test-clang-bpf-co-re.c and simplify the Clang recipe using $<.

Tested-by: James Clark <james.clark@xxxxxxxxxx>
Assisted-by: Gemini:gemini-3.1-pro-preview
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/build/feature/Makefile | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 704c687ed3ad..5b4a984973c4 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -75,7 +75,8 @@ FILES= \
test-file-handle.bin \
test-libpfm4.bin \
test-rust.bin \
- test-libopenssl.bin
+ test-libopenssl.bin \
+ test-bpftool-skeletons.bin

FILES := $(addprefix $(OUTPUT),$(FILES))

@@ -383,9 +384,9 @@ $(OUTPUT)test-libaio.bin:
$(OUTPUT)test-libzstd.bin:
$(BUILD) -lzstd

-$(OUTPUT)test-clang-bpf-co-re.bin:
- $(CLANG) -S -g --target=bpf -o - $(patsubst %.bin,%.c,$(@F)) | \
- grep BTF_KIND_VAR
+$(OUTPUT)test-clang-bpf-co-re.bin: test-clang-bpf-co-re.c
+ { $(CLANG) -S -g --target=bpf -o - $< | \
+ grep BTF_KIND_VAR; } > $(@:.bin=.make.output) 2>&1 && touch $@

$(OUTPUT)test-file-handle.bin:
$(BUILD)
@@ -397,8 +398,8 @@ $(OUTPUT)test-libopenssl.bin:
$(BUILD) $(shell $(PKG_CONFIG) --libs --cflags openssl 2>/dev/null)

$(OUTPUT)test-bpftool-skeletons.bin:
- $(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons' \
- > $(@:.bin=.make.output) 2>&1
+ { $(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons'; } \
+ > $(@:.bin=.make.output) 2>&1 && touch $@

# Testing Rust is special: we don't compile anything, it's enough to check the
# compiler presence. Compiling a test code for this purposes is problematic,
--
2.54.0.563.g4f69b47b94-goog