selftests/Makefile builds each test with OUTPUT on the make command line: $(MAKE) OUTPUT=$$BUILD/$$TARGET -C $$TARGET That OUTPUT is authoritative (command-line origin) and travels through MAKEFLAGS into every sub-make. For tests that set TEST_GEN_MODS_DIR (currently mm/page_frag and livepatch/test_modules) the gen_mods_dir rule recurses into a kernel module build: $(MAKE) -C $(TEST_GEN_MODS_DIR) # -> make -C $(KDIR) M=... modules which may in turn (re)build tools/bpf/resolve_btfids as a kernel "prepare" dependency (CONFIG_DEBUG_INFO_BTF). resolve_btfids derives its OUTPUT from O= via tools/scripts/Makefile.include: OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/) but a command-line OUTPUT inherited from kselftest overrides that assignment, so resolve_btfids builds into the kselftest test directory. Because that directory lacks a trailing '/', the tools/build pattern rules $(OUTPUT)%.o are corrupted as well: ".../mmmain.o" instead of ".../mm/main.o", ending in: ld: cannot find .../resolve_btfids-in.o: No such file or directory Fix this at the source of the leak: strip OUTPUT from the command-line overrides handed to the gen_mods_dir/clean_mods_dir sub-make only. OUTPUT, if still present, then reaches the kernel build merely as an overridable environment default, which the tools build overrides with its O=-derived value (which always carries a trailing '/'). The assignment is target-specific, so other selftest sub-makes -- and the test programs that rely on OUTPUT -- are unaffected; selftests that build resolve_btfids themselves with an explicit OUTPUT= (bpf, hid) do not use gen_mods_dir and are untouched. This supersedes the earlier attempt to normalise OUTPUT with an override in tools/bpf/resolve_btfids/Makefile. That override lives in the outer resolve_btfids make and is invisible to the nested "$(MAKE) $(build)=resolve_btfids" sub-make in which the pattern rules actually run, so it did not fix the corruption; it also risked the explicit-OUTPUT builds used by bpf/hid. Reproduce the leak (before this fix), e.g. with a kernel configured for CONFIG_DEBUG_INFO_BTF and a TEST_GEN_MODS_DIR test such as mm/page_frag: $ make kselftest-all ... HOSTLD .../mmresolve_btfids-in.o gcc: error: .../mm/resolve_btfids-in.o: No such file or directory Tested: * With a real lib.mk gen_mods_dir descent, OUTPUT no longer reaches a resolve_btfids-style sub-make as command-line (origin becomes environment); the O=-derived "OUTPUT := " assignment then wins. * make -C tools/bpf/resolve_btfids make -C tools/bpf/resolve_btfids OUTPUT=/tmp/o/resolve_btfids/ both still build. * make OUTPUT=/tmp/build/kcmp -C tools/testing/selftests/kcmp still honours OUTPUT for its own programs. Signed-off-by: Jiangshan Yi --- v2: - Reworked the fix: instead of overriding OUTPUT in tools/bpf/resolve_btfids/Makefile (v1), which is invisible to the nested "$(MAKE) $(build)=resolve_btfids" sub-make where the pattern rules actually run and also clobbers the explicit OUTPUT= used by bpf/hid, strip OUTPUT from the command-line overrides of the gen_mods_dir/clean_mods_dir sub-make in tools/testing/selftests/lib.mk so the leak is fixed at its source. v1: - initial submission tools/testing/selftests/lib.mk | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk index f02cc8a2e4ae..5345be76223a 100644 --- a/tools/testing/selftests/lib.mk +++ b/tools/testing/selftests/lib.mk @@ -142,9 +142,26 @@ else @$(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS)) endif +# The build of TEST_GEN_MODS_DIR recurses into the kernel build (it builds +# out-of-tree modules via "make -C \$(KDIR) M=..."), which may in turn build +# tools/bpf/resolve_btfids as a kernel "prepare" dependency. That tools build +# derives its own OUTPUT from O=, but a command-line OUTPUT inherited from here +# (e.g. the per-test output directory that selftests/Makefile passes on its +# command line) is authoritative and overrides that derivation, corrupting the +# paths produced by the tools/build pattern rules (e.g. ".../mmmain.o" instead +# of ".../mm/main.o", and a missing resolve_btfids-in.o). +# +# Strip OUTPUT from the command-line overrides handed to this sub-make only, so +# it can no longer override the O=-derived value downstream. The variable, if +# still present, then reaches the kernel build merely as an overridable +# environment default, which the tools build ignores in favour of its O=-derived +# OUTPUT. This is target-specific so that other sub-makes, which may legitimately +# rely on the inherited OUTPUT, are unaffected. +gen_mods_dir: MAKEOVERRIDES := $(filter-out OUTPUT=%,$(MAKEOVERRIDES)) gen_mods_dir: $(Q)$(MAKE) -C $(TEST_GEN_MODS_DIR) +clean_mods_dir: MAKEOVERRIDES := $(filter-out OUTPUT=%,$(MAKEOVERRIDES)) clean_mods_dir: $(Q)$(MAKE) -C $(TEST_GEN_MODS_DIR) clean -- 2.25.1