| # 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=<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 | |
| # 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 - </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 | |
| 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) |