312 lines · plain
1# SPDX-License-Identifier: GPL-2.0-only2feature_dir := $(srctree)/tools/build/feature3 4ifneq ($(OUTPUT),)5 OUTPUT_FEATURES = $(OUTPUT)feature/6 $(shell mkdir -p $(OUTPUT_FEATURES))7endif8 9feature_check = $(eval $(feature_check_code))10define feature_check_code11 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CC="$(CC)" CXX="$(CXX)" CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)12endef13 14feature_set = $(eval $(feature_set_code))15define feature_set_code16 feature-$(1) := 117endef18 19#20# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:21#22 23#24# Note that this is not a complete list of all feature tests, just25# those that are typically built on a fully configured system.26#27# [ Feature tests not mentioned here have to be built explicitly in28# the rule that uses them - an example for that is the 'bionic'29# feature check. ]30#31FEATURE_TESTS_BASIC := \32 backtrace \33 dwarf \34 dwarf_getlocations \35 dwarf_getcfi \36 eventfd \37 fortify-source \38 get_current_dir_name \39 gettid \40 glibc \41 libbfd \42 libbfd-buildid \43 libcap \44 libelf \45 libelf-getphdrnum \46 libelf-gelf_getnote \47 libelf-getshdrstrndx \48 libnuma \49 numa_num_possible_cpus \50 libperl \51 libpython \52 libslang \53 libslang-include-subdir \54 libtraceevent \55 libtracefs \56 libcrypto \57 libunwind \58 pthread-attr-setaffinity-np \59 pthread-barrier \60 reallocarray \61 stackprotector-all \62 timerfd \63 libdw-dwarf-unwind \64 zlib \65 lzma \66 get_cpuid \67 bpf \68 scandirat \69 sched_getcpu \70 sdt \71 setns \72 libaio \73 libzstd \74 disassembler-four-args \75 disassembler-init-styled \76 file-handle77 78# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list79# of all feature tests80FEATURE_TESTS_EXTRA := \81 bionic \82 compile-32 \83 compile-x32 \84 cplus-demangle \85 cxa-demangle \86 gtk2 \87 gtk2-infobar \88 hello \89 libbabeltrace \90 libcapstone \91 libbfd-liberty \92 libbfd-liberty-z \93 libopencsd \94 libunwind-x86 \95 libunwind-x86_64 \96 libunwind-arm \97 libunwind-aarch64 \98 libunwind-debug-frame \99 libunwind-debug-frame-arm \100 libunwind-debug-frame-aarch64 \101 cxx \102 llvm \103 clang \104 libbpf \105 libbpf-btf__load_from_kernel_by_id \106 libbpf-bpf_prog_load \107 libbpf-bpf_object__next_program \108 libbpf-bpf_object__next_map \109 libbpf-bpf_program__set_insns \110 libbpf-bpf_create_map \111 libpfm4 \112 libdebuginfod \113 clang-bpf-co-re114 115 116FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)117 118ifeq ($(FEATURE_TESTS),all)119 FEATURE_TESTS := $(FEATURE_TESTS_BASIC) $(FEATURE_TESTS_EXTRA)120endif121 122FEATURE_DISPLAY ?= \123 dwarf \124 dwarf_getlocations \125 glibc \126 libbfd \127 libbfd-buildid \128 libcap \129 libelf \130 libnuma \131 numa_num_possible_cpus \132 libperl \133 libpython \134 libcrypto \135 libunwind \136 libdw-dwarf-unwind \137 libcapstone \138 llvm-perf \139 zlib \140 lzma \141 get_cpuid \142 bpf \143 libaio \144 libzstd145 146#147# Declare group members of a feature to display the logical OR of the detection148# result instead of each member result.149#150FEATURE_GROUP_MEMBERS-libbfd = libbfd-liberty libbfd-liberty-z151 152#153# Declare list of feature dependency packages that provide pkg-config files.154#155FEATURE_PKG_CONFIG ?= \156 libtraceevent \157 libtracefs158 159feature_pkg_config = $(eval $(feature_pkg_config_code))160define feature_pkg_config_code161 FEATURE_CHECK_CFLAGS-$(1) := $(shell $(PKG_CONFIG) --cflags $(1) 2>/dev/null)162 FEATURE_CHECK_LDFLAGS-$(1) := $(shell $(PKG_CONFIG) --libs $(1) 2>/dev/null)163endef164 165# Set FEATURE_CHECK_(C|LD)FLAGS-$(package) for packages using pkg-config.166ifneq ($(PKG_CONFIG),)167 $(foreach package,$(FEATURE_PKG_CONFIG),$(call feature_pkg_config,$(package)))168endif169 170# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.171# If in the future we need per-feature checks/flags for features not172# mentioned in this list we need to refactor this ;-).173set_test_all_flags = $(eval $(set_test_all_flags_code))174define set_test_all_flags_code175 FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1))176 FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))177endef178 179$(foreach feat,$(FEATURE_TESTS),$(call set_test_all_flags,$(feat)))180 181#182# Special fast-path for the 'all features are available' case:183#184$(call feature_check,all,$(MSG))185 186#187# Just in case the build freshly failed, make sure we print the188# feature matrix:189#190ifeq ($(feature-all), 1)191 #192 # test-all.c passed - just set all the core feature flags to 1:193 #194 $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat)))195 #196 # test-all.c does not comprise these tests, so we need to197 # for this case to get features proper values198 #199 $(call feature_check,compile-32)200 $(call feature_check,compile-x32)201 $(call feature_check,bionic)202 $(call feature_check,libbabeltrace)203else204 $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat)))205endif206 207#208# Print the result of the feature test:209#210feature_print_status = $(eval $(feature_print_status_code))211 212feature_group = $(eval $(feature_gen_group)) $(GROUP)213 214define feature_gen_group215 GROUP := $(1)216 ifneq ($(feature_verbose),1)217 GROUP += $(FEATURE_GROUP_MEMBERS-$(1))218 endif219endef220 221define feature_print_status_code222 ifneq (,$(filter 1,$(foreach feat,$(call feature_group,$(feat)),$(feature-$(feat)))))223 MSG = $(shell printf '...%40s: [ \033[32mon\033[m ]' $(1))224 else225 MSG = $(shell printf '...%40s: [ \033[31mOFF\033[m ]' $(1))226 endif227endef228 229feature_print_text = $(eval $(feature_print_text_code))230define feature_print_text_code231 MSG = $(shell printf '...%40s: %s' $(1) $(2))232endef233 234#235# generates feature value assignment for name, like:236# $(call feature_assign,dwarf) == feature-dwarf=1237#238feature_assign = feature-$(1)=$(feature-$(1))239 240FEATURE_DUMP_FILENAME = $(OUTPUT)FEATURE-DUMP$(FEATURE_USER)241FEATURE_DUMP := $(shell touch $(FEATURE_DUMP_FILENAME); cat $(FEATURE_DUMP_FILENAME))242 243feature_dump_check = $(eval $(feature_dump_check_code))244define feature_dump_check_code245 ifeq ($(findstring $(1),$(FEATURE_DUMP)),)246 $(2) := 1247 endif248endef249 250#251# First check if any test from FEATURE_DISPLAY252# and set feature_display := 1 if it does253$(foreach feat,$(FEATURE_DISPLAY),$(call feature_dump_check,$(call feature_assign,$(feat)),feature_display))254 255#256# Now also check if any other test changed,257# so we force FEATURE-DUMP generation258$(foreach feat,$(FEATURE_TESTS),$(call feature_dump_check,$(call feature_assign,$(feat)),feature_dump_changed))259 260# The $(feature_display) controls the default detection message261# output. It's set if:262# - detected features differes from stored features from263# last build (in $(FEATURE_DUMP_FILENAME) file)264# - one of the $(FEATURE_DISPLAY) is not detected265# - VF is enabled266 267ifeq ($(feature_dump_changed),1)268 $(shell rm -f $(FEATURE_DUMP_FILENAME))269 $(foreach feat,$(FEATURE_TESTS),$(shell echo "$(call feature_assign,$(feat))" >> $(FEATURE_DUMP_FILENAME)))270endif271 272feature_display_check = $(eval $(feature_check_display_code))273define feature_check_display_code274 ifneq ($(feature-$(1)), 1)275 feature_display := 1276 endif277endef278 279$(foreach feat,$(FEATURE_DISPLAY),$(call feature_display_check,$(feat)))280 281ifeq ($(VF),1)282 feature_display := 1283 feature_verbose := 1284endif285 286ifneq ($(feature_verbose),1)287 #288 # Determine the features to omit from the displayed message, as only the289 # logical OR of the detection result will be shown.290 #291 FEATURE_OMIT := $(foreach feat,$(FEATURE_DISPLAY),$(FEATURE_GROUP_MEMBERS-$(feat)))292endif293 294feature_display_entries = $(eval $(feature_display_entries_code))295define feature_display_entries_code296 ifeq ($(feature_display),1)297 $$(info )298 $$(info Auto-detecting system features:)299 $(foreach feat,$(filter-out $(FEATURE_OMIT),$(FEATURE_DISPLAY)),$(call feature_print_status,$(feat),) $$(info $(MSG)))300 endif301 302 ifeq ($(feature_verbose),1)303 $(eval TMP := $(filter-out $(FEATURE_DISPLAY),$(FEATURE_TESTS)))304 $(foreach feat,$(TMP),$(call feature_print_status,$(feat),) $$(info $(MSG)))305 endif306endef307 308ifeq ($(FEATURE_DISPLAY_DEFERRED),)309 $(call feature_display_entries)310 $(info )311endif312