From 25addc8be0d5548652a9a93504a1245157faa845 Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Wed, 5 Aug 2026 23:35:14 -0700 Subject: [PATCH] selftests/bpf: build the runner userspace objects in the main Makefile Squash into "selftests/bpf: build each test runner instance in its own sub-make". Instead of maintaining an invariant list of source files to pre-build in the main makefile and having the rules to build same objects in the Makefile.runner, build these objects explicitly in the main makefile and drop the rules from Makefile.runner. Let each runner instance link them as plain prerequisites. The lists live in Makefile.buildvars. Gone from Makefile.runner: the invariant note, EXTRA_SOURCES, LIB_SOURCES, EXTRA_OBJS, LIB_OBJS and both compile rules. EXTRA_HDRS shrinks to the generated headers and is renamed accordingly. The flavored instances no longer build their own copies of shared prerequesties. With no rule left for those objects, a missing one would match make's built-in %.o rule and be rebuilt with default flags, so disable the built-in rules (The `MAKEFLAGS += -r` thingy). --- tools/testing/selftests/bpf/Makefile | 39 ++++++------- .../testing/selftests/bpf/Makefile.buildvars | 17 ++++++ tools/testing/selftests/bpf/Makefile.runner | 55 +++++-------------- 3 files changed, 46 insertions(+), 65 deletions(-) diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index af3709d51f67..dc14a89ed55b 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -245,32 +245,25 @@ $(OUTPUT)/test_sock_fields: $(CGROUP_HELPERS) $(TESTING_HELPERS) $(OUTPUT)/test_tag: $(TESTING_HELPERS) $(OUTPUT)/test_lirc_mode2_user: $(TESTING_HELPERS) $(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS) -$(OUTPUT)/test_maps: $(TESTING_HELPERS) $(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS) $(UNPRIV_HELPERS) -$(OUTPUT)/xsk.o: $(BPFOBJ) - -# All helper objects a runner instance links, pre-built here so runner -# sub-makes sharing $(OUTPUT) never compile them concurrently. -HELPER_OBJS := $(TESTING_HELPERS) $(CGROUP_HELPERS) $(UNPRIV_HELPERS) \ - $(TRACE_HELPERS) $(JSON_WRITER) $(CAP_HELPERS) \ - $(NETWORK_HELPERS) $(OUTPUT)/usdt_1.o $(OUTPUT)/usdt_2.o \ - $(OUTPUT)/xsk.o +# 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. +# # $(BPFTOOL) is a prerequisite because its sub-make is what installs # libbpf's internal headers (bpf/hashmap.h, bpf/libbpf_internal.h) into -# $(INCLUDE_DIR); without it, helpers including those headers race the -# install and can silently pick up the source-tree copies instead. -# -# Invariant: this list must be a superset of every prerequisite the -# runner's EXTRA_OBJS rule attaches to these same objects (EXTRA_HDRS, -# both tests.h flavors, $(BPFOBJ)). It guarantees the helpers built -# here are never older than a runner-side prerequisite, so the -# unflavored test_progs and test_maps sub-makes, which share $(OUTPUT), -# treat them as up to date instead of both recompiling the same object -# file concurrently. -$(HELPER_OBJS): flow_dissector_load.h ip_check_defrag_frags.h \ - $(VERIFY_SIG_HDR) $(LIBARENA_SKEL) $(LIBARENA_ASAN_SKEL)\ - prog_tests/tests.h map_tests/tests.h $(BPFOBJ) $(BPFTOOL) +# $(INCLUDE_DIR); without it, trace_helpers.c races the install and can +# silently pick up the source-tree copies instead. +$(RUNNER_OBJS): $(VERIFY_SIG_HDR) prog_tests/tests.h map_tests/tests.h \ + $(BPFOBJ) $(BPFTOOL) + +# Some utility functions use LLVM libraries +$(OUTPUT)/jit_disasm_helpers.o: CFLAGS += $(LLVM_CFLAGS) + +$(OUTPUT)/find_bit.o: $(TOOLSDIR)/lib/find_bit.c + $(call msg,CC,,$@) + $(Q)$(CC) $(CFLAGS) -c $< -o $@ $(OUTPUT)/flow_dissector_load: flow_dissector_load.h @@ -446,7 +439,7 @@ RUNNER_PREREQS := $(INCLUDE_DIR)/vmlinux.h $(BPFOBJ) $(BPFTOOL) \ $(VERIFY_SIG_HDR) $(PRIVATE_KEY) $(VERIFICATION_CERT) \ $(LIBARENA_SKEL) $(LIBARENA_ASAN_SKEL) \ prog_tests/tests.h map_tests/tests.h \ - $(HELPER_OBJS) \ + $(RUNNER_OBJS) \ $(OUTPUT)/urandom_read $(OUTPUT)/liburandom_read.so \ $(OUTPUT)/xdp_synproxy $(OUTPUT)/sign-file \ $(OUTPUT)/uprobe_multi $(TEST_KMOD_TARGETS) diff --git a/tools/testing/selftests/bpf/Makefile.buildvars b/tools/testing/selftests/bpf/Makefile.buildvars index 044e0d73b09b..bb95cff65324 100644 --- a/tools/testing/selftests/bpf/Makefile.buildvars +++ b/tools/testing/selftests/bpf/Makefile.buildvars @@ -169,3 +169,20 @@ 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) +RUNNER_OBJS-test_maps := $(addprefix $(OUTPUT)/, \ + test_maps.o testing_helpers.o) + +# find_bit.c is the only runner source outside this directory, +# so it needs a rule of its own +RUNNER_LIB_OBJS-test_progs := $(OUTPUT)/find_bit.o + +RUNNER_OBJS := $(sort $(RUNNER_OBJS-test_progs) $(RUNNER_OBJS-test_maps)\ + $(RUNNER_LIB_OBJS-test_progs)) diff --git a/tools/testing/selftests/bpf/Makefile.runner b/tools/testing/selftests/bpf/Makefile.runner index 91e8a2df468f..ed6262dc13e3 100644 --- a/tools/testing/selftests/bpf/Makefile.runner +++ b/tools/testing/selftests/bpf/Makefile.runner @@ -7,9 +7,9 @@ # so everything here is written in plain make - no $$-escaping, no eval, # no per-flavor guards. This file is always invoked by the main Makefile, # never directly: all shared prerequisites (libbpf, bpftool, vmlinux.h, -# veristat, helper objects, signing key, generated tests.h, extra -# binaries) are built by the main Makefile *before* this one runs and are -# referenced below as plain files. +# veristat, helper objects, signing key, generated +# tests.h, extra binaries) are built by the main Makefile *before* this +# one runs and are referenced below as plain files. # # Parameters (all passed on the sub-make command line): # OUTPUT absolute path of the selftests output directory @@ -63,6 +63,11 @@ all: $(OUTPUT)/$(BINARY) # 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 skip-on-failure of individual tests applies to test_progs and # its flavors only; test_maps uses strong cross-object references and keeps # strict semantics even when BPF_STRICT_BUILD=0. @@ -77,15 +82,7 @@ $(RDIR): # --------------------------------------------------------------------- ifeq ($(RUNNER),test_progs) -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 bpftool_helpers.c usdt_1.c usdt_2.c -LIB_SOURCES := find_bit.c -EXTRA_HDRS := flow_dissector_load.h ip_check_defrag_frags.h \ - $(VERIFY_SIG_HDR) $(LIBARENA_SKEL) $(LIBARENA_ASAN_SKEL) +GENERATED_HDRS := $(LIBARENA_SKEL) $(LIBARENA_ASAN_SKEL) EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/liburandom_read.so \ $(OUTPUT)/xdp_synproxy $(OUTPUT)/sign-file \ $(OUTPUT)/uprobe_multi \ @@ -95,25 +92,9 @@ EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/liburandom_read.so \ $(wildcard progs/*.bpf.o) endif -ifeq ($(RUNNER),test_maps) -EXTRA_SOURCES := test_maps.c testing_helpers.c -endif - -# Note on the unflavored runners, which share $(OUTPUT) with the main -# Makefile: helper objects the main Makefile also uses (and lists in the -# runner prerequisites) are already built and fresh when a runner starts, -# so the rules below find them up to date and never write them. This -# holds because the main Makefile's helper-object rule depends on a -# superset of the prerequisites the EXTRA_OBJS rule uses here - keep -# the two lists in sync (see the invariant comment there). - -TESTS_HDR := $(TESTS_DIR)/tests.h - TEST_SRCS := $(notdir $(wildcard $(TESTS_DIR)/*.c)) TEST_OBJS := $(patsubst %.c,$(RDIR)/%.test.o,$(TEST_SRCS)) TEST_DEPS := $(TEST_OBJS:.o=.d) -EXTRA_OBJS := $(patsubst %.c,$(RDIR)/%.o,$(filter %.c,$(EXTRA_SOURCES))) -LIB_OBJS := $(patsubst %.c,$(RDIR)/%.o,$(LIB_SOURCES)) # --------------------------------------------------------------------- # BPF objects and skeletons @@ -270,22 +251,11 @@ $(TEST_OBJS): $(RDIR)/%.test.o: $(TESTS_DIR)/%.c | $(RDIR)/%.test.d $(RESOLVE_BTFIDS) --patch_btfids $@.BTF_ids $@; \ fi) -$(TEST_DEPS): $(RDIR)/%.test.d: $(TESTS_DIR)/%.c $(EXTRA_HDRS) $(BPFOBJ) \ +$(TEST_DEPS): $(RDIR)/%.test.d: $(TESTS_DIR)/%.c $(GENERATED_HDRS) $(BPFOBJ) \ | $(RDIR) $(ALL_SKELS) include $(wildcard $(TEST_DEPS)) -# Some utility functions use LLVM libraries -$(RDIR)/jit_disasm_helpers.o: CFLAGS += $(LLVM_CFLAGS) - -$(EXTRA_OBJS): $(RDIR)/%.o: %.c $(EXTRA_HDRS) $(TESTS_HDR) $(BPFOBJ) | $(RDIR) - $(call msg,EXT-OBJ,$(BINARY),$@) - $(Q)$(CC) $(CFLAGS) -c $< -o $@ - -$(LIB_OBJS): $(RDIR)/%.o: $(TOOLSDIR)/lib/%.c | $(RDIR) - $(call msg,LIB-OBJ,$(BINARY),$@) - $(Q)$(CC) $(CFLAGS) -c $< -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()). .PHONY: extras @@ -303,10 +273,11 @@ endif # relinks the runner - while the full set stays order-only to drive the # build attempts, and the wildcard in the recipe picks up the survivors # at link time. -# Prerequisite order is also link order (test objects, extra objects, +# Prerequisite order is also link order (test objects, runner objects, # libbpf, lib objects). $(OUTPUT)/$(BINARY): $(if $(PERMISSIVE_TESTS),$(wildcard $(TEST_OBJS)),$(TEST_OBJS)) \ - $(EXTRA_OBJS) $(BPFOBJ) $(LIB_OBJS) \ + $(RUNNER_OBJS-$(RUNNER)) $(BPFOBJ) \ + $(RUNNER_LIB_OBJS-$(RUNNER)) \ $(TRUNNER_BPFTOOL) $(OUTPUT)/veristat \ | extras $(BPF_OBJS) \ $(if $(PERMISSIVE_TESTS),$(TEST_OBJS)) -- 2.53.0-Meta