# 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 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 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=, # 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 # Programs in Rust are built by upstream rustc. It has no prebuilt core for # the bpf target, so it has to come with the source of core: # rustup component add rust-src # core is built as edition 2024, which it is since rustc 1.87. # rustc emits LLVM bitcode and clang makes the object of it, so clang has to be # 23 or newer and not older than LLVM of rustc. # Otherwise RUST_CORE is empty and the tests are skipped. RUSTC ?= rustc RUST_CORE_SRC := $(wildcard $(shell $(RUSTC) --print sysroot 2>/dev/null)$\ /lib/rustlib/src/rust/library/core/src/lib.rs) ifneq ($(RUST_CORE_SRC),) ifeq ($(shell { clang=$$(echo __clang_major__ | $(CLANG) -E -P -x c -) && \ llvm=$$($(srctree)/scripts/rustc-llvm-version.sh $(RUSTC)) && \ [ $$($(srctree)/scripts/rustc-version.sh $(RUSTC)) -ge 108700 ] && \ [ $$clang -ge 23 ] && [ $$clang -ge $$((llvm / 10000)) ]; } \ 2>/dev/null && echo y),y) RUST_CORE := $(BUILD_DIR)/rust/libcore.rlib endif endif # RUSTC_BOOTSTRAP=1 is to build core with a stable rustc, like the kernel does. # panic=abort is a stop gap until panic=unwind is supported. RUSTC_BPF = RUSTC_BOOTSTRAP=1 $(RUSTC) -O -C panic=abort --crate-type rlib \ --target $(if $(IS_LITTLE_ENDIAN),bpfel,bpfeb)-unknown-none \ -L $(dir $(RUST_CORE)) 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 -