1# SPDX-License-Identifier: GPL-2.0 2# Copyright (c) 2022 Meta Platforms, Inc. and affiliates. 3include ../../../build/Build.include 4include ../../../scripts/Makefile.arch 5include ../../../scripts/Makefile.include 6include ../lib.mk 7 8ifneq ($(LLVM),) 9ifneq ($(filter %/,$(LLVM)),) 10LLVM_PREFIX := $(LLVM) 11else ifneq ($(filter -%,$(LLVM)),) 12LLVM_SUFFIX := $(LLVM) 13endif 14 15CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX) $(CLANG_FLAGS) -fintegrated-as 16else 17CC := gcc 18endif # LLVM 19 20ifneq ($(CROSS_COMPILE),) 21$(error CROSS_COMPILE not supported for scx selftests) 22endif # CROSS_COMPILE 23 24CURDIR := $(abspath .) 25REPOROOT := $(abspath ../../../..) 26TOOLSDIR := $(REPOROOT)/tools 27LIBDIR := $(TOOLSDIR)/lib 28BPFDIR := $(LIBDIR)/bpf 29TOOLSINCDIR := $(TOOLSDIR)/include 30BPFTOOLDIR := $(TOOLSDIR)/bpf/bpftool 31APIDIR := $(TOOLSINCDIR)/uapi 32GENDIR := $(REPOROOT)/include/generated 33GENHDR := $(GENDIR)/autoconf.h 34SCXTOOLSDIR := $(TOOLSDIR)/sched_ext 35SCXTOOLSINCDIR := $(TOOLSDIR)/sched_ext/include 36 37OUTPUT_DIR := $(CURDIR)/build 38OBJ_DIR := $(OUTPUT_DIR)/obj 39INCLUDE_DIR := $(OUTPUT_DIR)/include 40BPFOBJ_DIR := $(OBJ_DIR)/libbpf 41SCXOBJ_DIR := $(OBJ_DIR)/sched_ext 42BPFOBJ := $(BPFOBJ_DIR)/libbpf.a 43LIBBPF_OUTPUT := $(OBJ_DIR)/libbpf/libbpf.a 44DEFAULT_BPFTOOL := $(OUTPUT_DIR)/sbin/bpftool 45HOST_BUILD_DIR := $(OBJ_DIR) 46HOST_OUTPUT_DIR := $(OUTPUT_DIR) 47 48VMLINUX_BTF_PATHS ?= ../../../../vmlinux \ 49 /sys/kernel/btf/vmlinux \ 50 /boot/vmlinux-$(shell uname -r) 51VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS)))) 52ifeq ($(VMLINUX_BTF),) 53$(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)") 54endif 55 56BPFTOOL ?= $(DEFAULT_BPFTOOL) 57 58ifneq ($(wildcard $(GENHDR)),) 59 GENFLAGS := -DHAVE_GENHDR 60endif 61 62CFLAGS += -g -O2 -rdynamic -pthread -Wall -Werror $(GENFLAGS) \ 63 -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \ 64 -I$(TOOLSINCDIR) -I$(APIDIR) -I$(CURDIR)/include -I$(SCXTOOLSINCDIR) 65 66# Silence some warnings when compiled with clang 67ifneq ($(LLVM),) 68CFLAGS += -Wno-unused-command-line-argument 69endif 70 71LDFLAGS = -lelf -lz -lpthread -lzstd 72 73IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - </dev/null | \ 74 grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__') 75 76# Get Clang's default includes on this system, as opposed to those seen by 77# '-target bpf'. This fixes "missing" files on some architectures/distros, 78# such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc. 79# 80# Use '-idirafter': Don't interfere with include mechanics except where the 81# build would have failed anyways. 82define get_sys_includes 83$(shell $(1) -v -E - </dev/null 2>&1 \ 84 | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \ 85$(shell $(1) -dM -E - </dev/null | grep '__riscv_xlen ' | awk '{printf("-D__riscv_xlen=%d -D__BITS_PER_LONG=%d", $$3, $$3)}') 86endef 87 88BPF_CFLAGS = -g -D__TARGET_ARCH_$(SRCARCH) \ 89 $(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian) \ 90 -I$(CURDIR)/include -I$(CURDIR)/include/bpf-compat \ 91 -I$(INCLUDE_DIR) -I$(APIDIR) -I$(SCXTOOLSINCDIR) \ 92 -I$(REPOROOT)/include \ 93 $(call get_sys_includes,$(CLANG)) \ 94 -Wall -Wno-compare-distinct-pointer-types \ 95 -Wno-incompatible-function-pointer-types \ 96 -O2 -mcpu=v3 97 98# sort removes libbpf duplicates when not cross-building 99MAKE_DIRS := $(sort $(OBJ_DIR)/libbpf $(OBJ_DIR)/libbpf \ 100 $(OBJ_DIR)/bpftool $(OBJ_DIR)/resolve_btfids \ 101 $(INCLUDE_DIR) $(SCXOBJ_DIR)) 102 103$(MAKE_DIRS): 104 $(call msg,MKDIR,,$@) 105 $(Q)mkdir -p $@ 106 107$(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ 108 $(APIDIR)/linux/bpf.h \ 109 | $(OBJ_DIR)/libbpf 110 $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) OUTPUT=$(OBJ_DIR)/libbpf/ \ 111 EXTRA_CFLAGS='-g -O0 -fPIC' \ 112 DESTDIR=$(OUTPUT_DIR) prefix= all install_headers 113 114$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \ 115 $(LIBBPF_OUTPUT) | $(OBJ_DIR)/bpftool 116 $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \ 117 ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) \ 118 EXTRA_CFLAGS='-g -O0' \ 119 OUTPUT=$(OBJ_DIR)/bpftool/ \ 120 LIBBPF_OUTPUT=$(OBJ_DIR)/libbpf/ \ 121 LIBBPF_DESTDIR=$(OUTPUT_DIR)/ \ 122 prefix= DESTDIR=$(OUTPUT_DIR)/ install-bin 123 124$(INCLUDE_DIR)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR) 125ifeq ($(VMLINUX_H),) 126 $(call msg,GEN,,$@) 127 $(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@ 128else 129 $(call msg,CP,,$@) 130 $(Q)cp "$(VMLINUX_H)" $@ 131endif 132 133$(SCXOBJ_DIR)/%.bpf.o: %.bpf.c $(INCLUDE_DIR)/vmlinux.h | $(BPFOBJ) $(SCXOBJ_DIR) 134 $(call msg,CLNG-BPF,,$(notdir $@)) 135 $(Q)$(CLANG) $(BPF_CFLAGS) -target bpf -c $< -o $@ 136 137$(INCLUDE_DIR)/%.bpf.skel.h: $(SCXOBJ_DIR)/%.bpf.o $(INCLUDE_DIR)/vmlinux.h $(BPFTOOL) | $(INCLUDE_DIR) 138 $(eval sched=$(notdir $@)) 139 $(call msg,GEN-SKEL,,$(sched)) 140 $(Q)$(BPFTOOL) gen object $(<:.o=.linked1.o) $< 141 $(Q)$(BPFTOOL) gen object $(<:.o=.linked2.o) $(<:.o=.linked1.o) 142 $(Q)$(BPFTOOL) gen object $(<:.o=.linked3.o) $(<:.o=.linked2.o) 143 $(Q)diff $(<:.o=.linked2.o) $(<:.o=.linked3.o) 144 $(Q)$(BPFTOOL) gen skeleton $(<:.o=.linked3.o) name $(subst .bpf.skel.h,,$(sched)) > $@ 145 $(Q)$(BPFTOOL) gen subskeleton $(<:.o=.linked3.o) name $(subst .bpf.skel.h,,$(sched)) > $(@:.skel.h=.subskel.h) 146 147################ 148# C schedulers # 149################ 150 151override define CLEAN 152 rm -rf $(OUTPUT_DIR) 153 rm -f *.o *.bpf.o *.bpf.skel.h *.bpf.subskel.h 154 rm -f $(TEST_GEN_PROGS) 155 rm -f runner 156endef 157 158# Every testcase takes all of the BPF progs are dependencies by default. This 159# allows testcases to load any BPF scheduler, which is useful for testcases 160# that don't need their own prog to run their test. 161all_test_bpfprogs := $(foreach prog,$(wildcard *.bpf.c),$(INCLUDE_DIR)/$(patsubst %.c,%.skel.h,$(prog))) 162 163auto-test-targets := \ 164 create_dsq \ 165 enq_last_no_enq_fails \ 166 enq_select_cpu_fails \ 167 ddsp_bogus_dsq_fail \ 168 ddsp_vtimelocal_fail \ 169 dsp_local_on \ 170 exit \ 171 hotplug \ 172 init_enable_count \ 173 maximal \ 174 maybe_null \ 175 minimal \ 176 prog_run \ 177 reload_loop \ 178 select_cpu_dfl \ 179 select_cpu_dfl_nodispatch \ 180 select_cpu_dispatch \ 181 select_cpu_dispatch_bad_dsq \ 182 select_cpu_dispatch_dbl_dsp \ 183 select_cpu_vtime \ 184 test_example \ 185 186testcase-targets := $(addsuffix .o,$(addprefix $(SCXOBJ_DIR)/,$(auto-test-targets))) 187 188$(SCXOBJ_DIR)/runner.o: runner.c | $(SCXOBJ_DIR) 189 $(CC) $(CFLAGS) -c $< -o $@ 190 191# Create all of the test targets object files, whose testcase objects will be 192# registered into the runner in ELF constructors. 193# 194# Note that we must do double expansion here in order to support conditionally 195# compiling BPF object files only if one is present, as the wildcard Make 196# function doesn't support using implicit rules otherwise. 197$(testcase-targets): $(SCXOBJ_DIR)/%.o: %.c $(SCXOBJ_DIR)/runner.o $(all_test_bpfprogs) | $(SCXOBJ_DIR) 198 $(eval test=$(patsubst %.o,%.c,$(notdir $@))) 199 $(CC) $(CFLAGS) -c $< -o $@ $(SCXOBJ_DIR)/runner.o 200 201$(SCXOBJ_DIR)/util.o: util.c | $(SCXOBJ_DIR) 202 $(CC) $(CFLAGS) -c $< -o $@ 203 204runner: $(SCXOBJ_DIR)/runner.o $(SCXOBJ_DIR)/util.o $(BPFOBJ) $(testcase-targets) 205 @echo "$(testcase-targets)" 206 $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) 207 208TEST_GEN_PROGS := runner 209 210all: runner 211 212.PHONY: all clean help 213 214.DEFAULT_GOAL := all 215 216.DELETE_ON_ERROR: 217 218.SECONDARY: 219