* [PATCH bpf-next v8 1/9] selftests/bpf: keep headers off the generic link command line
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
@ 2026-09-21 7:58 ` Mykola Lysenko
2026-09-21 7:58 ` [PATCH bpf-next v8 2/9] selftests/bpf: drop stale lines, restore two header dependencies Mykola Lysenko
` (9 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 7:58 UTC (permalink / raw)
To: bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko
The generic '$(OUTPUT)/%:%.c' rule links with '$(LINK.c) $^', so every
prerequisite reaches the compiler driver. A header argument makes clang
fail with "cannot specify -o when generating multiple output files".
Filter headers out of the link command while retaining them as
prerequisites.
Signed-off-by: Mykola Lysenko <nickolay.lysenko@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
---
tools/testing/selftests/bpf/Makefile | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 7ea5ba1df29e..bfb788ea6561 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -257,9 +257,11 @@ $(OUTPUT)/%.o: %.c
$(call msg,CC,,$@)
$(Q)$(CC) $(CFLAGS) -c $(filter %.c,$^) $(LDLIBS) -o $@
+# Keep header prerequisites off the link command: clang treats
+# bare headers as precompiled-header jobs and refuses -o.
$(OUTPUT)/%:%.c
$(call msg,BINARY,,$@)
- $(Q)$(LINK.c) $^ $(LDLIBS) -o $@
+ $(Q)$(LINK.c) $(filter-out %.h,$^) $(LDLIBS) -o $@
# LLVM's ld.lld doesn't support all the architectures, so use it only on x86
ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 riscv))
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH bpf-next v8 2/9] selftests/bpf: drop stale lines, restore two header dependencies
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
2026-09-21 7:58 ` [PATCH bpf-next v8 1/9] selftests/bpf: keep headers off the generic link command line Mykola Lysenko
@ 2026-09-21 7:58 ` Mykola Lysenko
2026-09-21 9:06 ` bot+bpf-ci
2026-09-21 7:58 ` [PATCH bpf-next v8 3/9] selftests/bpf: factor the permissive-mode skip suffix into a helper Mykola Lysenko
` (8 subsequent siblings)
10 siblings, 1 reply; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 7:58 UTC (permalink / raw)
To: bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko
Four target-specific lines name objects nothing builds.
Commit afef88e65554 ("selftests/bpf: Store BPF object files with .bpf.o
extension") left three naming the old BPF objects; flow_dissector_load.o
names an intermediate the one-step compile and link rule does not
produce.
The xsk_xdp_progs, xdp_hw_metadata and xdp_features dependency-map
entries are unused: none is listed in LINKED_SKELS, and the regular
skeleton rule does not consult the map.
The test_l4lb_noinline and test_xdp_noinline '-fno-inline' settings had
already stopped taking effect with commit 74b5a5968fe8 ("selftests/bpf:
Replace test_progs and test_maps w/ general rule"). The compile recipe
uses TRUNNER_BPF_CFLAGS, a simply-expanded copy of BPF_CFLAGS that the
target-specific additions cannot affect. The intended functions already
carry noinline annotations; restoring the flag produces byte-identical
objects.
Restore flow_dissector_load.h as a prerequisite of the binary, which is
compiled and linked directly from its .c file. Move
cgroup_getset_retval_hooks.h under progs/, where the BPF rules' blanket
header prerequisite tracks it. Its userspace consumer remains tracked by
compiler-generated dependencies.
Drop the redundant CURDIR assignment and the unused OBJCOPY definition.
Signed-off-by: Mykola Lysenko <nickolay.lysenko@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
---
tools/testing/selftests/bpf/Makefile | 14 +-------------
.../bpf/prog_tests/cgroup_getset_retval.c | 2 +-
.../bpf/{ => progs}/cgroup_getset_retval_hooks.h | 0
3 files changed, 2 insertions(+), 14 deletions(-)
rename tools/testing/selftests/bpf/{ => progs}/cgroup_getset_retval_hooks.h (100%)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index bfb788ea6561..3606ee8ab794 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -3,9 +3,6 @@ include ../../../build/Build.include
include ../../../scripts/Makefile.arch
include ../../../scripts/Makefile.include
-OBJCOPY ?= $(CROSS_COMPILE)objcopy
-
-CURDIR := $(abspath .)
TOOLSDIR := $(abspath ../../..)
LIBDIR := $(TOOLSDIR)/lib
BPFDIR := $(LIBDIR)/bpf
@@ -339,7 +336,7 @@ $(OUTPUT)/test_sockmap: $(CGROUP_HELPERS) $(TESTING_HELPERS)
$(OUTPUT)/test_tcpnotify_user: $(CGROUP_HELPERS) $(TESTING_HELPERS) $(TRACE_HELPERS)
$(OUTPUT)/test_sock_fields: $(CGROUP_HELPERS) $(TESTING_HELPERS)
$(OUTPUT)/test_tag: $(TESTING_HELPERS)
-$(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS)
+$(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS) flow_dissector_load.h
$(OUTPUT)/test_maps: $(TESTING_HELPERS)
$(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS) $(UNPRIV_HELPERS)
$(OUTPUT)/xsk.o: $(BPFOBJ)
@@ -477,12 +474,6 @@ BPF_CFLAGS = -g -Wall -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) \
CLANG_CFLAGS = $(CLANG_SYS_INCLUDES)
-$(OUTPUT)/test_l4lb_noinline.o: BPF_CFLAGS += -fno-inline
-$(OUTPUT)/test_xdp_noinline.o: BPF_CFLAGS += -fno-inline
-
-$(OUTPUT)/flow_dissector_load.o: flow_dissector_load.h
-$(OUTPUT)/cgroup_getset_retval_hooks.o: cgroup_getset_retval_hooks.h
-
# Build BPF object using Clang
# $1 - input .c file
# $2 - output .o file
@@ -543,9 +534,6 @@ linked_maps.skel.h-deps := linked_maps1.bpf.o linked_maps2.bpf.o
test_subskeleton.skel.h-deps := test_subskeleton_lib2.bpf.o test_subskeleton_lib.bpf.o test_subskeleton.bpf.o
test_subskeleton_lib.skel.h-deps := test_subskeleton_lib2.bpf.o test_subskeleton_lib.bpf.o
test_usdt.skel.h-deps := test_usdt.bpf.o test_usdt_multispec.bpf.o
-xsk_xdp_progs.skel.h-deps := xsk_xdp_progs.bpf.o
-xdp_hw_metadata.skel.h-deps := xdp_hw_metadata.bpf.o
-xdp_features.skel.h-deps := xdp_features.bpf.o
tracing_multi.skel.h-deps := tracing_multi_attach.bpf.o tracing_multi_check.bpf.o
tracing_multi_module.skel.h-deps := tracing_multi_attach_module.bpf.o tracing_multi_check.bpf.o
tracing_multi_intersect.skel.h-deps := tracing_multi_intersect_attach.bpf.o tracing_multi_check.bpf.o
diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup_getset_retval.c b/tools/testing/selftests/bpf/prog_tests/cgroup_getset_retval.c
index 2bb5773d6f99..ea342859d6ce 100644
--- a/tools/testing/selftests/bpf/prog_tests/cgroup_getset_retval.c
+++ b/tools/testing/selftests/bpf/prog_tests/cgroup_getset_retval.c
@@ -465,7 +465,7 @@ struct exposed_hook {
.expected_err = EXPECTED_ERR, \
},
-#include "cgroup_getset_retval_hooks.h"
+#include "progs/cgroup_getset_retval_hooks.h"
#undef BPF_RETVAL_HOOK
};
diff --git a/tools/testing/selftests/bpf/cgroup_getset_retval_hooks.h b/tools/testing/selftests/bpf/progs/cgroup_getset_retval_hooks.h
similarity index 100%
rename from tools/testing/selftests/bpf/cgroup_getset_retval_hooks.h
rename to tools/testing/selftests/bpf/progs/cgroup_getset_retval_hooks.h
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH bpf-next v8 2/9] selftests/bpf: drop stale lines, restore two header dependencies
2026-09-21 7:58 ` [PATCH bpf-next v8 2/9] selftests/bpf: drop stale lines, restore two header dependencies Mykola Lysenko
@ 2026-09-21 9:06 ` bot+bpf-ci
2026-09-21 9:21 ` Mykola Lysenko
0 siblings, 1 reply; 19+ messages in thread
From: bot+bpf-ci @ 2026-09-21 9:06 UTC (permalink / raw)
To: nickolay.lysenko, bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko, ast, andrii, daniel, martin.lau,
eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1431 bytes --]
> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> index bfb788ea65618..3606ee8ab7949 100644
> --- a/tools/testing/selftests/bpf/Makefile
> +++ b/tools/testing/selftests/bpf/Makefile
[ ... ]
> @@ -339,7 +336,7 @@ $(OUTPUT)/test_sockmap: $(CGROUP_HELPERS) $(TESTING_HELPERS)
> $(OUTPUT)/test_tcpnotify_user: $(CGROUP_HELPERS) $(TESTING_HELPERS) $(TRACE_HELPERS)
> $(OUTPUT)/test_sock_fields: $(CGROUP_HELPERS) $(TESTING_HELPERS)
> $(OUTPUT)/test_tag: $(TESTING_HELPERS)
> -$(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS)
> +$(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS) flow_dissector_load.h
^^^^^^^^^^^^^^^^^^^^
> $(OUTPUT)/test_maps: $(TESTING_HELPERS)
> $(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS) $(UNPRIV_HELPERS)
> $(OUTPUT)/xsk.o: $(BPFOBJ)
This isn't a bug, but since the patch is already retiring the stale
references to flow_dissector_load.h, would it make sense to drop the
TRUNNER_EXTRA_SOURCES entry in the same go? Only flow_dissector_load.c
seems to include the header now, and that binary gets its dependency from
the line restored above.
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/35577680350
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH bpf-next v8 2/9] selftests/bpf: drop stale lines, restore two header dependencies
2026-09-21 9:06 ` bot+bpf-ci
@ 2026-09-21 9:21 ` Mykola Lysenko
0 siblings, 0 replies; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 9:21 UTC (permalink / raw)
To: bot+bpf-ci
Cc: bpf, ast, daniel, andrii, eddyz87, martin.lau, song,
yonghong.song, jolsa, memxor, martin.lau, mason, ihor.solodrai
On Mon, Sep 21, 2026 at 11:06 AM <bot+bpf-ci@kernel.org> wrote:
>
> > diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> > index bfb788ea65618..3606ee8ab7949 100644
> > --- a/tools/testing/selftests/bpf/Makefile
> > +++ b/tools/testing/selftests/bpf/Makefile
>
> [ ... ]
>
> > @@ -339,7 +336,7 @@ $(OUTPUT)/test_sockmap: $(CGROUP_HELPERS) $(TESTING_HELPERS)
> > $(OUTPUT)/test_tcpnotify_user: $(CGROUP_HELPERS) $(TESTING_HELPERS) $(TRACE_HELPERS)
> > $(OUTPUT)/test_sock_fields: $(CGROUP_HELPERS) $(TESTING_HELPERS)
> > $(OUTPUT)/test_tag: $(TESTING_HELPERS)
> > -$(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS)
> > +$(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS) flow_dissector_load.h
> ^^^^^^^^^^^^^^^^^^^^
> > $(OUTPUT)/test_maps: $(TESTING_HELPERS)
> > $(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS) $(UNPRIV_HELPERS)
> > $(OUTPUT)/xsk.o: $(BPFOBJ)
>
> This isn't a bug, but since the patch is already retiring the stale
> references to flow_dissector_load.h, would it make sense to drop the
> TRUNNER_EXTRA_SOURCES entry in the same go? Only flow_dissector_load.c
> seems to include the header now, and that binary gets its dependency from
> the line restored above.
Thanks. Patch 9 removes TRUNNER_EXTRA_SOURCES entirely, including the
flow_dissector_load.h entry. The dependency added here on the
flow_dissector_load binary remains. I would leave that cleanup in patch 9,
together with the runner restructuring.
>
> [ ... ]
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/35577680350
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH bpf-next v8 3/9] selftests/bpf: factor the permissive-mode skip suffix into a helper
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
2026-09-21 7:58 ` [PATCH bpf-next v8 1/9] selftests/bpf: keep headers off the generic link command line Mykola Lysenko
2026-09-21 7:58 ` [PATCH bpf-next v8 2/9] selftests/bpf: drop stale lines, restore two header dependencies Mykola Lysenko
@ 2026-09-21 7:58 ` Mykola Lysenko
2026-09-21 8:09 ` sashiko-bot
2026-09-21 7:58 ` [PATCH bpf-next v8 4/9] selftests/bpf: generate the signing key and certificate once Mykola Lysenko
` (7 subsequent siblings)
10 siblings, 1 reply; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 7:58 UTC (permalink / raw)
To: bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko
With BPF_STRICT_BUILD=0, eleven recipes append the same "|| { remove the
target, print a SKIP marker, report success }" tail, each spelled out
inline. Factor the tail into skip_on_fail; every call site keeps its
exact message and behavior.
Signed-off-by: Mykola Lysenko <nickolay.lysenko@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
---
tools/testing/selftests/bpf/Makefile | 49 +++++++++++-----------------
1 file changed, 19 insertions(+), 30 deletions(-)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 3606ee8ab794..11bd8997aea5 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -46,6 +46,14 @@ SKIP_CRYPTO ?=
BPF_STRICT_BUILD ?= 1
PERMISSIVE := $(filter 0,$(BPF_STRICT_BUILD))
+# Permissive-mode recipe suffix: on failure, remove the target, emit a
+# SKIP marker and report success so the rest of the build continues.
+# $(1) - SKIP tag (BPF, TEST, BENCH, SKEL, LINK, ...)
+# $(2) - optional extra files to remove alongside the target
+# $(3) - optional note appended to the SKIP message
+skip_on_fail = $(if $(PERMISSIVE),|| { $(RM) $@ $(2); \
+ printf ' %-12s %s\n' 'SKIP-$(1)' '$(notdir $@)$(if $(3), $(3))' 1>&2; })
+
ifeq ($(srctree),)
srctree := $(patsubst %/,%,$(dir $(CURDIR)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
@@ -481,26 +489,22 @@ CLANG_CFLAGS = $(CLANG_SYS_INCLUDES)
# $4 - binary name
define CLANG_BPF_BUILD_RULE
$(call msg,CLNG-BPF,$4,$2)
- $(Q)$(CLANG) $3 -O2 $(BPF_TARGET_ENDIAN) -c $1 -mcpu=v3 -o $2 $(if $(PERMISSIVE),|| \
- ($(RM) $2; printf ' %-12s %s\n' 'SKIP-BPF' '$(notdir $2)' 1>&2))
+ $(Q)$(CLANG) $3 -O2 $(BPF_TARGET_ENDIAN) -c $1 -mcpu=v3 -o $2 $(call skip_on_fail,BPF)
endef
# Similar to CLANG_BPF_BUILD_RULE, but with disabled alu32
define CLANG_NOALU32_BPF_BUILD_RULE
$(call msg,CLNG-BPF,$4,$2)
- $(Q)$(CLANG) $3 -O2 $(BPF_TARGET_ENDIAN) -c $1 -mcpu=v2 -o $2 $(if $(PERMISSIVE),|| \
- ($(RM) $2; printf ' %-12s %s\n' 'SKIP-BPF' '$(notdir $2)' 1>&2))
+ $(Q)$(CLANG) $3 -O2 $(BPF_TARGET_ENDIAN) -c $1 -mcpu=v2 -o $2 $(call skip_on_fail,BPF)
endef
# Similar to CLANG_BPF_BUILD_RULE, but with cpu-v4
define CLANG_CPUV4_BPF_BUILD_RULE
$(call msg,CLNG-BPF,$4,$2)
- $(Q)$(CLANG) $3 -O2 $(BPF_TARGET_ENDIAN) -c $1 -mcpu=v4 -o $2 $(if $(PERMISSIVE),|| \
- ($(RM) $2; printf ' %-12s %s\n' 'SKIP-BPF' '$(notdir $2)' 1>&2))
+ $(Q)$(CLANG) $3 -O2 $(BPF_TARGET_ENDIAN) -c $1 -mcpu=v4 -o $2 $(call skip_on_fail,BPF)
endef
# Build BPF object using GCC
define GCC_BPF_BUILD_RULE
$(call msg,GCC-BPF,$4,$2)
- $(Q)$(BPF_GCC) $3 -DBPF_NO_PRESERVE_ACCESS_INDEX -Wno-attributes -O2 -c $1 -o $2 $(if $(PERMISSIVE),|| \
- ($(RM) $2; printf ' %-12s %s\n' 'SKIP-BPF' '$(notdir $2)' 1>&2))
+ $(Q)$(BPF_GCC) $3 -DBPF_NO_PRESERVE_ACCESS_INDEX -Wno-attributes -O2 -c $1 -o $2 $(call skip_on_fail,BPF)
endef
SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
@@ -628,10 +632,7 @@ $(TRUNNER_BPF_SKELS): %.skel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
$$(BPFTOOL) gen object $$(<:.o=.linked3.o) $$(<:.o=.linked2.o) && \
diff $$(<:.o=.linked2.o) $$(<:.o=.linked3.o) && \
$$(BPFTOOL) gen skeleton $$(<:.o=.linked3.o) name $$(notdir $$(<:.bpf.o=)) > $$@ && \
- $$(BPFTOOL) gen subskeleton $$(<:.o=.linked3.o) name $$(notdir $$(<:.bpf.o=)) > $$(@:.skel.h=.subskel.h) $(if $(PERMISSIVE),|| { \
- $$(RM) $$@ $$(@:.skel.h=.subskel.h); \
- printf ' %-12s %s\n' 'SKIP-SKEL' '$$(notdir $$@)' 1>&2; \
- }) && \
+ $$(BPFTOOL) gen subskeleton $$(<:.o=.linked3.o) name $$(notdir $$(<:.bpf.o=)) > $$(@:.skel.h=.subskel.h) $$(call skip_on_fail,SKEL,$$(@:.skel.h=.subskel.h)) && \
rm -f $$(<:.o=.linked1.o) $$(<:.o=.linked2.o) $$(<:.o=.linked3.o)
$(TRUNNER_BPF_LSKELS): %.lskel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
@@ -645,10 +646,7 @@ $(TRUNNER_BPF_LSKELS): %.lskel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
$$(BPFTOOL) gen object $$(<:.o=.llinked2.o) $$(<:.o=.llinked1.o) && \
$$(BPFTOOL) gen object $$(<:.o=.llinked3.o) $$(<:.o=.llinked2.o) && \
diff $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o) && \
- $$(BPFTOOL) gen skeleton -L $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@ $(if $(PERMISSIVE),|| { \
- $$(RM) $$@; \
- printf ' %-12s %s\n' 'SKIP-SKEL' '$$(notdir $$@)' 1>&2; \
- }) && \
+ $$(BPFTOOL) gen skeleton -L $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@ $$(call skip_on_fail,SKEL) && \
rm -f $$(<:.o=.llinked1.o) $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
$(TRUNNER_BPF_LSKELS_SIGNED): %.lskel.h: %.bpf.o $(BPFTOOL) $(VERIFICATION_CERT) | $(TRUNNER_OUTPUT)
@@ -662,10 +660,7 @@ $(TRUNNER_BPF_LSKELS_SIGNED): %.lskel.h: %.bpf.o $(BPFTOOL) $(VERIFICATION_CERT)
$$(BPFTOOL) gen object $$(<:.o=.llinked2.o) $$(<:.o=.llinked1.o) && \
$$(BPFTOOL) gen object $$(<:.o=.llinked3.o) $$(<:.o=.llinked2.o) && \
diff $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o) && \
- $$(BPFTOOL) gen skeleton $(LSKEL_SIGN) $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@ $(if $(PERMISSIVE),|| { \
- $$(RM) $$@; \
- printf ' %-12s %s\n' 'SKIP-SKEL' '$$(notdir $$@)' 1>&2; \
- }) && \
+ $$(BPFTOOL) gen skeleton $(LSKEL_SIGN) $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@ $$(call skip_on_fail,SKEL) && \
rm -f $$(<:.o=.llinked1.o) $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
$(LINKED_BPF_OBJS): %: $(TRUNNER_OUTPUT)/%
@@ -687,10 +682,7 @@ $(TRUNNER_BPF_SKELS_LINKED): $(TRUNNER_OUTPUT)/%: $$$$(%-deps) $(BPFTOOL) | $(TR
diff $$(@:.skel.h=.linked2.o) $$(@:.skel.h=.linked3.o) && \
printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY)] $$(notdir $$@)' 1>&2 && \
$$(BPFTOOL) gen skeleton $$(@:.skel.h=.linked3.o) name $$(notdir $$(@:.skel.h=)) > $$@ && \
- $$(BPFTOOL) gen subskeleton $$(@:.skel.h=.linked3.o) name $$(notdir $$(@:.skel.h=)) > $$(@:.skel.h=.subskel.h) $(if $(PERMISSIVE),|| { \
- $$(RM) $$@ $$(@:.skel.h=.subskel.h); \
- printf ' %-12s %s\n' 'SKIP-SKEL' '$$(notdir $$@)' 1>&2; \
- }) && \
+ $$(BPFTOOL) gen subskeleton $$(@:.skel.h=.linked3.o) name $$(notdir $$(@:.skel.h=)) > $$(@:.skel.h=.subskel.h) $$(call skip_on_fail,SKEL,$$(@:.skel.h=.subskel.h)) && \
rm -f $$(@:.skel.h=.linked1.o) $$(@:.skel.h=.linked2.o) $$(@:.skel.h=.linked3.o)
# When the compiler generates a %.d file, only skel basenames (not
@@ -723,8 +715,7 @@ $(TRUNNER_TEST_OBJS): $(TRUNNER_OUTPUT)/%.test.o: \
$(TRUNNER_TESTS_DIR)/%.c \
| $(TRUNNER_OUTPUT)/%.test.d
$$(call msg,TEST-OBJ,$(TRUNNER_BINARY),$$@)
- $(Q)(cd $$(@D) && $$(CC) -I. $$(CFLAGS) -MMD -MT $$@ -c $(CURDIR)/$$< $$(LDLIBS) -o $$(@F)) $(if $(filter test_progs%,$1),$(if $(PERMISSIVE),|| \
- ($(RM) $$@; printf ' %-12s %s\n' 'SKIP-TEST' '$$(notdir $$@)' 1>&2)))
+ $(Q)(cd $$(@D) && $$(CC) -I. $$(CFLAGS) -MMD -MT $$@ -c $(CURDIR)/$$< $$(LDLIBS) -o $$(@F)) $(if $(filter test_progs%,$1),$$(call skip_on_fail,TEST))
$$(if $$(TEST_NEEDS_BTFIDS), \
$(Q)if [ -f $$@ ]; then \
$(if $(filter 1,$(V)),true,printf ' %-8s%s %s\n' "BTFIDS" " [$(TRUNNER_BINARY)]" "$$(notdir $$@)"); \
@@ -960,8 +951,7 @@ $(OUTPUT)/test_cpp: test_cpp.cpp $(OUTPUT)/test_core_extern.skel.h $(BPFOBJ)
# Benchmark runner
$(OUTPUT)/bench_%.o: benchs/bench_%.c bench.h $(BPFOBJ)
$(call msg,CC,,$@)
- $(Q)$(CC) $(CFLAGS) -O2 -c $(filter %.c,$^) $(LDLIBS) -o $@ $(if $(PERMISSIVE),|| \
- ($(RM) $@; printf ' %-12s %s\n' 'SKIP-BENCH' '$(notdir $@)' 1>&2))
+ $(Q)$(CC) $(CFLAGS) -O2 -c $(filter %.c,$^) $(LDLIBS) -o $@ $(call skip_on_fail,BENCH)
$(OUTPUT)/bench_rename.o: $(OUTPUT)/test_overhead.skel.h
$(OUTPUT)/bench_trigger.o: $(OUTPUT)/trigger_bench.skel.h
$(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \
@@ -1014,8 +1004,7 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \
$(OUTPUT)/usdt_2.o \
#
$(call msg,BINARY,,$@)
- $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ $(if $(PERMISSIVE),|| \
- ($(RM) $@; printf ' %-12s %s\n' 'SKIP-LINK' '$(notdir $@) (some benchmarks may have been skipped)' 1>&2))
+ $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ $(call skip_on_fail,LINK,,(some benchmarks may have been skipped))
# This works around GCC warning about snprintf truncating strings like:
#
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH bpf-next v8 3/9] selftests/bpf: factor the permissive-mode skip suffix into a helper
2026-09-21 7:58 ` [PATCH bpf-next v8 3/9] selftests/bpf: factor the permissive-mode skip suffix into a helper Mykola Lysenko
@ 2026-09-21 8:09 ` sashiko-bot
0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-09-21 8:09 UTC (permalink / raw)
To: Mykola Lysenko; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] build: missing space in skip_on_fail formatting
--
commit a3e18474fd48a50d84abcafc18805d61a8736ce1
Author: Mykola Lysenko <nickolay.lysenko@gmail.com>
selftests/bpf: factor the permissive-mode skip suffix into a helper
With BPF_STRICT_BUILD=0, eleven recipes append the same "|| { remove the
target, print a SKIP marker, report success }" tail, each spelled out
inline. Factor the tail into skip_on_fail; every call site keeps its
exact message and behavior.
> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> index 3606ee8ab7949..11bd8997aea5d 100644
> --- a/tools/testing/selftests/bpf/Makefile
> +++ b/tools/testing/selftests/bpf/Makefile
> @@ -46,6 +46,14 @@ SKIP_CRYPTO ?=
> BPF_STRICT_BUILD ?= 1
> PERMISSIVE := $(filter 0,$(BPF_STRICT_BUILD))
>
> +# Permissive-mode recipe suffix: on failure, remove the target, emit a
> +# SKIP marker and report success so the rest of the build continues.
> +# $(1) - SKIP tag (BPF, TEST, BENCH, SKEL, LINK, ...)
> +# $(2) - optional extra files to remove alongside the target
> +# $(3) - optional note appended to the SKIP message
> +skip_on_fail = $(if $(PERMISSIVE),|| { $(RM) $@ $(2); \
> + printf ' %-12s %s\n' 'SKIP-$(1)' '$(notdir $@)$(if $(3), $(3))' 1>&2; })
[Severity: Low]
Does this formatting result in a missing space between the target name and the
note?
GNU Make strips unescaped leading whitespace following commas in function
arguments, so the space in `$(if $(3), $(3))` is discarded during expansion.
[ ... ]
> @@ -1014,8 +1004,7 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \
> $(OUTPUT)/usdt_2.o \
> #
> $(call msg,BINARY,,$@)
> - $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ $(if $(PERMISSIVE),|| \
> - ($(RM) $@; printf ' %-12s %s\n' 'SKIP-LINK' '$(notdir $@) (some benchmarks may have been skipped)' 1>&2))
> + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ $(call skip_on_fail,LINK,,(some benchmarks may have been skipped))
[Severity: Low]
Because the space is stripped, the invocation above doesn't provide a leading
space either. Will this log output as `bench(some benchmarks may have been
skipped)` instead of `bench (some benchmarks may have been skipped)`?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260921075855.2065871-1-nickolay.lysenko@gmail.com?part=3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH bpf-next v8 4/9] selftests/bpf: generate the signing key and certificate once
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
` (2 preceding siblings ...)
2026-09-21 7:58 ` [PATCH bpf-next v8 3/9] selftests/bpf: factor the permissive-mode skip suffix into a helper Mykola Lysenko
@ 2026-09-21 7:58 ` Mykola Lysenko
2026-09-21 7:58 ` [PATCH bpf-next v8 5/9] selftests/bpf: generate verifier/tests.h in a regular recipe Mykola Lysenko
` (6 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 7:58 UTC (permalink / raw)
To: bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko
genkey produces the private key and certificate together, but an
ordinary multi-target rule can run it twice concurrently when both
outputs are required. Only the certificate is currently a prerequisite;
the runner split will require both.
Use an implicitly grouped pattern rule, as test_kmods already does, to
support make versions before 4.3.
Signed-off-by: Mykola Lysenko <nickolay.lysenko@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
---
tools/testing/selftests/bpf/Makefile | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 11bd8997aea5..5bcb762dc3fc 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -783,7 +783,10 @@ VERIFY_SIG_HDR := verification_cert.h
VERIFICATION_CERT := $(BUILD_DIR)/signing_key.der
PRIVATE_KEY := $(BUILD_DIR)/signing_key.pem
-$(VERIFICATION_CERT) $(PRIVATE_KEY): $(VERIFY_SIG_SETUP)
+# genkey writes both outputs. Pattern rules group them even on make
+# versions before 4.3, preventing concurrent genkey invocations.
+# Restrict the pattern to *_key files because genkey uses fixed names.
+$(BUILD_DIR)/%_key.pem $(BUILD_DIR)/%_key.der: $(VERIFY_SIG_SETUP)
$(Q)mkdir -p $(BUILD_DIR)
$(Q)$(VERIFY_SIG_SETUP) genkey $(BUILD_DIR)
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH bpf-next v8 5/9] selftests/bpf: generate verifier/tests.h in a regular recipe
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
` (3 preceding siblings ...)
2026-09-21 7:58 ` [PATCH bpf-next v8 4/9] selftests/bpf: generate the signing key and certificate once Mykola Lysenko
@ 2026-09-21 7:58 ` Mykola Lysenko
2026-09-21 9:06 ` bot+bpf-ci
2026-09-21 7:58 ` [PATCH bpf-next v8 6/9] selftests/bpf: derive the bench object list from the sources Mykola Lysenko
` (5 subsequent siblings)
10 siblings, 1 reply; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 7:58 UTC (permalink / raw)
To: bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko
The verifier/tests.h recipe is a $(shell ...) expansion: the command
runs while make expands the recipe line - including under make -n - its
exit status is discarded, and the resulting (empty) expansion is what
make actually executes.
Signed-off-by: Mykola Lysenko <nickolay.lysenko@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
---
tools/testing/selftests/bpf/Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 5bcb762dc3fc..0e23cb506777 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -910,12 +910,12 @@ $(eval $(call DEFINE_TEST_RUNNER,test_maps))
# them (e.g., test.h is using completely pattern), that it's worth just
# explicitly defining all the rules explicitly.
verifier/tests.h: verifier/*.c
- $(shell ( cd verifier/; \
+ $(Q)( cd verifier/; \
echo '/* Generated header, do not edit */'; \
echo '#ifdef FILL_ARRAY'; \
ls *.c 2> /dev/null | sed -e 's@\(.*\)@#include \"\1\"@'; \
echo '#endif' \
- ) > verifier/tests.h)
+ ) > verifier/tests.h
$(OUTPUT)/test_verifier: test_verifier.c verifier/tests.h $(BPFOBJ) | $(OUTPUT)
$(call msg,BINARY,,$@)
$(Q)$(CC) $(CFLAGS) $(filter %.a %.o %.c,$^) $(LDLIBS) -o $@
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH bpf-next v8 5/9] selftests/bpf: generate verifier/tests.h in a regular recipe
2026-09-21 7:58 ` [PATCH bpf-next v8 5/9] selftests/bpf: generate verifier/tests.h in a regular recipe Mykola Lysenko
@ 2026-09-21 9:06 ` bot+bpf-ci
2026-09-21 12:36 ` Mykola Lysenko
0 siblings, 1 reply; 19+ messages in thread
From: bot+bpf-ci @ 2026-09-21 9:06 UTC (permalink / raw)
To: nickolay.lysenko, bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko, ast, andrii, daniel, martin.lau,
eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2961 bytes --]
> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> index 5bcb762dc3fcf..0e23cb5067776 100644
> --- a/tools/testing/selftests/bpf/Makefile
> +++ b/tools/testing/selftests/bpf/Makefile
> @@ -910,12 +910,12 @@ $(eval $(call DEFINE_TEST_RUNNER,test_maps))
> # them (e.g., test.h is using completely pattern), that it's worth just
> # explicitly defining all the rules explicitly.
> verifier/tests.h: verifier/*.c
> - $(shell ( cd verifier/; \
> + $(Q)( cd verifier/; \
> echo '/* Generated header, do not edit */'; \
> echo '#ifdef FILL_ARRAY'; \
> ls *.c 2> /dev/null | sed -e 's@\(.*\)@#include \"\1\"@'; \
> echo '#endif' \
> - ) > verifier/tests.h)
> + ) > verifier/tests.h
The changelog states that "its exit status is discarded" was a defect
of the old $(shell ...) form that this patch fixes. Does the new form
actually make the exit status meaningful?
The recipe body is a subshell whose commands are chained with ';', not
'&&', and whose last command is 'echo '#endif''. A subshell exits with
the status of its last command, so the recipe's status is echo's status,
which is always 0. Concretely:
- 'cd verifier/' failing is not fatal (';' chaining), and the
following echos still run.
- 'ls *.c 2> /dev/null' deliberately discards its own error output,
and a pipeline reports only sed's status.
- sed failing (missing/broken sed, ENOMEM, SIGPIPE) yields a header
containing only the '/* Generated header */' line, '#ifdef FILL_ARRAY'
and '#endif' - a valid but empty test list - and the recipe still
reports success.
In that case make treats verifier/tests.h as successfully built,
.DELETE_ON_ERROR: does not trigger because there was no error, the file
gets an mtime newer than every verifier/*.c so it is never regenerated,
and $(OUTPUT)/test_verifier links and runs with zero verifier tests
instead of ~1000 - a silent pass rather than a build failure. The only
failure the recipe can now report is the '> verifier/tests.h' redirect
itself failing.
This is not a behavioural regression relative to the pre-patch code (the
old $(shell) form masked the same failures), but it means the exit-status
rationale in the changelog is not satisfied by the patch. Could the
commands be chained with '&&' or the recipe be prefixed with 'set -e;'?
Note the sibling recipe just above at Makefile:795-798 has the identical
';'-chained shape, so matching it might be the intent - but that recipe
ends in a command whose failure is equally invisible.
> $(OUTPUT)/test_verifier: test_verifier.c verifier/tests.h $(BPFOBJ) | $(OUTPUT)
> $(call msg,BINARY,,$@)
> $(Q)$(CC) $(CFLAGS) $(filter %.a %.o %.c,$^) $(LDLIBS) -o $@
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/35577680350
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH bpf-next v8 5/9] selftests/bpf: generate verifier/tests.h in a regular recipe
2026-09-21 9:06 ` bot+bpf-ci
@ 2026-09-21 12:36 ` Mykola Lysenko
0 siblings, 0 replies; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 12:36 UTC (permalink / raw)
To: bot+bpf-ci
Cc: bpf, ast, daniel, andrii, eddyz87, martin.lau, song,
yonghong.song, jolsa, memxor, martin.lau, mason, ihor.solodrai
On Mon, Sep 21, 2026 at 11:06 AM <bot+bpf-ci@kernel.org> wrote:
>
> > diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> > index 5bcb762dc3fcf..0e23cb5067776 100644
> > --- a/tools/testing/selftests/bpf/Makefile
> > +++ b/tools/testing/selftests/bpf/Makefile
> > @@ -910,12 +910,12 @@ $(eval $(call DEFINE_TEST_RUNNER,test_maps))
> > # them (e.g., test.h is using completely pattern), that it's worth just
> > # explicitly defining all the rules explicitly.
> > verifier/tests.h: verifier/*.c
> > - $(shell ( cd verifier/; \
> > + $(Q)( cd verifier/; \
> > echo '/* Generated header, do not edit */'; \
> > echo '#ifdef FILL_ARRAY'; \
> > ls *.c 2> /dev/null | sed -e 's@\(.*\)@#include \"\1\"@'; \
> > echo '#endif' \
> > - ) > verifier/tests.h)
> > + ) > verifier/tests.h
>
> The changelog states that "its exit status is discarded" was a defect
> of the old $(shell ...) form that this patch fixes. Does the new form
> actually make the exit status meaningful?
Yes, it does. Previously, $(shell ...) discarded the command's exit
status. With this change, make detects failures such as being unable
to open verifier/tests.h for writing.
The commands inside the subshell can still mask failures from ls or
sed. That behavior predates this patch, and I would leave improving
it to a separate follow-up.
>
> The recipe body is a subshell whose commands are chained with ';', not
> '&&', and whose last command is 'echo '#endif''. A subshell exits with
> the status of its last command, so the recipe's status is echo's status,
> which is always 0. Concretely:
>
> - 'cd verifier/' failing is not fatal (';' chaining), and the
> following echos still run.
>
> - 'ls *.c 2> /dev/null' deliberately discards its own error output,
> and a pipeline reports only sed's status.
>
> - sed failing (missing/broken sed, ENOMEM, SIGPIPE) yields a header
> containing only the '/* Generated header */' line, '#ifdef FILL_ARRAY'
> and '#endif' - a valid but empty test list - and the recipe still
> reports success.
>
> In that case make treats verifier/tests.h as successfully built,
> .DELETE_ON_ERROR: does not trigger because there was no error, the file
> gets an mtime newer than every verifier/*.c so it is never regenerated,
> and $(OUTPUT)/test_verifier links and runs with zero verifier tests
> instead of ~1000 - a silent pass rather than a build failure. The only
> failure the recipe can now report is the '> verifier/tests.h' redirect
> itself failing.
>
> This is not a behavioural regression relative to the pre-patch code (the
> old $(shell) form masked the same failures), but it means the exit-status
> rationale in the changelog is not satisfied by the patch. Could the
> commands be chained with '&&' or the recipe be prefixed with 'set -e;'?
> Note the sibling recipe just above at Makefile:795-798 has the identical
> ';'-chained shape, so matching it might be the intent - but that recipe
> ends in a command whose failure is equally invisible.
>
> > $(OUTPUT)/test_verifier: test_verifier.c verifier/tests.h $(BPFOBJ) | $(OUTPUT)
> > $(call msg,BINARY,,$@)
> > $(Q)$(CC) $(CFLAGS) $(filter %.a %.o %.c,$^) $(LDLIBS) -o $@
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/35577680350
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH bpf-next v8 6/9] selftests/bpf: derive the bench object list from the sources
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
` (4 preceding siblings ...)
2026-09-21 7:58 ` [PATCH bpf-next v8 5/9] selftests/bpf: generate verifier/tests.h in a regular recipe Mykola Lysenko
@ 2026-09-21 7:58 ` Mykola Lysenko
2026-09-21 7:58 ` [PATCH bpf-next v8 7/9] selftests/bpf: extract BPF skeleton generation into a helper script Mykola Lysenko
` (4 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 7:58 UTC (permalink / raw)
To: bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko
bench links every benchs/bench_*.c object. Derive the object list with a
wildcard so adding a benchmark no longer requires updating the link
rule. Skeleton prerequisites remain explicit.
The sorted list changes object link order and the binary's symbol
layout; no benchmark behaves differently.
Signed-off-by: Mykola Lysenko <nickolay.lysenko@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
---
tools/testing/selftests/bpf/Makefile | 28 ++++------------------------
1 file changed, 4 insertions(+), 24 deletions(-)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 0e23cb506777..99237c3b32d5 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -951,7 +951,8 @@ $(OUTPUT)/test_cpp: test_cpp.cpp $(OUTPUT)/test_core_extern.skel.h $(BPFOBJ)
$(call msg,CXX,,$@)
$(Q)$(CXX) $(CXXFLAGS) $(filter %.a %.o %.cpp,$^) $(LDLIBS) -o $@
-# Benchmark runner
+# Benchmark runner. Every benchs/bench_*.c is compiled and linked in.
+BENCH_OBJS := $(sort $(patsubst benchs/%.c,$(OUTPUT)/%.o,$(wildcard benchs/bench_*.c)))
$(OUTPUT)/bench_%.o: benchs/bench_%.c bench.h $(BPFOBJ)
$(call msg,CC,,$@)
$(Q)$(CC) $(CFLAGS) -O2 -c $(filter %.c,$^) $(LDLIBS) -o $@ $(call skip_on_fail,BENCH)
@@ -982,30 +983,9 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \
$(TESTING_HELPERS) \
$(TRACE_HELPERS) \
$(CGROUP_HELPERS) \
- $(OUTPUT)/bench_count.o \
- $(OUTPUT)/bench_rename.o \
- $(OUTPUT)/bench_trigger.o \
- $(OUTPUT)/bench_ringbufs.o \
- $(OUTPUT)/bench_bloom_filter_map.o \
- $(OUTPUT)/bench_bpf_loop.o \
- $(OUTPUT)/bench_bpf_for.o \
- $(OUTPUT)/bench_strncmp.o \
- $(OUTPUT)/bench_bpf_hashmap_full_update.o \
- $(OUTPUT)/bench_local_storage.o \
- $(OUTPUT)/bench_local_storage_rcu_tasks_trace.o \
- $(OUTPUT)/bench_bpf_hashmap_lookup.o \
- $(OUTPUT)/bench_local_storage_create.o \
- $(OUTPUT)/bench_htab_mem.o \
- $(OUTPUT)/bench_bpf_crypto.o \
- $(OUTPUT)/bench_sockmap.o \
- $(OUTPUT)/bench_lpm_trie_map.o \
- $(OUTPUT)/bench_bpf_timing.o \
- $(OUTPUT)/bench_bpf_nop.o \
- $(OUTPUT)/bench_xdp_lb.o \
- $(OUTPUT)/bench_libarena.o \
+ $(BENCH_OBJS) \
$(OUTPUT)/usdt_1.o \
- $(OUTPUT)/usdt_2.o \
- #
+ $(OUTPUT)/usdt_2.o
$(call msg,BINARY,,$@)
$(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ $(call skip_on_fail,LINK,,(some benchmarks may have been skipped))
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH bpf-next v8 7/9] selftests/bpf: extract BPF skeleton generation into a helper script
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
` (5 preceding siblings ...)
2026-09-21 7:58 ` [PATCH bpf-next v8 6/9] selftests/bpf: derive the bench object list from the sources Mykola Lysenko
@ 2026-09-21 7:58 ` Mykola Lysenko
2026-09-21 7:58 ` [PATCH bpf-next v8 8/9] selftests/bpf: move shared build definitions into Makefile.buildvars Mykola Lysenko
` (3 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 7:58 UTC (permalink / raw)
To: bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko
Four skeleton recipes duplicate the link, determinism-check and
header-generation pipeline inside DEFINE_TEST_RUNNER_RULES. Extract it
into gen_bpf_skel.sh, with options for light and signed skeletons.
Intermediate names now derive from the output header, retaining separate
linked/llinked infixes for regular and light skeletons.
Keep the permissive-mode missing-input guards in a skip_if_missing
helper, so a skipped skeleton still prints only SKIP-SKEL. On failure,
the script removes intermediates and both output headers; previously,
strict-mode recipes left intermediates behind and .DELETE_ON_ERROR
covered only the target, not its subskeleton.
The determinism check names the skeleton when it fails, and linked
skeletons log GEN-SKEL before linking.
Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
Assisted-by: Claude:claude-fable-5 shellcheck
Signed-off-by: Mykola Lysenko <nickolay.lysenko@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
---
tools/testing/selftests/bpf/Makefile | 93 ++++++++-----------
tools/testing/selftests/bpf/gen_bpf_skel.sh | 99 +++++++++++++++++++++
2 files changed, 136 insertions(+), 56 deletions(-)
create mode 100755 tools/testing/selftests/bpf/gen_bpf_skel.sh
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 99237c3b32d5..a6fd107e357f 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -54,6 +54,17 @@ PERMISSIVE := $(filter 0,$(BPF_STRICT_BUILD))
skip_on_fail = $(if $(PERMISSIVE),|| { $(RM) $@ $(2); \
printf ' %-12s %s\n' 'SKIP-$(1)' '$(notdir $@)$(if $(3), $(3))' 1>&2; })
+# Permissive-mode recipe prefix: when a prerequisite object is missing
+# (its compile failed and was skipped), remove the target and $(3),
+# emit a SKIP marker and report success without running the rest of
+# the recipe.
+# $(1) - SKIP tag
+# $(2) - input files to check
+# $(3) - optional extra files to remove alongside the target
+skip_if_missing = $(if $(PERMISSIVE),for f in $(2); do [ -f $$f ] || { \
+ $(RM) $@ $(3); \
+ printf ' %-12s %s\n' 'SKIP-$(1)' '$(notdir $@)' 1>&2; exit 0; }; done;)
+
ifeq ($(srctree),)
srctree := $(patsubst %/,%,$(dir $(CURDIR)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
@@ -560,7 +571,6 @@ HEADERS_FOR_BPF_OBJS := $(wildcard $(BPFDIR)/*.bpf.h) \
# $2 - test runner extra "flavor" (e.g., no_alu32, cpuv4, bpf_gcc, etc)
define DEFINE_TEST_RUNNER
-LSKEL_SIGN := -S -k $(PRIVATE_KEY) -i $(VERIFICATION_CERT)
TRUNNER_OUTPUT := $(OUTPUT)$(if $2,/)$2
TRUNNER_BINARY := $1$(if $2,-)$2
TRUNNER_TEST_OBJS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.test.o, \
@@ -620,70 +630,41 @@ $(TRUNNER_BPF_OBJS): $(TRUNNER_OUTPUT)/%.bpf.o: \
$$($$<-CFLAGS) \
$$($$<-$2-CFLAGS),$(TRUNNER_BINARY))
-$(TRUNNER_BPF_SKELS): %.skel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
- $(Q)$(if $(PERMISSIVE),if [ ! -f $$< ]; then \
- $$(RM) $$@ $$(@:.skel.h=.subskel.h); \
- printf ' %-12s %s\n' 'SKIP-SKEL' '$$(notdir $$@)' 1>&2; \
- exit 0; \
- fi;) \
+$(TRUNNER_BPF_SKELS): %.skel.h: %.bpf.o $(BPFTOOL) gen_bpf_skel.sh | $(TRUNNER_OUTPUT)
+ $(Q)$$(call skip_if_missing,SKEL,$$<,$$(@:.skel.h=.subskel.h)) \
printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY)] $$(notdir $$@)' 1>&2; \
- $$(BPFTOOL) gen object $$(<:.o=.linked1.o) $$< && \
- $$(BPFTOOL) gen object $$(<:.o=.linked2.o) $$(<:.o=.linked1.o) && \
- $$(BPFTOOL) gen object $$(<:.o=.linked3.o) $$(<:.o=.linked2.o) && \
- diff $$(<:.o=.linked2.o) $$(<:.o=.linked3.o) && \
- $$(BPFTOOL) gen skeleton $$(<:.o=.linked3.o) name $$(notdir $$(<:.bpf.o=)) > $$@ && \
- $$(BPFTOOL) gen subskeleton $$(<:.o=.linked3.o) name $$(notdir $$(<:.bpf.o=)) > $$(@:.skel.h=.subskel.h) $$(call skip_on_fail,SKEL,$$(@:.skel.h=.subskel.h)) && \
- rm -f $$(<:.o=.linked1.o) $$(<:.o=.linked2.o) $$(<:.o=.linked3.o)
-
-$(TRUNNER_BPF_LSKELS): %.lskel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
- $(Q)$(if $(PERMISSIVE),if [ ! -f $$< ]; then \
- $$(RM) $$@; \
- printf ' %-12s %s\n' 'SKIP-SKEL' '$$(notdir $$@)' 1>&2; \
- exit 0; \
- fi;) \
+ BPFTOOL=$$(BPFTOOL) ./gen_bpf_skel.sh \
+ --name $$(notdir $$(<:.bpf.o=)) \
+ --skel $$@ --subskel $$(@:.skel.h=.subskel.h) $$< $$(call skip_on_fail,SKEL,$$(@:.skel.h=.subskel.h))
+
+$(TRUNNER_BPF_LSKELS): %.lskel.h: %.bpf.o $(BPFTOOL) gen_bpf_skel.sh | $(TRUNNER_OUTPUT)
+ $(Q)$$(call skip_if_missing,SKEL,$$<) \
printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY)] $$(notdir $$@)' 1>&2; \
- $$(BPFTOOL) gen object $$(<:.o=.llinked1.o) $$< && \
- $$(BPFTOOL) gen object $$(<:.o=.llinked2.o) $$(<:.o=.llinked1.o) && \
- $$(BPFTOOL) gen object $$(<:.o=.llinked3.o) $$(<:.o=.llinked2.o) && \
- diff $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o) && \
- $$(BPFTOOL) gen skeleton -L $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@ $$(call skip_on_fail,SKEL) && \
- rm -f $$(<:.o=.llinked1.o) $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
-
-$(TRUNNER_BPF_LSKELS_SIGNED): %.lskel.h: %.bpf.o $(BPFTOOL) $(VERIFICATION_CERT) | $(TRUNNER_OUTPUT)
- $(Q)$(if $(PERMISSIVE),if [ ! -f $$< ]; then \
- $$(RM) $$@; \
- printf ' %-12s %s\n' 'SKIP-SKEL' '$$(notdir $$@)' 1>&2; \
- exit 0; \
- fi;) \
+ BPFTOOL=$$(BPFTOOL) ./gen_bpf_skel.sh \
+ --name $$(notdir $$(<:.bpf.o=_lskel)) --lskel \
+ --skel $$@ $$< $$(call skip_on_fail,SKEL)
+
+$(TRUNNER_BPF_LSKELS_SIGNED): %.lskel.h: %.bpf.o $(BPFTOOL) $(VERIFICATION_CERT) gen_bpf_skel.sh | $(TRUNNER_OUTPUT)
+ $(Q)$$(call skip_if_missing,SKEL,$$<) \
printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY) (signed)] $$(notdir $$@)' 1>&2; \
- $$(BPFTOOL) gen object $$(<:.o=.llinked1.o) $$< && \
- $$(BPFTOOL) gen object $$(<:.o=.llinked2.o) $$(<:.o=.llinked1.o) && \
- $$(BPFTOOL) gen object $$(<:.o=.llinked3.o) $$(<:.o=.llinked2.o) && \
- diff $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o) && \
- $$(BPFTOOL) gen skeleton $(LSKEL_SIGN) $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@ $$(call skip_on_fail,SKEL) && \
- rm -f $$(<:.o=.llinked1.o) $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
+ BPFTOOL=$$(BPFTOOL) PRIVATE_KEY=$(PRIVATE_KEY) \
+ VERIFICATION_CERT=$(VERIFICATION_CERT) \
+ ./gen_bpf_skel.sh --sign \
+ --name $$(notdir $$(<:.bpf.o=_lskel)) \
+ --skel $$@ $$< $$(call skip_on_fail,SKEL)
$(LINKED_BPF_OBJS): %: $(TRUNNER_OUTPUT)/%
# .SECONDEXPANSION here allows to correctly expand %-deps variables as prerequisites
.SECONDEXPANSION:
-$(TRUNNER_BPF_SKELS_LINKED): $(TRUNNER_OUTPUT)/%: $$$$(%-deps) $(BPFTOOL) | $(TRUNNER_OUTPUT)
- $(Q)$(if $(PERMISSIVE),for f in $$(addprefix $(TRUNNER_OUTPUT)/,$$($$(@F)-deps)); do \
- if [ ! -f $$$$f ]; then \
- $$(RM) $$@ $$(@:.skel.h=.subskel.h); \
- printf ' %-12s %s\n' 'SKIP-SKEL' '$$(notdir $$@)' 1>&2; \
- exit 0; \
- fi; \
- done;) \
+$(TRUNNER_BPF_SKELS_LINKED): $(TRUNNER_OUTPUT)/%: $$$$(%-deps) $(BPFTOOL) gen_bpf_skel.sh | $(TRUNNER_OUTPUT)
+ $(Q)$$(call skip_if_missing,SKEL,$$(addprefix $(TRUNNER_OUTPUT)/,$$($$(@F)-deps)),$$(@:.skel.h=.subskel.h)) \
printf ' %-12s %s\n' 'LINK-BPF' '[$(TRUNNER_BINARY)] $$(notdir $$(@:.skel.h=.bpf.o))' 1>&2; \
- $$(BPFTOOL) gen object $$(@:.skel.h=.linked1.o) $$(addprefix $(TRUNNER_OUTPUT)/,$$($$(@F)-deps)) && \
- $$(BPFTOOL) gen object $$(@:.skel.h=.linked2.o) $$(@:.skel.h=.linked1.o) && \
- $$(BPFTOOL) gen object $$(@:.skel.h=.linked3.o) $$(@:.skel.h=.linked2.o) && \
- diff $$(@:.skel.h=.linked2.o) $$(@:.skel.h=.linked3.o) && \
- printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY)] $$(notdir $$@)' 1>&2 && \
- $$(BPFTOOL) gen skeleton $$(@:.skel.h=.linked3.o) name $$(notdir $$(@:.skel.h=)) > $$@ && \
- $$(BPFTOOL) gen subskeleton $$(@:.skel.h=.linked3.o) name $$(notdir $$(@:.skel.h=)) > $$(@:.skel.h=.subskel.h) $$(call skip_on_fail,SKEL,$$(@:.skel.h=.subskel.h)) && \
- rm -f $$(@:.skel.h=.linked1.o) $$(@:.skel.h=.linked2.o) $$(@:.skel.h=.linked3.o)
+ printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY)] $$(notdir $$@)' 1>&2; \
+ BPFTOOL=$$(BPFTOOL) ./gen_bpf_skel.sh \
+ --name $$(notdir $$(@:.skel.h=)) \
+ --skel $$@ --subskel $$(@:.skel.h=.subskel.h) \
+ $$(addprefix $(TRUNNER_OUTPUT)/,$$($$(@F)-deps)) $$(call skip_on_fail,SKEL,$$(@:.skel.h=.subskel.h))
# When the compiler generates a %.d file, only skel basenames (not
# full paths) are specified as prerequisites for corresponding %.o
diff --git a/tools/testing/selftests/bpf/gen_bpf_skel.sh b/tools/testing/selftests/bpf/gen_bpf_skel.sh
new file mode 100755
index 000000000000..60942f24b094
--- /dev/null
+++ b/tools/testing/selftests/bpf/gen_bpf_skel.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Link BPF object file(s) with "bpftool gen object" and generate a
+# skeleton (or light skeleton) header from the result.
+#
+# Usage:
+# BPFTOOL=<bpftool> gen_bpf_skel.sh --name NAME --skel OUT
+# [options] OBJ...
+#
+# --name NAME skeleton object name ("name NAME" for bpftool)
+# --skel OUT output header ("foo.skel.h" or "foo.lskel.h")
+# --subskel OUT also generate a subskeleton header into OUT
+# --lskel generate a light skeleton (bpftool gen skeleton -L)
+# --sign sign the (light) skeleton, with the key and
+# certificate taken from $PRIVATE_KEY and
+# $VERIFICATION_CERT
+#
+# The inputs are linked three times and the 2nd and 3rd results compared,
+# as a regression test for the determinism of "bpftool gen object".
+#
+# Intermediate files are named after the output header with a "linked"
+# infix - "llinked" for light or signed skeletons, so that generating a
+# .skel.h and a .lskel.h from the same .bpf.o in parallel never races on
+# the intermediates.
+#
+# The bpftool binary is taken from $BPFTOOL (default: bpftool from PATH).
+# On failure all outputs and intermediates are removed and the script exits
+# non-zero; permissive-mode skipping is the caller's business (see
+# skip_on_fail in the Makefile).
+
+set -u
+
+bpftool=${BPFTOOL:-bpftool}
+name='' skel='' subskel=''
+lskel=0 sign=0
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --name) name=$2; shift 2 ;;
+ --skel) skel=$2; shift 2 ;;
+ --subskel) subskel=$2; shift 2 ;;
+ --lskel) lskel=1; shift ;;
+ --sign) sign=1; shift ;;
+ --) shift; break ;;
+ -*) echo "$0: unknown option: $1" >&2; exit 1 ;;
+ *) break ;;
+ esac
+done
+
+if [ -z "$name" ] || [ -z "$skel" ] || [ $# -eq 0 ]; then
+ echo "usage: $0 --name NAME --skel OUT [options] OBJ..." >&2
+ exit 1
+fi
+
+infix=linked
+if [ "$lskel" -eq 1 ] || [ "$sign" -eq 1 ]; then
+ infix=llinked
+fi
+
+if [ "$sign" -eq 1 ] && { [ -z "${PRIVATE_KEY-}" ] || [ -z "${VERIFICATION_CERT-}" ]; }; then
+ echo "$0: --sign requires PRIVATE_KEY and VERIFICATION_CERT in the environment" >&2
+ exit 1
+fi
+
+base=${skel%.skel.h}
+base=${base%.lskel.h}
+t1=$base.${infix}1.o
+t2=$base.${infix}2.o
+t3=$base.${infix}3.o
+
+fail() {
+ rm -f "$skel" ${subskel:+"$subskel"} "$t1" "$t2" "$t3"
+ exit 1
+}
+
+"$bpftool" gen object "$t1" "$@" || fail
+"$bpftool" gen object "$t2" "$t1" || fail
+"$bpftool" gen object "$t3" "$t2" || fail
+if ! cmp -s "$t2" "$t3"; then
+ echo "$0: bpftool gen object is not deterministic for $skel" >&2
+ fail
+fi
+
+args=()
+if [ "$sign" -eq 1 ]; then
+ args+=(-S -k "$PRIVATE_KEY" -i "$VERIFICATION_CERT")
+fi
+if [ "$lskel" -eq 1 ]; then
+ args+=(-L)
+fi
+"$bpftool" gen skeleton ${args[@]+"${args[@]}"} "$t3" name "$name" > "$skel" || fail
+
+if [ -n "$subskel" ]; then
+ "$bpftool" gen subskeleton "$t3" name "$name" > "$subskel" || fail
+fi
+
+rm -f "$t1" "$t2" "$t3"
+exit 0
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH bpf-next v8 8/9] selftests/bpf: move shared build definitions into Makefile.buildvars
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
` (6 preceding siblings ...)
2026-09-21 7:58 ` [PATCH bpf-next v8 7/9] selftests/bpf: extract BPF skeleton generation into a helper script Mykola Lysenko
@ 2026-09-21 7:58 ` Mykola Lysenko
2026-09-21 7:58 ` [PATCH bpf-next v8 9/9] selftests/bpf: build each test runner instance in its own sub-make Mykola Lysenko
` (2 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 7:58 UTC (permalink / raw)
To: bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko
Move shared build definitions into Makefile.buildvars, preserving their
order, in preparation for separate runner sub-makes.
Include it after ../lib.mk and before Makefile.feature, so the LLVM
feature probe still sees srctree. Keep the CFLAGS and LDFLAGS additions
before lib.mk to preserve flag ordering; their references to definitions
below the include expand when used. Name the clang warning suppression
CLANG_WARN_CFLAGS so it can be referenced there.
The arena-ASAN probe moves below lib.mk, so it queries the CLANG the BPF
objects are built with. The CPU-v4 probe, BPF_GCC and TEST_KMODS remain
before lib.mk because they determine the target lists. Definitions no
runner reads move too when they are declared beside ones a runner does.
BPFTOOLDIR, HOST_BPFOBJ and BPF_TARGET_ENDIAN stay in the Makefile,
which alone reads them, and follow the include because their :=
assignments read values it defines.
Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
Assisted-by: Claude:claude-fable-5 shellcheck
Signed-off-by: Mykola Lysenko <nickolay.lysenko@gmail.com>
---
tools/testing/selftests/bpf/Makefile | 151 ++----------------
.../testing/selftests/bpf/Makefile.buildvars | 150 +++++++++++++++++
2 files changed, 160 insertions(+), 141 deletions(-)
create mode 100644 tools/testing/selftests/bpf/Makefile.buildvars
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index a6fd107e357f..25a21247a1ba 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -3,109 +3,21 @@ include ../../../build/Build.include
include ../../../scripts/Makefile.arch
include ../../../scripts/Makefile.include
-TOOLSDIR := $(abspath ../../..)
-LIBDIR := $(TOOLSDIR)/lib
-BPFDIR := $(LIBDIR)/bpf
-TOOLSINCDIR := $(TOOLSDIR)/include
-TOOLSARCHINCDIR := $(TOOLSDIR)/arch/$(SRCARCH)/include
-BPFTOOLDIR := $(TOOLSDIR)/bpf/bpftool
-APIDIR := $(TOOLSINCDIR)/uapi
-ifneq ($(O),)
-GENDIR := $(O)/include/generated
-else
-GENDIR := $(abspath ../../../../include/generated)
-endif
-GENHDR := $(GENDIR)/autoconf.h
-PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config
-
-ifneq ($(wildcard $(GENHDR)),)
- GENFLAGS := -DHAVE_GENHDR
-endif
-
BPF_GCC ?= $(shell command -v bpf-gcc;)
-ifdef ASAN
-SAN_CFLAGS ?= -fsanitize=address -fno-omit-frame-pointer
-else
-SAN_CFLAGS ?=
-endif
-SAN_LDFLAGS ?= $(SAN_CFLAGS)
-RELEASE ?=
-OPT_FLAGS ?= $(if $(RELEASE),-O2,-O0)
-
-LIBELF_CFLAGS := $(shell $(PKG_CONFIG) libelf --cflags 2>/dev/null)
-LIBELF_LIBS := $(shell $(PKG_CONFIG) libelf --libs 2>/dev/null || echo -lelf)
SKIP_DOCS ?=
SKIP_LLVM ?=
SKIP_LIBBFD ?=
SKIP_CRYPTO ?=
-# When BPF_STRICT_BUILD is 1, any BPF object, skeleton, test object, or
-# benchmark compilation failure is fatal. Set to 0 to tolerate failures
-# and continue building the remaining tests.
-BPF_STRICT_BUILD ?= 1
-PERMISSIVE := $(filter 0,$(BPF_STRICT_BUILD))
-
-# Permissive-mode recipe suffix: on failure, remove the target, emit a
-# SKIP marker and report success so the rest of the build continues.
-# $(1) - SKIP tag (BPF, TEST, BENCH, SKEL, LINK, ...)
-# $(2) - optional extra files to remove alongside the target
-# $(3) - optional note appended to the SKIP message
-skip_on_fail = $(if $(PERMISSIVE),|| { $(RM) $@ $(2); \
- printf ' %-12s %s\n' 'SKIP-$(1)' '$(notdir $@)$(if $(3), $(3))' 1>&2; })
-
-# Permissive-mode recipe prefix: when a prerequisite object is missing
-# (its compile failed and was skipped), remove the target and $(3),
-# emit a SKIP marker and report success without running the rest of
-# the recipe.
-# $(1) - SKIP tag
-# $(2) - input files to check
-# $(3) - optional extra files to remove alongside the target
-skip_if_missing = $(if $(PERMISSIVE),for f in $(2); do [ -f $$f ] || { \
- $(RM) $@ $(3); \
- printf ' %-12s %s\n' 'SKIP-$(1)' '$(notdir $@)' 1>&2; exit 0; }; done;)
-
-ifeq ($(srctree),)
-srctree := $(patsubst %/,%,$(dir $(CURDIR)))
-srctree := $(patsubst %/,%,$(dir $(srctree)))
-srctree := $(patsubst %/,%,$(dir $(srctree)))
-srctree := $(patsubst %/,%,$(dir $(srctree)))
-endif
-
-COMMON_CFLAGS = -g $(OPT_FLAGS) -rdynamic -std=gnu11 \
- -Wall -Werror -fno-omit-frame-pointer \
- -Wno-unused-but-set-variable \
- $(GENFLAGS) $(SAN_CFLAGS) $(LIBELF_CFLAGS) \
- -I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \
- -I$(TOOLSINCDIR) -I$(TOOLSARCHINCDIR) -I$(APIDIR) -I$(OUTPUT) \
- -I$(CURDIR)/libarena/include
-LDFLAGS += $(SAN_LDFLAGS)
-LDLIBS += $(LIBELF_LIBS) -lz -lrt -lpthread
-
-PCAP_CFLAGS := $(shell $(PKG_CONFIG) --cflags libpcap 2>/dev/null && echo "-DTRAFFIC_MONITOR=1")
-PCAP_LIBS := $(shell $(PKG_CONFIG) --libs libpcap 2>/dev/null)
-LDLIBS += $(PCAP_LIBS)
-CFLAGS += $(COMMON_CFLAGS) $(PCAP_CFLAGS)
-
# Some utility functions use LLVM libraries
jit_disasm_helpers.c-CFLAGS = $(LLVM_CFLAGS)
-ifneq ($(LLVM),)
-# Silence some warnings when compiled with clang
-CFLAGS += -Wno-unused-command-line-argument
-endif
-
# Check whether bpf cpu=v4 is supported or not by clang
ifneq ($(shell $(CLANG) --target=bpf -mcpu=help 2>&1 | grep 'v4'),)
CLANG_CPUV4 := 1
endif
-# Check whether clang supports BPF address sanitizer (requires LLVM 22+)
-CLANG_HAS_ARENA_ASAN := $(shell echo 'int x;' | \
- $(CLANG) --target=bpf -fsanitize=kernel-address \
- -mllvm -asan-shadow-addr-space=1 \
- -x c -c - -o /dev/null 2>/dev/null && echo 1)
-
# Order correspond to 'make run_tests' order
TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_progs \
test_sockmap \
@@ -183,7 +95,17 @@ override define CLEAN
$(Q)$(MAKE) docs-clean
endef
+# Append build flags before lib.mk's user flags. References to
+# Makefile.buildvars definitions expand when the flags are used.
+# The arena-ASAN define is appended after lib.mk.
+CFLAGS += $(COMMON_CFLAGS) $(PCAP_CFLAGS) $(CLANG_WARN_CFLAGS)
+LDFLAGS += $(SAN_LDFLAGS)
include ../lib.mk
+include Makefile.buildvars
+
+BPFTOOLDIR := $(TOOLSDIR)/bpf/bpftool
+HOST_BPFOBJ := $(HOST_BUILD_DIR)/libbpf/libbpf.a
+BPF_TARGET_ENDIAN:=$(if $(IS_LITTLE_ENDIAN),--target=bpfel,--target=bpfeb)
NON_CHECK_FEAT_TARGETS := clean docs-clean emit_tests
CHECK_FEAT := $(filter-out $(NON_CHECK_FEAT_TARGETS),$(or $(MAKECMDGOALS), "none"))
@@ -228,21 +150,6 @@ ifeq ($(feature-llvm),1)
endif
endif
-SCRATCH_DIR := $(OUTPUT)/tools
-BUILD_DIR := $(SCRATCH_DIR)/build
-INCLUDE_DIR := $(SCRATCH_DIR)/include
-BPFOBJ := $(BUILD_DIR)/libbpf/libbpf.a
-ifneq ($(CROSS_COMPILE),)
-HOST_BUILD_DIR := $(BUILD_DIR)/host
-HOST_SCRATCH_DIR := $(OUTPUT)/host-tools
-HOST_INCLUDE_DIR := $(HOST_SCRATCH_DIR)/include
-else
-HOST_BUILD_DIR := $(BUILD_DIR)
-HOST_SCRATCH_DIR := $(SCRATCH_DIR)
-HOST_INCLUDE_DIR := $(INCLUDE_DIR)
-endif
-HOST_BPFOBJ := $(HOST_BUILD_DIR)/libbpf/libbpf.a
-RESOLVE_BTFIDS := $(HOST_BUILD_DIR)/resolve_btfids/resolve_btfids
VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \
$(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \
../../../../vmlinux \
@@ -330,17 +237,6 @@ $(TEST_KMOD_TARGETS): $(addprefix test_kmods/,$(TEST_KMODS))
$(call msg,MOD,,$@)
$(Q)$(if $(PERMISSIVE),if [ -f test_kmods/$(@F) ]; then )cp test_kmods/$(@F) $@$(if $(PERMISSIVE),; fi)
-
-DEFAULT_BPFTOOL := $(HOST_SCRATCH_DIR)/sbin/bpftool
-ifneq ($(CROSS_COMPILE),)
-CROSS_BPFTOOL := $(SCRATCH_DIR)/sbin/bpftool
-TRUNNER_BPFTOOL := $(CROSS_BPFTOOL)
-USE_BOOTSTRAP := ""
-else
-TRUNNER_BPFTOOL := $(DEFAULT_BPFTOOL)
-USE_BOOTSTRAP := "bootstrap/"
-endif
-
$(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED): $(BPFOBJ)
TESTING_HELPERS := $(OUTPUT)/testing_helpers.o
@@ -360,7 +256,6 @@ $(OUTPUT)/test_maps: $(TESTING_HELPERS)
$(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS) $(UNPRIV_HELPERS)
$(OUTPUT)/xsk.o: $(BPFOBJ)
-BPFTOOL ?= $(DEFAULT_BPFTOOL)
$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
$(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool
$(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \
@@ -467,30 +362,11 @@ $(shell $(1) $(2) -dM -E - </dev/null | grep '__loongarch_grlen ' | awk '{printf
$(shell $(1) $(2) -dM -E - </dev/null | grep -E 'MIPS(EL|EB)|_MIPS_SZ(PTR|LONG) |_MIPS_SIM |_ABI(O32|N32|64) ' | awk '{printf("-D%s=%s ", $$2, $$3)}')
endef
-# Determine target endianness.
-IS_LITTLE_ENDIAN := $(shell $(CC) -dM -E - </dev/null | \
- grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__')
-MENDIAN:=$(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian)
-BPF_TARGET_ENDIAN:=$(if $(IS_LITTLE_ENDIAN),--target=bpfel,--target=bpfeb)
-
ifneq ($(CROSS_COMPILE),)
CLANG_TARGET_ARCH = --target=$(notdir $(CROSS_COMPILE:%-=%))
endif
CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH))
-BPF_CFLAGS = -g -Wall -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) \
- -I$(INCLUDE_DIR) -I$(CURDIR) -I$(APIDIR) \
- -I$(TOOLSINCDIR) -I$(CURDIR)/libarena/include \
- -I$(abspath $(OUTPUT)/../usr/include) \
- -std=gnu11 \
- -fno-strict-aliasing \
- -Wno-microsoft-anon-tag \
- -fms-extensions \
- -Wno-compare-distinct-pointer-types \
- -Wno-initializer-overrides \
- #
-# TODO: enable me -Wsign-compare
-
CLANG_CFLAGS = $(CLANG_SYS_INCLUDES)
# Build BPF object using Clang
@@ -759,10 +635,7 @@ $(OUTPUT)/$(TRUNNER_BINARY): $(if $(filter test_progs%,$1),$(if $(PERMISSIVE),$$
endef
-VERIFY_SIG_SETUP := $(CURDIR)/verify_sig_setup.sh
VERIFY_SIG_HDR := verification_cert.h
-VERIFICATION_CERT := $(BUILD_DIR)/signing_key.der
-PRIVATE_KEY := $(BUILD_DIR)/signing_key.pem
# genkey writes both outputs. Pattern rules group them even on make
# versions before 4.3, preventing concurrent genkey invocations.
@@ -796,7 +669,6 @@ LIBARENA_COMMON_DEPS := $(wildcard libarena/Makefile \
LIBARENA_BPF_DEPS := $(LIBARENA_COMMON_DEPS) $(wildcard libarena/selftests/*)
LIBARENA_BENCH_BPF_DEPS := $(LIBARENA_COMMON_DEPS) $(wildcard libarena/benchs/*)
-LIBARENA_SKEL := libarena/libarena.skel.h
LIBARENA_BENCH_SKEL := libarena/libarena_bench.skel.h
$(LIBARENA_SKEL): $(INCLUDE_DIR)/vmlinux.h $(BPFOBJ) $(LIBARENA_BPF_DEPS)
@@ -806,9 +678,6 @@ $(LIBARENA_BENCH_SKEL): $(INCLUDE_DIR)/vmlinux.h $(BPFOBJ) $(LIBARENA_BENCH_BPF_
+$(MAKE) -C libarena benchmarks $(LIBARENA_MAKE_ARGS)
ifneq ($(CLANG_HAS_ARENA_ASAN),)
-LIBARENA_ASAN_SKEL := libarena/libarena_asan.skel.h
-CFLAGS += -DHAS_BPF_ARENA_ASAN
-
$(LIBARENA_ASAN_SKEL): $(INCLUDE_DIR)/vmlinux.h $(BPFOBJ) $(LIBARENA_BPF_DEPS)
+$(MAKE) -C libarena libarena_asan.skel.h $(LIBARENA_MAKE_ARGS)
endif
diff --git a/tools/testing/selftests/bpf/Makefile.buildvars b/tools/testing/selftests/bpf/Makefile.buildvars
new file mode 100644
index 000000000000..b7e4d7e678ac
--- /dev/null
+++ b/tools/testing/selftests/bpf/Makefile.buildvars
@@ -0,0 +1,150 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Toolchain, path and flag definitions for the BPF selftests build,
+# kept apart from the rules so that more than one makefile can include
+# them. Included after ../lib.mk - the note above the Makefile's include
+# explains how the flags are ordered around it.
+
+TOOLSDIR := $(abspath ../../..)
+LIBDIR := $(TOOLSDIR)/lib
+BPFDIR := $(LIBDIR)/bpf
+TOOLSINCDIR := $(TOOLSDIR)/include
+TOOLSARCHINCDIR := $(TOOLSDIR)/arch/$(SRCARCH)/include
+APIDIR := $(TOOLSINCDIR)/uapi
+ifneq ($(O),)
+GENDIR := $(O)/include/generated
+else
+GENDIR := $(abspath ../../../../include/generated)
+endif
+GENHDR := $(GENDIR)/autoconf.h
+PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config
+
+ifneq ($(wildcard $(GENHDR)),)
+ GENFLAGS := -DHAVE_GENHDR
+endif
+
+ifdef ASAN
+SAN_CFLAGS ?= -fsanitize=address -fno-omit-frame-pointer
+else
+SAN_CFLAGS ?=
+endif
+SAN_LDFLAGS ?= $(SAN_CFLAGS)
+RELEASE ?=
+OPT_FLAGS ?= $(if $(RELEASE),-O2,-O0)
+
+LIBELF_CFLAGS := $(shell $(PKG_CONFIG) libelf --cflags 2>/dev/null)
+LIBELF_LIBS := $(shell $(PKG_CONFIG) libelf --libs 2>/dev/null || echo -lelf)
+
+# When BPF_STRICT_BUILD is 1, any BPF object, skeleton, test object, or
+# benchmark compilation failure is fatal. Set to 0 to tolerate failures
+# and continue building the remaining tests.
+BPF_STRICT_BUILD ?= 1
+PERMISSIVE := $(filter 0,$(BPF_STRICT_BUILD))
+
+# Permissive-mode recipe suffix: on failure, remove the target, emit a
+# SKIP marker and report success so the rest of the build continues.
+# $(1) - SKIP tag (BPF, TEST, BENCH, SKEL, LINK, ...)
+# $(2) - optional extra files to remove alongside the target
+# $(3) - optional note appended to the SKIP message
+skip_on_fail = $(if $(PERMISSIVE),|| { $(RM) $@ $(2); \
+ printf ' %-12s %s\n' 'SKIP-$(1)' '$(notdir $@)$(if $(3), $(3))' 1>&2; })
+
+# Permissive-mode recipe prefix: when a prerequisite object is missing
+# (its compile failed and was skipped), remove the target and $(3),
+# emit a SKIP marker and report success without running the rest of
+# the recipe.
+# $(1) - SKIP tag
+# $(2) - input files to check
+# $(3) - optional extra files to remove alongside the target
+skip_if_missing = $(if $(PERMISSIVE),for f in $(2); do [ -f $$f ] || { \
+ $(RM) $@ $(3); \
+ printf ' %-12s %s\n' 'SKIP-$(1)' '$(notdir $@)' 1>&2; exit 0; }; done;)
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+endif
+
+COMMON_CFLAGS = -g $(OPT_FLAGS) -rdynamic -std=gnu11 \
+ -Wall -Werror -fno-omit-frame-pointer \
+ -Wno-unused-but-set-variable \
+ $(GENFLAGS) $(SAN_CFLAGS) $(LIBELF_CFLAGS) \
+ -I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \
+ -I$(TOOLSINCDIR) -I$(TOOLSARCHINCDIR) -I$(APIDIR) -I$(OUTPUT) \
+ -I$(CURDIR)/libarena/include
+LDLIBS += $(LIBELF_LIBS) -lz -lrt -lpthread
+
+PCAP_CFLAGS := $(shell $(PKG_CONFIG) --cflags libpcap 2>/dev/null && echo "-DTRAFFIC_MONITOR=1")
+PCAP_LIBS := $(shell $(PKG_CONFIG) --libs libpcap 2>/dev/null)
+LDLIBS += $(PCAP_LIBS)
+
+ifneq ($(LLVM),)
+# Silence some warnings when compiled with clang
+CLANG_WARN_CFLAGS := -Wno-unused-command-line-argument
+endif
+
+# Check whether clang supports BPF address sanitizer (requires LLVM 22+).
+# This runs after ../lib.mk has resolved CLANG from LLVM=<suffix or path>,
+# so it probes the compiler that builds the BPF objects.
+CLANG_HAS_ARENA_ASAN := $(shell echo 'int x;' | \
+ $(CLANG) --target=bpf -fsanitize=kernel-address \
+ -mllvm -asan-shadow-addr-space=1 \
+ -x c -c - -o /dev/null 2>/dev/null && echo 1)
+
+SCRATCH_DIR := $(OUTPUT)/tools
+BUILD_DIR := $(SCRATCH_DIR)/build
+INCLUDE_DIR := $(SCRATCH_DIR)/include
+BPFOBJ := $(BUILD_DIR)/libbpf/libbpf.a
+ifneq ($(CROSS_COMPILE),)
+HOST_BUILD_DIR := $(BUILD_DIR)/host
+HOST_SCRATCH_DIR := $(OUTPUT)/host-tools
+HOST_INCLUDE_DIR := $(HOST_SCRATCH_DIR)/include
+else
+HOST_BUILD_DIR := $(BUILD_DIR)
+HOST_SCRATCH_DIR := $(SCRATCH_DIR)
+HOST_INCLUDE_DIR := $(INCLUDE_DIR)
+endif
+RESOLVE_BTFIDS := $(HOST_BUILD_DIR)/resolve_btfids/resolve_btfids
+
+DEFAULT_BPFTOOL := $(HOST_SCRATCH_DIR)/sbin/bpftool
+ifneq ($(CROSS_COMPILE),)
+CROSS_BPFTOOL := $(SCRATCH_DIR)/sbin/bpftool
+TRUNNER_BPFTOOL := $(CROSS_BPFTOOL)
+USE_BOOTSTRAP := ""
+else
+TRUNNER_BPFTOOL := $(DEFAULT_BPFTOOL)
+USE_BOOTSTRAP := "bootstrap/"
+endif
+
+BPFTOOL ?= $(DEFAULT_BPFTOOL)
+
+# Determine target endianness.
+IS_LITTLE_ENDIAN := $(shell $(CC) -dM -E - </dev/null | \
+ grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__')
+MENDIAN:=$(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian)
+
+BPF_CFLAGS = -g -Wall -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) \
+ -I$(INCLUDE_DIR) -I$(CURDIR) -I$(APIDIR) \
+ -I$(TOOLSINCDIR) -I$(CURDIR)/libarena/include \
+ -I$(abspath $(OUTPUT)/../usr/include) \
+ -std=gnu11 \
+ -fno-strict-aliasing \
+ -Wno-microsoft-anon-tag \
+ -fms-extensions \
+ -Wno-compare-distinct-pointer-types \
+ -Wno-initializer-overrides \
+ #
+# TODO: enable me -Wsign-compare
+
+VERIFY_SIG_SETUP := $(CURDIR)/verify_sig_setup.sh
+VERIFICATION_CERT := $(BUILD_DIR)/signing_key.der
+PRIVATE_KEY := $(BUILD_DIR)/signing_key.pem
+
+LIBARENA_SKEL := libarena/libarena.skel.h
+
+ifneq ($(CLANG_HAS_ARENA_ASAN),)
+LIBARENA_ASAN_SKEL := libarena/libarena_asan.skel.h
+CFLAGS += -DHAS_BPF_ARENA_ASAN
+endif
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH bpf-next v8 9/9] selftests/bpf: build each test runner instance in its own sub-make
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
` (7 preceding siblings ...)
2026-09-21 7:58 ` [PATCH bpf-next v8 8/9] selftests/bpf: move shared build definitions into Makefile.buildvars Mykola Lysenko
@ 2026-09-21 7:58 ` Mykola Lysenko
2026-09-21 9:22 ` bot+bpf-ci
2026-09-21 9:28 ` [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Kumar Kartikeya Dwivedi
2026-09-21 9:30 ` patchwork-bot+netdevbpf
10 siblings, 1 reply; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 7:58 UTC (permalink / raw)
To: bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko
Replace DEFINE_TEST_RUNNER/DEFINE_TEST_RUNNER_RULES with
Makefile.runner, invoked once per test runner instance. Each invocation
uses ordinary make rules in a single-flavor namespace.
The main Makefile owns shared build outputs and the kselftest
run/install rules. Makefile.skel supplies the BPF object and skeleton
rules used by both the main Makefile and the runners. The main Makefile
builds the default flavor before invoking unflavored runners; flavored
runners build in separate directories.
Build shared userspace objects once and link them into every flavor.
Order their compilation after the bpftool sub-build, which installs the
libbpf-internal headers they include. Pass the assembled CFLAGS and
LDFLAGS to runners on their command lines.
Build and copy runtime fixtures alongside runner compilation so module
builds do not delay runner startup. They are prerequisites of the
test_progs, test_progs-<flavor> and all goals rather than of the runner
binaries, so a goal spelled as a binary's path builds the binary alone.
Installation copies the default flavor's BPF objects, preserving the
previous result.
Generate prog_tests/tests.h and map_tests/tests.h through ordinary
recipes, avoiding generation during make -n. Signed skeletons explicitly
depend on the private key. The flavored runners' objects and the test
objects are targets of the sub-makes only, and the bare linked-object
names (make linked_funcs1.bpf.o) are no longer targets. Build-log
details change: skeleton messages adopt the common format and output
stream, the shared objects log as CC, the fixture copy prints no
EXT-COPY line and TEST-HDR carries no runner tag.
Co-developed-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Assisted-by: Claude:claude-fable-5 shellcheck
Signed-off-by: Mykola Lysenko <nickolay.lysenko@gmail.com>
---
tools/testing/selftests/bpf/Makefile | 501 ++++++------------
.../testing/selftests/bpf/Makefile.buildvars | 16 +-
tools/testing/selftests/bpf/Makefile.runner | 125 +++++
tools/testing/selftests/bpf/Makefile.skel | 139 +++++
4 files changed, 428 insertions(+), 353 deletions(-)
create mode 100644 tools/testing/selftests/bpf/Makefile.runner
create mode 100644 tools/testing/selftests/bpf/Makefile.skel
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 25a21247a1ba..afa589a27b15 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -10,9 +10,6 @@ SKIP_LLVM ?=
SKIP_LIBBFD ?=
SKIP_CRYPTO ?=
-# Some utility functions use LLVM libraries
-jit_disasm_helpers.c-CFLAGS = $(LLVM_CFLAGS)
-
# Check whether bpf cpu=v4 is supported or not by clang
ifneq ($(shell $(CLANG) --target=bpf -mcpu=help 2>&1 | grep 'v4'),)
CLANG_CPUV4 := 1
@@ -29,16 +26,6 @@ TEST_INST_SUBDIRS := no_alu32
ifneq ($(BPF_GCC),)
TEST_GEN_PROGS += test_progs-bpf_gcc
TEST_INST_SUBDIRS += bpf_gcc
-
-# The following tests contain C code that, although technically legal,
-# triggers GCC warnings that cannot be disabled: declaration of
-# anonymous struct types in function parameter lists.
-progs/btf_dump_test_case_bitfields.c-bpf_gcc-CFLAGS := -Wno-error
-progs/btf_dump_test_case_namespacing.c-bpf_gcc-CFLAGS := -Wno-error
-progs/btf_dump_test_case_packing.c-bpf_gcc-CFLAGS := -Wno-error
-progs/btf_dump_test_case_padding.c-bpf_gcc-CFLAGS := -Wno-error
-progs/btf_dump_test_case_syntax.c-bpf_gcc-CFLAGS := -Wno-error
-
endif
ifneq ($(CLANG_CPUV4),)
@@ -150,6 +137,9 @@ ifeq ($(feature-llvm),1)
endif
endif
+# Some utility functions use LLVM libraries
+$(OUTPUT)/jit_disasm_helpers.o: CFLAGS += $(LLVM_CFLAGS)
+
VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \
$(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \
../../../../vmlinux \
@@ -168,7 +158,7 @@ $(notdir $(TEST_GEN_PROGS) $(TEST_KMODS) \
$(TEST_GEN_PROGS_EXTENDED)): %: $(OUTPUT)/% ;
# sort removes libbpf duplicates when not cross-building
-MAKE_DIRS := $(sort $(BUILD_DIR)/libbpf $(HOST_BUILD_DIR)/libbpf \
+MAKE_DIRS := $(sort $(OUTPUT) $(BUILD_DIR)/libbpf $(HOST_BUILD_DIR)/libbpf \
$(BUILD_DIR)/bpftool $(HOST_BUILD_DIR)/bpftool \
$(HOST_BUILD_DIR)/resolve_btfids \
$(INCLUDE_DIR))
@@ -252,9 +242,27 @@ $(OUTPUT)/test_tcpnotify_user: $(CGROUP_HELPERS) $(TESTING_HELPERS) $(TRACE_HELP
$(OUTPUT)/test_sock_fields: $(CGROUP_HELPERS) $(TESTING_HELPERS)
$(OUTPUT)/test_tag: $(TESTING_HELPERS)
$(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS) flow_dissector_load.h
-$(OUTPUT)/test_maps: $(TESTING_HELPERS)
$(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS) $(UNPRIV_HELPERS)
-$(OUTPUT)/xsk.o: $(BPFOBJ)
+
+# Defined ahead of the first rule that lists it as a prerequisite.
+VERIFY_SIG_HDR := verification_cert.h
+
+# The userspace objects the runner instances link (RUNNER_OBJS, see
+# Makefile.buildvars) are built here, once, so that no runner sub-make
+# ever writes a file this Makefile also builds.
+#
+# Helper C files include headers installed to $(INCLUDE_DIR) by the
+# $(TRUNNER_BPFTOOL) and $(BPFOBJ) targets.
+RUNNER_OBJS := $(sort $(RUNNER_OBJS-test_progs) $(RUNNER_OBJS-test_maps))
+$(RUNNER_OBJS): $(VERIFY_SIG_HDR) $(BPFOBJ) $(TRUNNER_BPFTOOL)
+$(OUTPUT)/test_progs.o: prog_tests/tests.h
+$(OUTPUT)/test_maps.o: map_tests/tests.h
+
+# find_bit.c is the only runner source outside this directory, so it
+# needs a rule of its own.
+$(OUTPUT)/find_bit.o: $(TOOLSDIR)/lib/find_bit.c
+ $(call msg,CC,,$@)
+ $(Q)$(CC) $(CFLAGS) -c $< $(LDLIBS) -o $@
$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
$(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool
@@ -323,7 +331,7 @@ endif
# vmlinux.h is first dumped to a temporary file and then compared to
# the previous version. This helps to avoid unnecessary re-builds of
-# $(TRUNNER_BPF_OBJS)
+# BPF objects.
$(INCLUDE_DIR)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR)
ifeq ($(VMLINUX_H),)
$(call msg,GEN,,$@)
@@ -369,274 +377,6 @@ endif
CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH))
CLANG_CFLAGS = $(CLANG_SYS_INCLUDES)
-# Build BPF object using Clang
-# $1 - input .c file
-# $2 - output .o file
-# $3 - CFLAGS
-# $4 - binary name
-define CLANG_BPF_BUILD_RULE
- $(call msg,CLNG-BPF,$4,$2)
- $(Q)$(CLANG) $3 -O2 $(BPF_TARGET_ENDIAN) -c $1 -mcpu=v3 -o $2 $(call skip_on_fail,BPF)
-endef
-# Similar to CLANG_BPF_BUILD_RULE, but with disabled alu32
-define CLANG_NOALU32_BPF_BUILD_RULE
- $(call msg,CLNG-BPF,$4,$2)
- $(Q)$(CLANG) $3 -O2 $(BPF_TARGET_ENDIAN) -c $1 -mcpu=v2 -o $2 $(call skip_on_fail,BPF)
-endef
-# Similar to CLANG_BPF_BUILD_RULE, but with cpu-v4
-define CLANG_CPUV4_BPF_BUILD_RULE
- $(call msg,CLNG-BPF,$4,$2)
- $(Q)$(CLANG) $3 -O2 $(BPF_TARGET_ENDIAN) -c $1 -mcpu=v4 -o $2 $(call skip_on_fail,BPF)
-endef
-# Build BPF object using GCC
-define GCC_BPF_BUILD_RULE
- $(call msg,GCC-BPF,$4,$2)
- $(Q)$(BPF_GCC) $3 -DBPF_NO_PRESERVE_ACCESS_INDEX -Wno-attributes -O2 -c $1 -o $2 $(call skip_on_fail,BPF)
-endef
-
-SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
-
-LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h \
- linked_vars.skel.h linked_maps.skel.h \
- test_subskeleton.skel.h test_subskeleton_lib.skel.h \
- test_usdt.skel.h tracing_multi.skel.h \
- tracing_multi_module.skel.h \
- tracing_multi_intersect.skel.h \
- tracing_multi_session.skel.h
-
-LSKELS := fexit_sleep.c trace_printk.c trace_vprintk.c map_ptr_kern.c \
- core_kern.c core_kern_overflow.c test_ringbuf.c \
- test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c \
- test_ringbuf_overwrite.c
-
-LSKELS_SIGNED := fentry_test.c fexit_test.c atomics.c
-
-# Generate both light skeleton and libbpf skeleton for these
-LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \
- kfunc_call_test_subprog.c test_global_percpu_data.c
-SKEL_BLACKLIST += $$(LSKELS) $$(LSKELS_SIGNED)
-
-test_static_linked.skel.h-deps := test_static_linked1.bpf.o test_static_linked2.bpf.o
-linked_funcs.skel.h-deps := linked_funcs1.bpf.o linked_funcs2.bpf.o
-linked_vars.skel.h-deps := linked_vars1.bpf.o linked_vars2.bpf.o
-linked_maps.skel.h-deps := linked_maps1.bpf.o linked_maps2.bpf.o
-# In the subskeleton case, we want the test_subskeleton_lib.subskel.h file
-# but that's created as a side-effect of the skel.h generation.
-test_subskeleton.skel.h-deps := test_subskeleton_lib2.bpf.o test_subskeleton_lib.bpf.o test_subskeleton.bpf.o
-test_subskeleton_lib.skel.h-deps := test_subskeleton_lib2.bpf.o test_subskeleton_lib.bpf.o
-test_usdt.skel.h-deps := test_usdt.bpf.o test_usdt_multispec.bpf.o
-tracing_multi.skel.h-deps := tracing_multi_attach.bpf.o tracing_multi_check.bpf.o
-tracing_multi_module.skel.h-deps := tracing_multi_attach_module.bpf.o tracing_multi_check.bpf.o
-tracing_multi_intersect.skel.h-deps := tracing_multi_intersect_attach.bpf.o tracing_multi_check.bpf.o
-tracing_multi_session.skel.h-deps := tracing_multi_session_attach.bpf.o tracing_multi_check.bpf.o
-
-LINKED_BPF_OBJS := $(foreach skel,$(LINKED_SKELS),$($(skel)-deps))
-LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.c,$(LINKED_BPF_OBJS))
-
-HEADERS_FOR_BPF_OBJS := $(wildcard $(BPFDIR)/*.bpf.h) \
- $(wildcard $(CURDIR)/libarena/include/*.[ch]) \
- $(addprefix $(BPFDIR)/, bpf_core_read.h \
- bpf_endian.h \
- bpf_helpers.h \
- bpf_tracing.h)
-
-# Set up extra TRUNNER_XXX "temporary" variables in the environment (relies on
-# $eval()) and pass control to DEFINE_TEST_RUNNER_RULES.
-# Parameters:
-# $1 - test runner base binary name (e.g., test_progs)
-# $2 - test runner extra "flavor" (e.g., no_alu32, cpuv4, bpf_gcc, etc)
-define DEFINE_TEST_RUNNER
-
-TRUNNER_OUTPUT := $(OUTPUT)$(if $2,/)$2
-TRUNNER_BINARY := $1$(if $2,-)$2
-TRUNNER_TEST_OBJS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.test.o, \
- $$(notdir $$(wildcard $(TRUNNER_TESTS_DIR)/*.c)))
-TRUNNER_EXTRA_OBJS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.o, \
- $$(filter %.c,$(TRUNNER_EXTRA_SOURCES)))
-TRUNNER_LIB_OBJS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.o, \
- $$(filter %.c,$(TRUNNER_LIB_SOURCES)))
-TRUNNER_EXTRA_HDRS := $$(filter %.h,$(TRUNNER_EXTRA_SOURCES))
-TRUNNER_TESTS_HDR := $(TRUNNER_TESTS_DIR)/tests.h
-TRUNNER_BPF_SRCS := $$(notdir $$(wildcard $(TRUNNER_BPF_PROGS_DIR)/*.c))
-TRUNNER_BPF_OBJS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.bpf.o, $$(TRUNNER_BPF_SRCS))
-TRUNNER_BPF_SKELS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.skel.h, \
- $$(filter-out $(SKEL_BLACKLIST) $(LINKED_BPF_SRCS),\
- $$(TRUNNER_BPF_SRCS)))
-TRUNNER_BPF_LSKELS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.lskel.h, $$(LSKELS) $$(LSKELS_EXTRA))
-TRUNNER_BPF_SKELS_LINKED := $$(addprefix $$(TRUNNER_OUTPUT)/,$(LINKED_SKELS))
-TRUNNER_BPF_LSKELS_SIGNED := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.lskel.h, $$(LSKELS_SIGNED))
-TEST_GEN_FILES += $$(TRUNNER_BPF_OBJS)
-
-# Evaluate rules now with extra TRUNNER_XXX variables above already defined
-$$(eval $$(call DEFINE_TEST_RUNNER_RULES,$1,$2))
-
-endef
-
-# Using TRUNNER_XXX variables, provided by callers of DEFINE_TEST_RUNNER and
-# set up by DEFINE_TEST_RUNNER itself, create test runner build rules with:
-# $1 - test runner base binary name (e.g., test_progs)
-# $2 - test runner extra "flavor" (e.g., no_alu32, cpuv4, bpf_gcc, etc)
-define DEFINE_TEST_RUNNER_RULES
-
-# Permissive build behaviour (skip-on-failure compile, partial-link) only
-# applies to test_progs and its flavors; runners that use strong cross-object
-# references (e.g. test_maps) keep strict semantics even when permissive.
-# The check is inlined per-runner so $1 is substituted at $(call) time and
-# the result is baked into each rule's recipe.
-
-ifeq ($($(TRUNNER_OUTPUT)-dir),)
-$(TRUNNER_OUTPUT)-dir := y
-$(TRUNNER_OUTPUT):
- $$(call msg,MKDIR,,$$@)
- $(Q)mkdir -p $$@
-endif
-
-# ensure we set up BPF objects generation rule just once for a given
-# input/output directory combination
-ifeq ($($(TRUNNER_BPF_PROGS_DIR)$(if $2,-)$2-bpfobjs),)
-$(TRUNNER_BPF_PROGS_DIR)$(if $2,-)$2-bpfobjs := y
-$(TRUNNER_BPF_OBJS): $(TRUNNER_OUTPUT)/%.bpf.o: \
- $(TRUNNER_BPF_PROGS_DIR)/%.c \
- $(TRUNNER_BPF_PROGS_DIR)/*.h \
- $$(INCLUDE_DIR)/vmlinux.h \
- $(HEADERS_FOR_BPF_OBJS) \
- | $(TRUNNER_OUTPUT) $$(BPFOBJ)
- $$(call $(TRUNNER_BPF_BUILD_RULE),$$<,$$@, \
- $(TRUNNER_BPF_CFLAGS) \
- $$($$<-CFLAGS) \
- $$($$<-$2-CFLAGS),$(TRUNNER_BINARY))
-
-$(TRUNNER_BPF_SKELS): %.skel.h: %.bpf.o $(BPFTOOL) gen_bpf_skel.sh | $(TRUNNER_OUTPUT)
- $(Q)$$(call skip_if_missing,SKEL,$$<,$$(@:.skel.h=.subskel.h)) \
- printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY)] $$(notdir $$@)' 1>&2; \
- BPFTOOL=$$(BPFTOOL) ./gen_bpf_skel.sh \
- --name $$(notdir $$(<:.bpf.o=)) \
- --skel $$@ --subskel $$(@:.skel.h=.subskel.h) $$< $$(call skip_on_fail,SKEL,$$(@:.skel.h=.subskel.h))
-
-$(TRUNNER_BPF_LSKELS): %.lskel.h: %.bpf.o $(BPFTOOL) gen_bpf_skel.sh | $(TRUNNER_OUTPUT)
- $(Q)$$(call skip_if_missing,SKEL,$$<) \
- printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY)] $$(notdir $$@)' 1>&2; \
- BPFTOOL=$$(BPFTOOL) ./gen_bpf_skel.sh \
- --name $$(notdir $$(<:.bpf.o=_lskel)) --lskel \
- --skel $$@ $$< $$(call skip_on_fail,SKEL)
-
-$(TRUNNER_BPF_LSKELS_SIGNED): %.lskel.h: %.bpf.o $(BPFTOOL) $(VERIFICATION_CERT) gen_bpf_skel.sh | $(TRUNNER_OUTPUT)
- $(Q)$$(call skip_if_missing,SKEL,$$<) \
- printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY) (signed)] $$(notdir $$@)' 1>&2; \
- BPFTOOL=$$(BPFTOOL) PRIVATE_KEY=$(PRIVATE_KEY) \
- VERIFICATION_CERT=$(VERIFICATION_CERT) \
- ./gen_bpf_skel.sh --sign \
- --name $$(notdir $$(<:.bpf.o=_lskel)) \
- --skel $$@ $$< $$(call skip_on_fail,SKEL)
-
-$(LINKED_BPF_OBJS): %: $(TRUNNER_OUTPUT)/%
-
-# .SECONDEXPANSION here allows to correctly expand %-deps variables as prerequisites
-.SECONDEXPANSION:
-$(TRUNNER_BPF_SKELS_LINKED): $(TRUNNER_OUTPUT)/%: $$$$(%-deps) $(BPFTOOL) gen_bpf_skel.sh | $(TRUNNER_OUTPUT)
- $(Q)$$(call skip_if_missing,SKEL,$$(addprefix $(TRUNNER_OUTPUT)/,$$($$(@F)-deps)),$$(@:.skel.h=.subskel.h)) \
- printf ' %-12s %s\n' 'LINK-BPF' '[$(TRUNNER_BINARY)] $$(notdir $$(@:.skel.h=.bpf.o))' 1>&2; \
- printf ' %-12s %s\n' 'GEN-SKEL' '[$(TRUNNER_BINARY)] $$(notdir $$@)' 1>&2; \
- BPFTOOL=$$(BPFTOOL) ./gen_bpf_skel.sh \
- --name $$(notdir $$(@:.skel.h=)) \
- --skel $$@ --subskel $$(@:.skel.h=.subskel.h) \
- $$(addprefix $(TRUNNER_OUTPUT)/,$$($$(@F)-deps)) $$(call skip_on_fail,SKEL,$$(@:.skel.h=.subskel.h))
-
-# When the compiler generates a %.d file, only skel basenames (not
-# full paths) are specified as prerequisites for corresponding %.o
-# file. vpath directives below instruct make to search for skel files
-# in TRUNNER_OUTPUT, if they are not present in the working directory.
-vpath %.skel.h $(TRUNNER_OUTPUT)
-vpath %.lskel.h $(TRUNNER_OUTPUT)
-vpath %.subskel.h $(TRUNNER_OUTPUT)
-
-endif
-
-# ensure we set up tests.h header generation rule just once
-ifeq ($($(TRUNNER_TESTS_DIR)-tests-hdr),)
-$(TRUNNER_TESTS_DIR)-tests-hdr := y
-$(TRUNNER_TESTS_HDR): $(TRUNNER_TESTS_DIR)/*.c
- $$(call msg,TEST-HDR,$(TRUNNER_BINARY),$$@)
- $$(shell (echo '/* Generated header, do not edit */'; \
- sed -n -E 's/^void (serial_)?test_([a-zA-Z0-9_]+)\((void)?\).*/DEFINE_TEST(\2)/p' \
- $(TRUNNER_TESTS_DIR)/*.c | sort ; \
- ) > $$@)
-endif
-
-$(TRUNNER_OUTPUT)/resolve_btfids.test.o: $(RESOLVE_BTFIDS) $(TRUNNER_OUTPUT)/btf_data.bpf.o
-$(TRUNNER_OUTPUT)/resolve_btfids.test.o: private TEST_NEEDS_BTFIDS = 1
-
-# compile individual test files
-# Note: we cd into output directory to ensure embedded BPF object is found
-$(TRUNNER_TEST_OBJS): $(TRUNNER_OUTPUT)/%.test.o: \
- $(TRUNNER_TESTS_DIR)/%.c \
- | $(TRUNNER_OUTPUT)/%.test.d
- $$(call msg,TEST-OBJ,$(TRUNNER_BINARY),$$@)
- $(Q)(cd $$(@D) && $$(CC) -I. $$(CFLAGS) -MMD -MT $$@ -c $(CURDIR)/$$< $$(LDLIBS) -o $$(@F)) $(if $(filter test_progs%,$1),$$(call skip_on_fail,TEST))
- $$(if $$(TEST_NEEDS_BTFIDS), \
- $(Q)if [ -f $$@ ]; then \
- $(if $(filter 1,$(V)),true,printf ' %-8s%s %s\n' "BTFIDS" " [$(TRUNNER_BINARY)]" "$$(notdir $$@)"); \
- $(RESOLVE_BTFIDS) --btf $(TRUNNER_OUTPUT)/btf_data.bpf.o $$@; \
- $(RESOLVE_BTFIDS) --patch_btfids $$@.BTF_ids $$@; \
- fi)
-
-$(TRUNNER_TEST_OBJS:.o=.d): $(TRUNNER_OUTPUT)/%.test.d: \
- $(TRUNNER_TESTS_DIR)/%.c \
- $(TRUNNER_EXTRA_HDRS) \
- $$(BPFOBJ) | $(TRUNNER_OUTPUT) \
- $(TRUNNER_BPF_SKELS) \
- $(TRUNNER_BPF_LSKELS) \
- $(TRUNNER_BPF_LSKELS_SIGNED) \
- $(TRUNNER_BPF_SKELS_LINKED)
-
-ifeq ($(filter clean docs-clean emit_tests,$(MAKECMDGOALS)),)
-include $(wildcard $(TRUNNER_TEST_OBJS:.o=.d))
-endif
-
-# add per extra obj CFGLAGS definitions
-$(foreach N,$(patsubst $(TRUNNER_OUTPUT)/%.o,%,$(TRUNNER_EXTRA_OBJS)), \
- $(eval $(TRUNNER_OUTPUT)/$(N).o: CFLAGS += $($(N).c-CFLAGS)))
-
-$(TRUNNER_EXTRA_OBJS): $(TRUNNER_OUTPUT)/%.o: \
- %.c \
- $(TRUNNER_EXTRA_HDRS) \
- $(VERIFY_SIG_HDR) \
- $(TRUNNER_TESTS_HDR) \
- $$(BPFOBJ) | $(TRUNNER_OUTPUT)
- $$(call msg,EXT-OBJ,$(TRUNNER_BINARY),$$@)
- $(Q)$$(CC) $$(CFLAGS) -c $$< $$(LDLIBS) -o $$@
-
-$(TRUNNER_LIB_OBJS): $(TRUNNER_OUTPUT)/%.o:$(TOOLSDIR)/lib/%.c
- $$(call msg,LIB-OBJ,$(TRUNNER_BINARY),$$@)
- $(Q)$$(CC) $$(CFLAGS) -c $$< $$(LDLIBS) -o $$@
-
-# non-flavored in-srctree builds receive special treatment, in particular, we
-# do not need to copy extra resources (see e.g. test_btf_dump_case())
-$(TRUNNER_BINARY)-extras: $(TRUNNER_EXTRA_FILES) | $(TRUNNER_OUTPUT)
-ifneq ($2:$(OUTPUT),:$(shell pwd))
- $$(call msg,EXT-COPY,$(TRUNNER_BINARY),$(TRUNNER_EXTRA_FILES))
- $(Q)rsync -aq $(if $(PERMISSIVE),--ignore-missing-args) $$^ $(TRUNNER_OUTPUT)/
-endif
-
-# some X.test.o files have runtime dependencies on Y.bpf.o files
-$(OUTPUT)/$(TRUNNER_BINARY): | $(TRUNNER_BPF_OBJS)
-
-$(OUTPUT)/$(TRUNNER_BINARY): $(if $(filter test_progs%,$1),$(if $(PERMISSIVE),$$(wildcard $(TRUNNER_TEST_OBJS)),$(TRUNNER_TEST_OBJS)),$(TRUNNER_TEST_OBJS)) \
- $(TRUNNER_EXTRA_OBJS) $$(BPFOBJ) \
- $(TRUNNER_LIB_OBJS) \
- $(TRUNNER_BPFTOOL) \
- $(OUTPUT)/veristat \
- | $(TRUNNER_BINARY)-extras \
- $(if $(filter test_progs%,$1),$(if $(PERMISSIVE),$(TRUNNER_TEST_OBJS)))
- $$(call msg,BINARY,,$$@)
- $(Q)$$(CC) $$(CFLAGS) $(if $(filter test_progs%,$1),$(if $(PERMISSIVE),$$(filter %.a %.o,$$(wildcard $(TRUNNER_TEST_OBJS)) $$(filter-out $(TRUNNER_TEST_OBJS),$$^)),$$(filter %.a %.o,$$^)),$$(filter %.a %.o,$$^)) $$(LDLIBS) $$(LLVM_LDLIBS) $$(LDFLAGS) $$(LLVM_LDFLAGS) -o $$@
- $(Q)ln -sf $(if $2,..,.)/tools/build/bpftool/$(USE_BOOTSTRAP)bpftool \
- $(OUTPUT)/$(if $2,$2/)bpftool
-
-endef
-
-VERIFY_SIG_HDR := verification_cert.h
-
# genkey writes both outputs. Pattern rules group them even on make
# versions before 4.3, preventing concurrent genkey invocations.
# Restrict the pattern to *_key files because genkey uses fixed names.
@@ -682,78 +422,137 @@ $(LIBARENA_ASAN_SKEL): $(INCLUDE_DIR)/vmlinux.h $(BPFOBJ) $(LIBARENA_BPF_DEPS)
+$(MAKE) -C libarena libarena_asan.skel.h $(LIBARENA_MAKE_ARGS)
endif
-# Define test_progs test runner.
-TRUNNER_TESTS_DIR := prog_tests
-TRUNNER_BPF_PROGS_DIR := progs
-TRUNNER_EXTRA_SOURCES := test_progs.c \
- cgroup_helpers.c \
- trace_helpers.c \
- network_helpers.c \
- testing_helpers.c \
- btf_helpers.c \
- cap_helpers.c \
- unpriv_helpers.c \
- sysctl_helpers.c \
- netlink_helpers.c \
- jit_disasm_helpers.c \
- io_helpers.c \
- test_loader.c \
- xsk.c \
- disasm.c \
- disasm_helpers.c \
- json_writer.c \
- $(VERIFY_SIG_HDR) \
- flow_dissector_load.h \
- ip_check_defrag_frags.h \
- bpftool_helpers.c \
- usdt_1.c usdt_2.c \
- $(LIBARENA_SKEL) \
- $(LIBARENA_ASAN_SKEL)
-TRUNNER_LIB_SOURCES := find_bit.c
-TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read \
- $(OUTPUT)/liburandom_read.so \
- $(OUTPUT)/xdp_synproxy \
- $(OUTPUT)/sign-file \
- $(OUTPUT)/uprobe_multi \
- $(TEST_KMOD_TARGETS) \
- ima_setup.sh \
- $(VERIFY_SIG_SETUP) \
- $(wildcard progs/btf_dump_test_case_*.c) \
- $(wildcard progs/*.bpf.o) \
- bpftool_btf_dump_sorted.expected \
- bpftool_btf_dump_unsorted.expected
-TRUNNER_BPF_BUILD_RULE := CLANG_BPF_BUILD_RULE
-TRUNNER_BPF_CFLAGS := $(BPF_CFLAGS) $(CLANG_CFLAGS) -DENABLE_ATOMICS_TESTS
-$(eval $(call DEFINE_TEST_RUNNER,test_progs))
-
-# Define test_progs-no_alu32 test runner.
-TRUNNER_BPF_BUILD_RULE := CLANG_NOALU32_BPF_BUILD_RULE
-TRUNNER_BPF_CFLAGS := $(BPF_CFLAGS) $(CLANG_CFLAGS)
-$(eval $(call DEFINE_TEST_RUNNER,test_progs,no_alu32))
-
-# Define test_progs-cpuv4 test runner.
+# Generated test list headers
+
+define gen_tests_hdr
+ $(call msg,TEST-HDR,,$@)
+ $(Q)(echo '/* Generated header, do not edit */'; \
+ sed -n -E 's/^void (serial_)?test_([a-zA-Z0-9_]+)\((void)?\).*/DEFINE_TEST(\2)/p' \
+ $(@D)/*.c | sort) > $@
+endef
+
+prog_tests/tests.h: $(wildcard prog_tests/*.c)
+ $(gen_tests_hdr)
+
+map_tests/tests.h: $(wildcard map_tests/*.c)
+ $(gen_tests_hdr)
+
+# Test runner instances, one sub-make each (see Makefile.runner).
+
+# Share LLVM probe results with runners. Pass CC explicitly to
+# runners so it does not affect libbpf's compiler selection.
+export LLVM_LDLIBS LLVM_LDFLAGS
+
+# Pass assembled flags on the command line so runner assignments
+# cannot append them again.
+RUNNER_MAKE := $(MAKE) --no-print-directory -f Makefile.runner \
+ OUTPUT=$(OUTPUT) CC='$(CC)' CLANG='$(CLANG)' \
+ CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)'
+
+# Shared inputs prepared before runner sub-makes start.
+# Also build veristat, which test_veristat executes.
+RUNNER_PREREQS := $(INCLUDE_DIR)/vmlinux.h $(BPFOBJ) $(BPFTOOL) \
+ $(TRUNNER_BPFTOOL) $(RESOLVE_BTFIDS) \
+ $(OUTPUT)/veristat \
+ $(VERIFY_SIG_HDR) $(PRIVATE_KEY) $(VERIFICATION_CERT) \
+ $(LIBARENA_SKEL) $(LIBARENA_ASAN_SKEL) \
+ prog_tests/tests.h map_tests/tests.h \
+ $(RUNNER_OBJS)
+
+# Runtime fixtures for each test_progs flavor.
+RUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read \
+ $(OUTPUT)/liburandom_read.so \
+ $(OUTPUT)/xdp_synproxy \
+ $(OUTPUT)/sign-file \
+ $(OUTPUT)/uprobe_multi \
+ $(TEST_KMOD_TARGETS) \
+ ima_setup.sh \
+ $(VERIFY_SIG_SETUP) \
+ $(wildcard progs/btf_dump_test_case_*.c) \
+ $(wildcard progs/*.bpf.o) \
+ bpftool_btf_dump_sorted.expected \
+ bpftool_btf_dump_unsorted.expected
+
+# Prepare fixtures in parallel with runner compilation.
+# Copy into flavor and out-of-tree directories; the in-tree
+# default runner uses the originals.
+RUNNER_EXTRA_DIRS := $(addprefix $(OUTPUT)/,$(TEST_INST_SUBDIRS))
+ifneq ($(realpath $(OUTPUT)),$(CURDIR))
+RUNNER_EXTRA_DIRS += $(OUTPUT)
+test_progs: $(OUTPUT)/runner-extras
+else
+test_progs: $(RUNNER_EXTRA_FILES)
+endif
+RUNNER_EXTRAS := $(addsuffix /runner-extras,$(RUNNER_EXTRA_DIRS))
+
+.PHONY: $(RUNNER_EXTRAS)
+$(RUNNER_EXTRAS): $(RUNNER_EXTRA_FILES)
+ $(Q)mkdir -p $(@D)
+ $(Q)rsync -aq $(if $(PERMISSIVE),--ignore-missing-args) \
+ $(RUNNER_EXTRA_FILES) $(@D)/
+
+all: $(RUNNER_EXTRAS)
+$(addprefix test_progs-,$(TEST_INST_SUBDIRS)): test_progs-%: \
+ $(OUTPUT)/%/runner-extras
+
+# The main Makefile cannot tell whether $(OUTPUT)/test_progs is stale -
+# only the runner sub-make knows its full dependency graph. FORCE makes
+# the delegating rules below always run; their dependents still rebuild
+# on mtime only.
+FORCE:
+
+# Build default BPF outputs here for standalone consumers and install.
+# Standalone consumers depend on individual skeletons; unflavored
+# runners depend on the complete set before their sub-makes start.
+RDIR := $(OUTPUT)
+FLAVOR :=
+BINARY := test_progs
+BPF_CC := $(CLANG)
+BPF_CC_MSG := CLNG-BPF
+BPF_SYS_INCLUDES := $(CLANG_SYS_INCLUDES)
+BPF_CC_FLAGS := -O2 $(BPF_TARGET_ENDIAN) -mcpu=v3
+BPF_DEFINES := -DENABLE_ATOMICS_TESTS
+include Makefile.skel
+
+DEFAULT_RUNNER_ARGS := RUNNER=test_progs FLAVOR= TESTS_DIR=prog_tests \
+ BPF_CC='$(BPF_CC)' BPF_CC_MSG=$(BPF_CC_MSG) \
+ BPF_SYS_INCLUDES='$(BPF_SYS_INCLUDES)' \
+ BPF_CC_FLAGS='$(BPF_CC_FLAGS)' BPF_DEFINES=$(BPF_DEFINES)
+CLANG_RUNNER_ARGS := BPF_CC='$(CLANG)' BPF_CC_MSG=CLNG-BPF \
+ BPF_SYS_INCLUDES='$(CLANG_SYS_INCLUDES)'
+
+$(OUTPUT)/test_progs: $(RUNNER_PREREQS) $(BPF_OBJS) $(ALL_SKELS) FORCE
+ +$(Q)$(RUNNER_MAKE) $(DEFAULT_RUNNER_ARGS)
+
+$(OUTPUT)/test_progs-no_alu32: $(RUNNER_PREREQS) FORCE
+ +$(Q)$(RUNNER_MAKE) RUNNER=test_progs FLAVOR=no_alu32 TESTS_DIR=prog_tests \
+ $(CLANG_RUNNER_ARGS) BPF_CC_FLAGS='-O2 $(BPF_TARGET_ENDIAN) -mcpu=v2'
+
ifneq ($(CLANG_CPUV4),)
-TRUNNER_BPF_BUILD_RULE := CLANG_CPUV4_BPF_BUILD_RULE
-TRUNNER_BPF_CFLAGS := $(BPF_CFLAGS) $(CLANG_CFLAGS) -DENABLE_ATOMICS_TESTS
-$(eval $(call DEFINE_TEST_RUNNER,test_progs,cpuv4))
+$(OUTPUT)/test_progs-cpuv4: $(RUNNER_PREREQS) FORCE
+ +$(Q)$(RUNNER_MAKE) RUNNER=test_progs FLAVOR=cpuv4 TESTS_DIR=prog_tests \
+ $(CLANG_RUNNER_ARGS) BPF_CC_FLAGS='-O2 $(BPF_TARGET_ENDIAN) -mcpu=v4' \
+ BPF_DEFINES=-DENABLE_ATOMICS_TESTS
endif
-# Define test_progs BPF-GCC-flavored test runner.
ifneq ($(BPF_GCC),)
-TRUNNER_BPF_BUILD_RULE := GCC_BPF_BUILD_RULE
-TRUNNER_BPF_CFLAGS := $(BPF_CFLAGS) $(call get_sys_includes,gcc,)
-$(eval $(call DEFINE_TEST_RUNNER,test_progs,bpf_gcc))
+# Sys includes come from the *host* gcc, not $(BPF_GCC), as the rule
+# this replaces had it.
+GCC_SYS_INCLUDES := $(call get_sys_includes,gcc,)
+
+$(OUTPUT)/test_progs-bpf_gcc: $(RUNNER_PREREQS) FORCE
+ +$(Q)$(RUNNER_MAKE) RUNNER=test_progs FLAVOR=bpf_gcc TESTS_DIR=prog_tests \
+ BPF_CC='$(BPF_GCC)' BPF_CC_MSG=GCC-BPF \
+ BPF_SYS_INCLUDES='$(GCC_SYS_INCLUDES)' \
+ BPF_CC_FLAGS='-DBPF_NO_PRESERVE_ACCESS_INDEX -Wno-attributes -O2'
endif
-# Define test_maps test runner.
-TRUNNER_TESTS_DIR := map_tests
-TRUNNER_BPF_PROGS_DIR := progs
-TRUNNER_EXTRA_SOURCES := test_maps.c
-TRUNNER_LIB_SOURCES :=
-TRUNNER_EXTRA_FILES :=
-TRUNNER_BPF_BUILD_RULE := $$(error no BPF objects should be built)
-TRUNNER_BPF_CFLAGS :=
-$(eval $(call DEFINE_TEST_RUNNER,test_maps))
+# test_maps compiles map_tests/*.c against the default flavor's skeletons
+$(OUTPUT)/test_maps: $(RUNNER_PREREQS) $(BPF_OBJS) \
+ $(ALL_SKELS) FORCE
+ +$(Q)$(RUNNER_MAKE) RUNNER=test_maps FLAVOR= TESTS_DIR=map_tests
+
+TEST_GEN_FILES += $(BPF_OBJS)
# Define test_verifier test runner.
# It is much simpler than test_maps/test_progs and sufficiently different from
diff --git a/tools/testing/selftests/bpf/Makefile.buildvars b/tools/testing/selftests/bpf/Makefile.buildvars
index b7e4d7e678ac..d2a0c0031b87 100644
--- a/tools/testing/selftests/bpf/Makefile.buildvars
+++ b/tools/testing/selftests/bpf/Makefile.buildvars
@@ -2,8 +2,9 @@
#
# Toolchain, path and flag definitions for the BPF selftests build,
# kept apart from the rules so that more than one makefile can include
-# them. Included after ../lib.mk - the note above the Makefile's include
-# explains how the flags are ordered around it.
+# them. Included by the Makefile after ../lib.mk and by Makefile.runner
+# in its place - the note above the Makefile's include explains how the
+# flags are ordered around it.
TOOLSDIR := $(abspath ../../..)
LIBDIR := $(TOOLSDIR)/lib
@@ -148,3 +149,14 @@ ifneq ($(CLANG_HAS_ARENA_ASAN),)
LIBARENA_ASAN_SKEL := libarena/libarena_asan.skel.h
CFLAGS += -DHAS_BPF_ARENA_ASAN
endif
+
+RUNNER_OBJS-test_progs := $(addprefix $(OUTPUT)/, \
+ test_progs.o cgroup_helpers.o trace_helpers.o \
+ network_helpers.o testing_helpers.o btf_helpers.o \
+ cap_helpers.o unpriv_helpers.o sysctl_helpers.o \
+ netlink_helpers.o jit_disasm_helpers.o io_helpers.o \
+ test_loader.o xsk.o disasm.o disasm_helpers.o \
+ json_writer.o bpftool_helpers.o usdt_1.o usdt_2.o \
+ find_bit.o)
+RUNNER_OBJS-test_maps := $(addprefix $(OUTPUT)/, \
+ test_maps.o testing_helpers.o)
diff --git a/tools/testing/selftests/bpf/Makefile.runner b/tools/testing/selftests/bpf/Makefile.runner
new file mode 100644
index 000000000000..d266c4246888
--- /dev/null
+++ b/tools/testing/selftests/bpf/Makefile.runner
@@ -0,0 +1,125 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Build one test_progs flavor or test_maps.
+# Invoked by the main Makefile after shared build inputs are ready.
+# Flavored outputs live in $(OUTPUT)/$(FLAVOR); unflavored outputs
+# share $(OUTPUT) with the main Makefile.
+#
+# Command-line parameters:
+# OUTPUT selftests output directory, resolved by lib.mk
+# RUNNER test_progs | test_maps
+# FLAVOR empty | no_alu32 | cpuv4 | bpf_gcc
+# TESTS_DIR prog_tests | map_tests
+# BPF_* see Makefile.skel; BPF_CC is empty for test_maps
+# CC, CLANG compilers resolved by the main Makefile
+# CFLAGS, LDFLAGS assembled flags, including lib.mk's additions
+#
+# Exported by the main Makefile:
+# LLVM_LDLIBS, LLVM_LDFLAGS: LLVM feature-probe results
+
+include ../../../build/Build.include
+include ../../../scripts/Makefile.arch
+include ../../../scripts/Makefile.include
+
+# Same message helpers as ../lib.mk, which only the top level includes.
+ifeq ($(V),1)
+Q =
+msg =
+else
+Q = @
+msg = @printf ' %-8s%s %s%s\n' "$(1)" "$(if $(2), [$(2)])" "$(notdir $(3))" "$(if $(4), $(4))";
+MAKEFLAGS += --no-print-directory
+endif
+
+include Makefile.buildvars
+
+BINARY := $(RUNNER)$(if $(FLAVOR),-$(FLAVOR))
+RDIR := $(OUTPUT)$(if $(FLAVOR),/$(FLAVOR))
+
+all: $(OUTPUT)/$(BINARY)
+.PHONY: all
+
+# Delete partially updated (corrupted) files on error
+.DELETE_ON_ERROR:
+
+# No built-in rules: every file built here has an explicit rule, and the
+# objects that come from the main Makefile have to be an error when
+# missing rather than a silent rebuild by the built-in %.o recipes.
+MAKEFLAGS += -r
+
+# Permissive build behaviour (skip-on-failure compile, partial-link) only
+# applies to test_progs and its flavors; runners that use strong cross-object
+# references (e.g. test_maps) keep strict semantics even when permissive.
+PERMISSIVE_TESTS := $(if $(filter test_progs,$(RUNNER)),$(PERMISSIVE))
+
+$(RDIR):
+ $(call msg,MKDIR,,$@)
+ $(Q)mkdir -p $@
+
+# Per-runner sources
+
+ifeq ($(RUNNER),test_progs)
+GENERATED_HDRS := $(LIBARENA_SKEL) $(LIBARENA_ASAN_SKEL)
+endif
+
+TEST_SRCS := $(notdir $(wildcard $(TESTS_DIR)/*.c))
+TEST_OBJS := $(patsubst %.c,$(RDIR)/%.test.o,$(TEST_SRCS))
+TEST_DEPS := $(TEST_OBJS:.o=.d)
+
+# BPF objects and skeletons - rules shared with the main Makefile
+
+include Makefile.skel
+
+# When the compiler generates a %.d file, only skel basenames (not
+# full paths) are specified as prerequisites for corresponding %.o
+# file. vpath directives below instruct make to search for skel files
+# in $(RDIR), if they are not present in the working directory.
+vpath %.skel.h $(RDIR)
+vpath %.lskel.h $(RDIR)
+vpath %.subskel.h $(RDIR)
+
+# Test objects and runner binary
+
+$(RDIR)/resolve_btfids.test.o: $(RESOLVE_BTFIDS) $(RDIR)/btf_data.bpf.o
+$(RDIR)/resolve_btfids.test.o: private TEST_NEEDS_BTFIDS = 1
+
+# compile individual test files
+# Note: we cd into output directory to ensure embedded BPF object is found
+# The %.test.d dependency files are a side effect of the -MMD below; the
+# separate no-recipe rule for them orders the first compilation after
+# skeleton generation and re-orders test object compilation when headers
+# change.
+$(TEST_OBJS): $(RDIR)/%.test.o: $(TESTS_DIR)/%.c | $(RDIR)/%.test.d
+ $(call msg,TEST-OBJ,$(BINARY),$@)
+ $(Q)(cd $(@D) && $(CC) -I. $(CFLAGS) -MMD -MT $@ -c $(CURDIR)/$< $(LDLIBS) -o $(@F)) $(if \
+ $(PERMISSIVE_TESTS),$(call skip_on_fail,TEST))
+ $(if $(TEST_NEEDS_BTFIDS), \
+ $(Q)if [ -f $@ ]; then \
+ $(if $(filter 1,$(V)),true,printf ' %-8s%s %s\n' "BTFIDS" " [$(BINARY)]" "$(notdir $@)"); \
+ $(RESOLVE_BTFIDS) --btf $(RDIR)/btf_data.bpf.o $@; \
+ $(RESOLVE_BTFIDS) --patch_btfids $@.BTF_ids $@; \
+ fi)
+
+$(TEST_DEPS): $(RDIR)/%.test.d: $(TESTS_DIR)/%.c $(GENERATED_HDRS) $(BPFOBJ) \
+ | $(RDIR) $(ALL_SKELS)
+
+include $(wildcard $(TEST_DEPS))
+
+cmd_runner_link = $(CC) $(CFLAGS) \
+ $(if $(PERMISSIVE_TESTS),$(wildcard $(TEST_OBJS)) \
+ $(filter-out $(TEST_OBJS),$(filter %.a %.o,$^)), \
+ $(filter %.a %.o,$^)) \
+ $(LDLIBS) $(LLVM_LDLIBS) $(LDFLAGS) $(LLVM_LDFLAGS) -o $@
+
+# BPF objects are also needed at runtime.
+# In permissive mode, existing test objects are normal prerequisites
+# so edits trigger relinking. Order-only prerequisites attempt all
+# tests; the recipe links the objects that exist afterward.
+$(OUTPUT)/$(BINARY): $(if $(PERMISSIVE_TESTS),$(wildcard $(TEST_OBJS)),$(TEST_OBJS)) \
+ $(RUNNER_OBJS-$(RUNNER)) $(BPFOBJ) \
+ $(TRUNNER_BPFTOOL) \
+ | $(BPF_OBJS) \
+ $(if $(PERMISSIVE_TESTS),$(TEST_OBJS))
+ $(call msg,BINARY,,$@)
+ $(Q)$(cmd_runner_link)
+ $(Q)ln -sf $(if $(FLAVOR),..,.)/tools/build/bpftool/$(USE_BOOTSTRAP)bpftool $(RDIR)/bpftool
diff --git a/tools/testing/selftests/bpf/Makefile.skel b/tools/testing/selftests/bpf/Makefile.skel
new file mode 100644
index 000000000000..580d1d82c186
--- /dev/null
+++ b/tools/testing/selftests/bpf/Makefile.skel
@@ -0,0 +1,139 @@
+# SPDX-License-Identifier: GPL-2.0
+# BPF object and skeleton rules for one flavor.
+# Included by the main Makefile for default outputs and by runners
+# for their flavor. Unflavored runners require the default outputs first.
+#
+# Parameters (variables defined by the includer):
+# RDIR output directory of this flavor
+# FLAVOR flavor name, empty for the default
+# BINARY runner binary name, for build-log messages
+# BPF_CC BPF compiler
+# BPF_CC_MSG build-log tag (CLNG-BPF/GCC-BPF)
+# BPF_CC_FLAGS per-flavor compiler flags
+# BPF_SYS_INCLUDES system include flags for $(BPF_CC)
+# BPF_DEFINES extra defines (-DENABLE_ATOMICS_TESTS)
+
+# BPF objects and skeletons
+
+ifneq ($(BPF_CC),)
+
+BPF_SRCS := $(notdir $(wildcard progs/*.c))
+BPF_OBJS := $(patsubst %.c,$(RDIR)/%.bpf.o,$(BPF_SRCS))
+
+SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
+
+LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h \
+ linked_vars.skel.h linked_maps.skel.h \
+ test_subskeleton.skel.h test_subskeleton_lib.skel.h \
+ test_usdt.skel.h tracing_multi.skel.h \
+ tracing_multi_module.skel.h \
+ tracing_multi_intersect.skel.h \
+ tracing_multi_session.skel.h
+
+LSKELS := fexit_sleep.c trace_printk.c trace_vprintk.c map_ptr_kern.c \
+ core_kern.c core_kern_overflow.c test_ringbuf.c \
+ test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c \
+ test_ringbuf_overwrite.c
+
+LSKELS_SIGNED := fentry_test.c fexit_test.c atomics.c
+
+# Generate both light skeleton and libbpf skeleton for these
+LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \
+ kfunc_call_test_subprog.c test_global_percpu_data.c
+SKEL_BLACKLIST += $(LSKELS) $(LSKELS_SIGNED)
+
+test_static_linked.skel.h-deps := test_static_linked1.bpf.o test_static_linked2.bpf.o
+linked_funcs.skel.h-deps := linked_funcs1.bpf.o linked_funcs2.bpf.o
+linked_vars.skel.h-deps := linked_vars1.bpf.o linked_vars2.bpf.o
+linked_maps.skel.h-deps := linked_maps1.bpf.o linked_maps2.bpf.o
+# In the subskeleton case, we want the test_subskeleton_lib.subskel.h file
+# but that's created as a side-effect of the skel.h generation.
+test_subskeleton.skel.h-deps := test_subskeleton_lib2.bpf.o test_subskeleton_lib.bpf.o test_subskeleton.bpf.o
+test_subskeleton_lib.skel.h-deps := test_subskeleton_lib2.bpf.o test_subskeleton_lib.bpf.o
+test_usdt.skel.h-deps := test_usdt.bpf.o test_usdt_multispec.bpf.o
+tracing_multi.skel.h-deps := tracing_multi_attach.bpf.o tracing_multi_check.bpf.o
+tracing_multi_module.skel.h-deps := tracing_multi_attach_module.bpf.o tracing_multi_check.bpf.o
+tracing_multi_intersect.skel.h-deps := tracing_multi_intersect_attach.bpf.o tracing_multi_check.bpf.o
+tracing_multi_session.skel.h-deps := tracing_multi_session_attach.bpf.o tracing_multi_check.bpf.o
+
+LINKED_BPF_OBJS := $(foreach skel,$(LINKED_SKELS),$($(skel)-deps))
+LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.c,$(LINKED_BPF_OBJS))
+
+SKELS := $(patsubst %.c,$(RDIR)/%.skel.h, \
+ $(filter-out $(SKEL_BLACKLIST) $(LINKED_BPF_SRCS),$(BPF_SRCS)))
+LSKELS_H := $(patsubst %.c,$(RDIR)/%.lskel.h,$(LSKELS) $(LSKELS_EXTRA))
+LSKELS_SIGNED_H := $(patsubst %.c,$(RDIR)/%.lskel.h,$(LSKELS_SIGNED))
+LINKED_SKELS_H := $(addprefix $(RDIR)/,$(LINKED_SKELS))
+ALL_SKELS := $(SKELS) $(LSKELS_H) $(LSKELS_SIGNED_H) $(LINKED_SKELS_H)
+
+HEADERS_FOR_BPF_OBJS := $(wildcard $(BPFDIR)/*.bpf.h) \
+ $(wildcard $(CURDIR)/libarena/include/*.[ch]) \
+ $(addprefix $(BPFDIR)/, bpf_core_read.h \
+ bpf_endian.h \
+ bpf_helpers.h \
+ bpf_tracing.h)
+
+# The following tests contain C code that, although technically legal,
+# triggers GCC warnings that cannot be disabled: declaration of
+# anonymous struct types in function parameter lists.
+progs/btf_dump_test_case_bitfields.c-bpf_gcc-CFLAGS := -Wno-error
+progs/btf_dump_test_case_namespacing.c-bpf_gcc-CFLAGS := -Wno-error
+progs/btf_dump_test_case_packing.c-bpf_gcc-CFLAGS := -Wno-error
+progs/btf_dump_test_case_padding.c-bpf_gcc-CFLAGS := -Wno-error
+progs/btf_dump_test_case_syntax.c-bpf_gcc-CFLAGS := -Wno-error
+
+cmd_bpf_compile = $(BPF_CC) $(BPF_CFLAGS) $(BPF_SYS_INCLUDES) $(BPF_DEFINES) \
+ $($<-CFLAGS) $($<-$(FLAVOR)-CFLAGS) $(BPF_CC_FLAGS) -c $< -o $@ $(call skip_on_fail,BPF)
+
+$(BPF_OBJS): $(RDIR)/%.bpf.o: progs/%.c progs/*.h \
+ $(INCLUDE_DIR)/vmlinux.h $(HEADERS_FOR_BPF_OBJS) \
+ | $(RDIR) $(BPFOBJ)
+ $(call msg,$(BPF_CC_MSG),$(BINARY),$@)
+ $(Q)$(cmd_bpf_compile)
+
+GEN_SKEL := ./gen_bpf_skel.sh
+
+cmd_bpf_gen_skel = $(call skip_if_missing,SKEL,$<,$(@:.skel.h=.subskel.h))printf \
+ ' %-8s%s %s\n' 'GEN-SKEL' ' [$(BINARY)]' '$(notdir $@)'; \
+ BPFTOOL=$(BPFTOOL) $(GEN_SKEL) --name $* \
+ --skel $@ --subskel $(@:.skel.h=.subskel.h) $< $(call \
+ skip_on_fail,SKEL,$(@:.skel.h=.subskel.h))
+
+$(SKELS): $(RDIR)/%.skel.h: $(RDIR)/%.bpf.o $(BPFTOOL) $(GEN_SKEL) | $(RDIR)
+ $(Q)$(cmd_bpf_gen_skel)
+
+cmd_bpf_gen_lskel = $(call skip_if_missing,SKEL,$<)printf \
+ ' %-8s%s %s\n' 'GEN-SKEL' ' [$(BINARY)]' '$(notdir $@)'; \
+ BPFTOOL=$(BPFTOOL) $(GEN_SKEL) --name $*_lskel --lskel \
+ --skel $@ $< $(call skip_on_fail,SKEL)
+
+$(LSKELS_H): $(RDIR)/%.lskel.h: $(RDIR)/%.bpf.o $(BPFTOOL) $(GEN_SKEL) | $(RDIR)
+ $(Q)$(cmd_bpf_gen_lskel)
+
+cmd_bpf_gen_signed_lskel = $(call skip_if_missing,SKEL,$<)printf \
+ ' %-8s%s %s\n' 'GEN-SKEL' ' [$(BINARY) (signed)]' '$(notdir $@)'; \
+ BPFTOOL=$(BPFTOOL) PRIVATE_KEY=$(PRIVATE_KEY) \
+ VERIFICATION_CERT=$(VERIFICATION_CERT) \
+ $(GEN_SKEL) --sign --name $*_lskel \
+ --skel $@ $< $(call skip_on_fail,SKEL)
+
+$(LSKELS_SIGNED_H): $(RDIR)/%.lskel.h: $(RDIR)/%.bpf.o $(BPFTOOL) \
+ $(GEN_SKEL) $(PRIVATE_KEY) $(VERIFICATION_CERT) | $(RDIR)
+ $(Q)$(cmd_bpf_gen_signed_lskel)
+
+cmd_bpf_link_skel = $(call skip_if_missing,SKEL,$(addprefix $(RDIR)/,\
+ $($*.skel.h-deps)),$(@:.skel.h=.subskel.h))printf \
+ ' %-8s%s %s\n' 'LINK-BPF' ' [$(BINARY)]' '$(notdir $(@:.skel.h=.bpf.o))'; \
+ printf ' %-8s%s %s\n' 'GEN-SKEL' ' [$(BINARY)]' '$(notdir $@)'; \
+ BPFTOOL=$(BPFTOOL) $(GEN_SKEL) --name $* \
+ --skel $@ --subskel $(@:.skel.h=.subskel.h) \
+ $(addprefix $(RDIR)/,$($*.skel.h-deps)) $(call \
+ skip_on_fail,SKEL,$(@:.skel.h=.subskel.h))
+
+# .SECONDEXPANSION here allows to correctly expand %-deps variables as prerequisites
+.SECONDEXPANSION:
+$(LINKED_SKELS_H): $(RDIR)/%.skel.h: $$(addprefix $(RDIR)/,$$($$*.skel.h-deps)) \
+ $(BPFTOOL) $(GEN_SKEL) | $(RDIR)
+ $(Q)$(cmd_bpf_link_skel)
+
+endif # BPF_CC
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH bpf-next v8 9/9] selftests/bpf: build each test runner instance in its own sub-make
2026-09-21 7:58 ` [PATCH bpf-next v8 9/9] selftests/bpf: build each test runner instance in its own sub-make Mykola Lysenko
@ 2026-09-21 9:22 ` bot+bpf-ci
2026-09-21 12:08 ` Mykola Lysenko
0 siblings, 1 reply; 19+ messages in thread
From: bot+bpf-ci @ 2026-09-21 9:22 UTC (permalink / raw)
To: nickolay.lysenko, bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa, memxor, nickolay.lysenko, ast, andrii, daniel, martin.lau,
eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2730 bytes --]
> diff --git a/tools/testing/selftests/bpf/Makefile.runner b/tools/testing/selftests/bpf/Makefile.runner
> new file mode 100644
> index 0000000000000..d266c42468882
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/Makefile.runner
> @@ -0,0 +1,125 @@
[ ... ]
> +# Permissive build behaviour (skip-on-failure compile, partial-link) only
> +# applies to test_progs and its flavors; runners that use strong cross-object
> +# references (e.g. test_maps) keep strict semantics even when permissive.
> +PERMISSIVE_TESTS := $(if $(filter test_progs,$(RUNNER)),$(PERMISSIVE))
[ ... ]
> +# compile individual test files
> +# Note: we cd into output directory to ensure embedded BPF object is found
> +# The %.test.d dependency files are a side effect of the -MMD below; the
> +# separate no-recipe rule for them orders the first compilation after
> +# skeleton generation and re-orders test object compilation when headers
> +# change.
> +$(TEST_OBJS): $(RDIR)/%.test.o: $(TESTS_DIR)/%.c | $(RDIR)/%.test.d
> + $(call msg,TEST-OBJ,$(BINARY),$@)
> + $(Q)(cd $(@D) && $(CC) -I. $(CFLAGS) -MMD -MT $@ -c $(CURDIR)/$< $(LDLIBS) -o $(@F)) $(if \
> + $(PERMISSIVE_TESTS),$(call skip_on_fail,TEST))
Does the backslash placement here cause the $(if) condition to be
unconditionally true?
The backslash-newline sits inside the $(if ...) call between the
function name and its first argument. GNU make preserves
backslash-newline in recipe lines (so the shell can join continued
commands), and does not strip whitespace from the condition string
before testing it. The raw condition text becomes '\' + newline +
tabs + '$(PERMISSIVE_TESTS)', and since a backslash is not
whitespace, the condition string is never empty.
This means $(call skip_on_fail,TEST) is always appended, regardless
of PERMISSIVE_TESTS. The guard collapses to permissive for every
runner, including test_maps, contradicting the comment at line 50
that says permissive build behavior only applies to test_progs.
With BPF_STRICT_BUILD=0, a map_tests/*.c file that fails to compile
would now report success, have its .o deleted by skip_on_fail, and
then fail later in the test_maps link with 'No such file or
directory' for the removed object, instead of failing at compile
with the real diagnostic.
Moving the continuation to complete the condition on the first line
would fix this:
$(Q)(cd $(@D) && $(CC) -I. $(CFLAGS) -MMD -MT $@ -c $(CURDIR)/$< $(LDLIBS) -o $(@F)) \
$(if $(PERMISSIVE_TESTS),$(call skip_on_fail,TEST))
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/35577680350
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v8 9/9] selftests/bpf: build each test runner instance in its own sub-make
2026-09-21 9:22 ` bot+bpf-ci
@ 2026-09-21 12:08 ` Mykola Lysenko
0 siblings, 0 replies; 19+ messages in thread
From: Mykola Lysenko @ 2026-09-21 12:08 UTC (permalink / raw)
To: bot+bpf-ci
Cc: bpf, ast, daniel, andrii, eddyz87, martin.lau, song,
yonghong.song, jolsa, memxor, martin.lau, mason, ihor.solodrai
On Mon, Sep 21, 2026 at 11:22 AM <bot+bpf-ci@kernel.org> wrote:
>
> > diff --git a/tools/testing/selftests/bpf/Makefile.runner b/tools/testing/selftests/bpf/Makefile.runner
> > new file mode 100644
> > index 0000000000000..d266c42468882
> > --- /dev/null
> > +++ b/tools/testing/selftests/bpf/Makefile.runner
> > @@ -0,0 +1,125 @@
>
> [ ... ]
>
> > +# Permissive build behaviour (skip-on-failure compile, partial-link) only
> > +# applies to test_progs and its flavors; runners that use strong cross-object
> > +# references (e.g. test_maps) keep strict semantics even when permissive.
> > +PERMISSIVE_TESTS := $(if $(filter test_progs,$(RUNNER)),$(PERMISSIVE))
>
> [ ... ]
>
> > +# compile individual test files
> > +# Note: we cd into output directory to ensure embedded BPF object is found
> > +# The %.test.d dependency files are a side effect of the -MMD below; the
> > +# separate no-recipe rule for them orders the first compilation after
> > +# skeleton generation and re-orders test object compilation when headers
> > +# change.
> > +$(TEST_OBJS): $(RDIR)/%.test.o: $(TESTS_DIR)/%.c | $(RDIR)/%.test.d
> > + $(call msg,TEST-OBJ,$(BINARY),$@)
> > + $(Q)(cd $(@D) && $(CC) -I. $(CFLAGS) -MMD -MT $@ -c $(CURDIR)/$< $(LDLIBS) -o $(@F)) $(if \
> > + $(PERMISSIVE_TESTS),$(call skip_on_fail,TEST))
>
> Does the backslash placement here cause the $(if) condition to be
> unconditionally true?
>
> The backslash-newline sits inside the $(if ...) call between the
> function name and its first argument. GNU make preserves
> backslash-newline in recipe lines (so the shell can join continued
> commands), and does not strip whitespace from the condition string
> before testing it. The raw condition text becomes '\' + newline +
> tabs + '$(PERMISSIVE_TESTS)', and since a backslash is not
> whitespace, the condition string is never empty.
>
> This means $(call skip_on_fail,TEST) is always appended, regardless
> of PERMISSIVE_TESTS. The guard collapses to permissive for every
> runner, including test_maps, contradicting the comment at line 50
> that says permissive build behavior only applies to test_progs.
>
> With BPF_STRICT_BUILD=0, a map_tests/*.c file that fails to compile
> would now report success, have its .o deleted by skip_on_fail, and
> then fail later in the test_maps link with 'No such file or
> directory' for the removed object, instead of failing at compile
> with the real diagnostic.
>
> Moving the continuation to complete the condition on the first line
> would fix this:
>
> $(Q)(cd $(@D) && $(CC) -I. $(CFLAGS) -MMD -MT $@ -c $(CURDIR)/$< $(LDLIBS) -o $(@F)) \
> $(if $(PERMISSIVE_TESTS),$(call skip_on_fail,TEST))
>
I could not reproduce this. It seems make collapses backslash-newline sequences
inside variable and function references before expanding a recipe. The
continuation here therefore does not become part of the $(if) condition.
I tested this as follows in case anyone is curious to test as well (sorry
if i mangled whitespaces below anyhow):
$ cat Makefile
# Standalone reproduction of the condition reported against v8 patch 9.
RUNNER ?= test_maps
BPF_STRICT_BUILD ?= 1
PERMISSIVE := $(filter 0,$(BPF_STRICT_BUILD))
PERMISSIVE_TESTS := $(if $(filter test_progs,$(RUNNER)),$(PERMISSIVE))
# Same nested guard as the real helper; no files need removing here.
skip_on_fail = $(if $(PERMISSIVE),|| { printf '%s\n' 'SKIP-$(1)'; })
.PHONY: all
all:
@printf 'runner=%s strict=%s\n' '$(RUNNER)' '$(BPF_STRICT_BUILD)'
@false $(if \
$(PERMISSIVE_TESTS),$(call skip_on_fail,TEST))
@printf '%s\n' 'Continued after failed command'
$ for runner in test_maps test_progs; do
for strict in 0 1; do
if make --no-print-directory \
RUNNER="$runner" BPF_STRICT_BUILD="$strict"; then
echo "make exit: 0"
else
echo "make exit: $?"
fi
done
done
runner=test_maps strict=0
make: *** [Makefile:14: all] Error 1
make exit: 2
runner=test_maps strict=1
make: *** [Makefile:14: all] Error 1
make exit: 2
runner=test_progs strict=0
SKIP-TEST
Continued after failed command
make exit: 0
runner=test_progs strict=1
make: *** [Makefile:14: all] Error 1
make exit: 2
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/35577680350
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
` (8 preceding siblings ...)
2026-09-21 7:58 ` [PATCH bpf-next v8 9/9] selftests/bpf: build each test runner instance in its own sub-make Mykola Lysenko
@ 2026-09-21 9:28 ` Kumar Kartikeya Dwivedi
2026-09-21 9:30 ` patchwork-bot+netdevbpf
10 siblings, 0 replies; 19+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-21 9:28 UTC (permalink / raw)
To: Mykola Lysenko, bpf
Cc: ast, daniel, andrii, eddyz87, martin.lau, song, yonghong.song,
jolsa
On Mon Sep 21, 2026 at 9:58 AM CEST, Mykola Lysenko wrote:
> The BPF selftests Makefile has grown to ~1,100 lines, with much of the
> complexity concentrated in the DEFINE_TEST_RUNNER double-expansion
> machinery: the per-runner rules are written in $$-escaped make and
> eval'd once per flavor, so the rules that actually run never appear in
> the source and are easy to break for one flavor while testing another.
>
Applied, for any other comments let us do it as follow ups, if necessary.
> [...]
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build
2026-09-21 7:58 [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Mykola Lysenko
` (9 preceding siblings ...)
2026-09-21 9:28 ` [PATCH bpf-next v8 0/9] selftests/bpf: restructure the Makefile as a layered build Kumar Kartikeya Dwivedi
@ 2026-09-21 9:30 ` patchwork-bot+netdevbpf
10 siblings, 0 replies; 19+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-21 9:30 UTC (permalink / raw)
To: Mykola Lysenko
Cc: bpf, ast, daniel, andrii, eddyz87, martin.lau, song,
yonghong.song, jolsa, memxor
Hello:
This series was applied to bpf/bpf-next.git (master)
by Kumar Kartikeya Dwivedi <memxor@gmail.com>:
On Mon, 21 Sep 2026 00:58:46 -0700 you wrote:
> The BPF selftests Makefile has grown to ~1,100 lines, with much of the
> complexity concentrated in the DEFINE_TEST_RUNNER double-expansion
> machinery: the per-runner rules are written in $$-escaped make and
> eval'd once per flavor, so the rules that actually run never appear in
> the source and are easy to break for one flavor while testing another.
>
> The series opens with six small stand-alone changes, each usable (or
> droppable) on its own: patch 1 filters headers off the generic link
> rule's command line (gcc tolerates a stray .h there, clang refuses);
> patch 2 drops four stale target-specific lines that name objects nothing
> builds - restoring the two dependencies of value among them in working
> form (flow_dissector_load.h against the binary;
> cgroup_getset_retval_hooks.h by moving it under progs/, where the
> blanket header prerequisite of the BPF object rules covers it) - plus
> three never-referenced linked-skeleton dependency-map entries, a no-op
> CURDIR override and the OBJCOPY definition nothing reads; patch 3
> factors the eleven identical permissive-mode "remove the target, print
> SKIP, report success" recipe tails into a skip_on_fail helper; patch 4
> makes the signing key generation race-free under -j; patch 5 turns the
> verifier/tests.h $(shell)-in-recipe into a regular recipe; patch 6
> derives the bench object list from the sources with a wildcard.
>
> [...]
Here is the summary with links:
- [bpf-next,v8,1/9] selftests/bpf: keep headers off the generic link command line
https://git.kernel.org/bpf/bpf-next/c/75ab33a0a50f
- [bpf-next,v8,2/9] selftests/bpf: drop stale lines, restore two header dependencies
https://git.kernel.org/bpf/bpf-next/c/35ac30e71745
- [bpf-next,v8,3/9] selftests/bpf: factor the permissive-mode skip suffix into a helper
https://git.kernel.org/bpf/bpf-next/c/00c2b472d5dd
- [bpf-next,v8,4/9] selftests/bpf: generate the signing key and certificate once
https://git.kernel.org/bpf/bpf-next/c/73fb8cea7269
- [bpf-next,v8,5/9] selftests/bpf: generate verifier/tests.h in a regular recipe
https://git.kernel.org/bpf/bpf-next/c/7292e0ad85d5
- [bpf-next,v8,6/9] selftests/bpf: derive the bench object list from the sources
https://git.kernel.org/bpf/bpf-next/c/063fa645c723
- [bpf-next,v8,7/9] selftests/bpf: extract BPF skeleton generation into a helper script
https://git.kernel.org/bpf/bpf-next/c/da6cb3aff2cb
- [bpf-next,v8,8/9] selftests/bpf: move shared build definitions into Makefile.buildvars
https://git.kernel.org/bpf/bpf-next/c/ab1d791d0cc4
- [bpf-next,v8,9/9] selftests/bpf: build each test runner instance in its own sub-make
https://git.kernel.org/bpf/bpf-next/c/ef3744f49d98
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 19+ messages in thread