1*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 2*4882a593Smuzhiyunfeature_dir := $(srctree)/tools/build/feature 3*4882a593Smuzhiyun 4*4882a593Smuzhiyunifneq ($(OUTPUT),) 5*4882a593Smuzhiyun OUTPUT_FEATURES = $(OUTPUT)feature/ 6*4882a593Smuzhiyun $(shell mkdir -p $(OUTPUT_FEATURES)) 7*4882a593Smuzhiyunendif 8*4882a593Smuzhiyun 9*4882a593Smuzhiyunfeature_check = $(eval $(feature_check_code)) 10*4882a593Smuzhiyundefine feature_check_code 11*4882a593Smuzhiyun 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) 12*4882a593Smuzhiyunendef 13*4882a593Smuzhiyun 14*4882a593Smuzhiyunfeature_set = $(eval $(feature_set_code)) 15*4882a593Smuzhiyundefine feature_set_code 16*4882a593Smuzhiyun feature-$(1) := 1 17*4882a593Smuzhiyunendef 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun# 20*4882a593Smuzhiyun# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output: 21*4882a593Smuzhiyun# 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun# 24*4882a593Smuzhiyun# Note that this is not a complete list of all feature tests, just 25*4882a593Smuzhiyun# those that are typically built on a fully configured system. 26*4882a593Smuzhiyun# 27*4882a593Smuzhiyun# [ Feature tests not mentioned here have to be built explicitly in 28*4882a593Smuzhiyun# the rule that uses them - an example for that is the 'bionic' 29*4882a593Smuzhiyun# feature check. ] 30*4882a593Smuzhiyun# 31*4882a593SmuzhiyunFEATURE_TESTS_BASIC := \ 32*4882a593Smuzhiyun backtrace \ 33*4882a593Smuzhiyun dwarf \ 34*4882a593Smuzhiyun dwarf_getlocations \ 35*4882a593Smuzhiyun eventfd \ 36*4882a593Smuzhiyun fortify-source \ 37*4882a593Smuzhiyun sync-compare-and-swap \ 38*4882a593Smuzhiyun get_current_dir_name \ 39*4882a593Smuzhiyun gettid \ 40*4882a593Smuzhiyun glibc \ 41*4882a593Smuzhiyun libbfd \ 42*4882a593Smuzhiyun libbfd-buildid \ 43*4882a593Smuzhiyun libcap \ 44*4882a593Smuzhiyun libelf \ 45*4882a593Smuzhiyun libelf-getphdrnum \ 46*4882a593Smuzhiyun libelf-gelf_getnote \ 47*4882a593Smuzhiyun libelf-getshdrstrndx \ 48*4882a593Smuzhiyun libnuma \ 49*4882a593Smuzhiyun numa_num_possible_cpus \ 50*4882a593Smuzhiyun libperl \ 51*4882a593Smuzhiyun libpython \ 52*4882a593Smuzhiyun libslang \ 53*4882a593Smuzhiyun libslang-include-subdir \ 54*4882a593Smuzhiyun libcrypto \ 55*4882a593Smuzhiyun libunwind \ 56*4882a593Smuzhiyun pthread-attr-setaffinity-np \ 57*4882a593Smuzhiyun pthread-barrier \ 58*4882a593Smuzhiyun reallocarray \ 59*4882a593Smuzhiyun stackprotector-all \ 60*4882a593Smuzhiyun timerfd \ 61*4882a593Smuzhiyun libdw-dwarf-unwind \ 62*4882a593Smuzhiyun zlib \ 63*4882a593Smuzhiyun lzma \ 64*4882a593Smuzhiyun get_cpuid \ 65*4882a593Smuzhiyun bpf \ 66*4882a593Smuzhiyun sched_getcpu \ 67*4882a593Smuzhiyun sdt \ 68*4882a593Smuzhiyun setns \ 69*4882a593Smuzhiyun libaio \ 70*4882a593Smuzhiyun libzstd \ 71*4882a593Smuzhiyun disassembler-four-args \ 72*4882a593Smuzhiyun file-handle 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list 75*4882a593Smuzhiyun# of all feature tests 76*4882a593SmuzhiyunFEATURE_TESTS_EXTRA := \ 77*4882a593Smuzhiyun bionic \ 78*4882a593Smuzhiyun compile-32 \ 79*4882a593Smuzhiyun compile-x32 \ 80*4882a593Smuzhiyun cplus-demangle \ 81*4882a593Smuzhiyun gtk2 \ 82*4882a593Smuzhiyun gtk2-infobar \ 83*4882a593Smuzhiyun hello \ 84*4882a593Smuzhiyun libbabeltrace \ 85*4882a593Smuzhiyun libbfd-liberty \ 86*4882a593Smuzhiyun libbfd-liberty-z \ 87*4882a593Smuzhiyun libopencsd \ 88*4882a593Smuzhiyun libunwind-x86 \ 89*4882a593Smuzhiyun libunwind-x86_64 \ 90*4882a593Smuzhiyun libunwind-arm \ 91*4882a593Smuzhiyun libunwind-aarch64 \ 92*4882a593Smuzhiyun libunwind-debug-frame \ 93*4882a593Smuzhiyun libunwind-debug-frame-arm \ 94*4882a593Smuzhiyun libunwind-debug-frame-aarch64 \ 95*4882a593Smuzhiyun cxx \ 96*4882a593Smuzhiyun llvm \ 97*4882a593Smuzhiyun llvm-version \ 98*4882a593Smuzhiyun clang \ 99*4882a593Smuzhiyun libbpf \ 100*4882a593Smuzhiyun libpfm4 \ 101*4882a593Smuzhiyun libdebuginfod 102*4882a593Smuzhiyun 103*4882a593SmuzhiyunFEATURE_TESTS ?= $(FEATURE_TESTS_BASIC) 104*4882a593Smuzhiyun 105*4882a593Smuzhiyunifeq ($(FEATURE_TESTS),all) 106*4882a593Smuzhiyun FEATURE_TESTS := $(FEATURE_TESTS_BASIC) $(FEATURE_TESTS_EXTRA) 107*4882a593Smuzhiyunendif 108*4882a593Smuzhiyun 109*4882a593SmuzhiyunFEATURE_DISPLAY ?= \ 110*4882a593Smuzhiyun dwarf \ 111*4882a593Smuzhiyun dwarf_getlocations \ 112*4882a593Smuzhiyun glibc \ 113*4882a593Smuzhiyun libbfd \ 114*4882a593Smuzhiyun libbfd-buildid \ 115*4882a593Smuzhiyun libcap \ 116*4882a593Smuzhiyun libelf \ 117*4882a593Smuzhiyun libnuma \ 118*4882a593Smuzhiyun numa_num_possible_cpus \ 119*4882a593Smuzhiyun libperl \ 120*4882a593Smuzhiyun libpython \ 121*4882a593Smuzhiyun libcrypto \ 122*4882a593Smuzhiyun libunwind \ 123*4882a593Smuzhiyun libdw-dwarf-unwind \ 124*4882a593Smuzhiyun zlib \ 125*4882a593Smuzhiyun lzma \ 126*4882a593Smuzhiyun get_cpuid \ 127*4882a593Smuzhiyun bpf \ 128*4882a593Smuzhiyun libaio \ 129*4882a593Smuzhiyun libzstd \ 130*4882a593Smuzhiyun disassembler-four-args 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. 133*4882a593Smuzhiyun# If in the future we need per-feature checks/flags for features not 134*4882a593Smuzhiyun# mentioned in this list we need to refactor this ;-). 135*4882a593Smuzhiyunset_test_all_flags = $(eval $(set_test_all_flags_code)) 136*4882a593Smuzhiyundefine set_test_all_flags_code 137*4882a593Smuzhiyun FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1)) 138*4882a593Smuzhiyun FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1)) 139*4882a593Smuzhiyunendef 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun$(foreach feat,$(FEATURE_TESTS),$(call set_test_all_flags,$(feat))) 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun# 144*4882a593Smuzhiyun# Special fast-path for the 'all features are available' case: 145*4882a593Smuzhiyun# 146*4882a593Smuzhiyun$(call feature_check,all,$(MSG)) 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun# 149*4882a593Smuzhiyun# Just in case the build freshly failed, make sure we print the 150*4882a593Smuzhiyun# feature matrix: 151*4882a593Smuzhiyun# 152*4882a593Smuzhiyunifeq ($(feature-all), 1) 153*4882a593Smuzhiyun # 154*4882a593Smuzhiyun # test-all.c passed - just set all the core feature flags to 1: 155*4882a593Smuzhiyun # 156*4882a593Smuzhiyun $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat))) 157*4882a593Smuzhiyun # 158*4882a593Smuzhiyun # test-all.c does not comprise these tests, so we need to 159*4882a593Smuzhiyun # for this case to get features proper values 160*4882a593Smuzhiyun # 161*4882a593Smuzhiyun $(call feature_check,compile-32) 162*4882a593Smuzhiyun $(call feature_check,compile-x32) 163*4882a593Smuzhiyun $(call feature_check,bionic) 164*4882a593Smuzhiyun $(call feature_check,libbabeltrace) 165*4882a593Smuzhiyunelse 166*4882a593Smuzhiyun $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat))) 167*4882a593Smuzhiyunendif 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun# 170*4882a593Smuzhiyun# Print the result of the feature test: 171*4882a593Smuzhiyun# 172*4882a593Smuzhiyunfeature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG)) 173*4882a593Smuzhiyun 174*4882a593Smuzhiyundefine feature_print_status_code 175*4882a593Smuzhiyun ifeq ($(feature-$(1)), 1) 176*4882a593Smuzhiyun MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1)) 177*4882a593Smuzhiyun else 178*4882a593Smuzhiyun MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1)) 179*4882a593Smuzhiyun endif 180*4882a593Smuzhiyunendef 181*4882a593Smuzhiyun 182*4882a593Smuzhiyunfeature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG)) 183*4882a593Smuzhiyundefine feature_print_text_code 184*4882a593Smuzhiyun MSG = $(shell printf '...%30s: %s' $(1) $(2)) 185*4882a593Smuzhiyunendef 186*4882a593Smuzhiyun 187*4882a593Smuzhiyun# 188*4882a593Smuzhiyun# generates feature value assignment for name, like: 189*4882a593Smuzhiyun# $(call feature_assign,dwarf) == feature-dwarf=1 190*4882a593Smuzhiyun# 191*4882a593Smuzhiyunfeature_assign = feature-$(1)=$(feature-$(1)) 192*4882a593Smuzhiyun 193*4882a593SmuzhiyunFEATURE_DUMP_FILENAME = $(OUTPUT)FEATURE-DUMP$(FEATURE_USER) 194*4882a593SmuzhiyunFEATURE_DUMP := $(shell touch $(FEATURE_DUMP_FILENAME); cat $(FEATURE_DUMP_FILENAME)) 195*4882a593Smuzhiyun 196*4882a593Smuzhiyunfeature_dump_check = $(eval $(feature_dump_check_code)) 197*4882a593Smuzhiyundefine feature_dump_check_code 198*4882a593Smuzhiyun ifeq ($(findstring $(1),$(FEATURE_DUMP)),) 199*4882a593Smuzhiyun $(2) := 1 200*4882a593Smuzhiyun endif 201*4882a593Smuzhiyunendef 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun# 204*4882a593Smuzhiyun# First check if any test from FEATURE_DISPLAY 205*4882a593Smuzhiyun# and set feature_display := 1 if it does 206*4882a593Smuzhiyun$(foreach feat,$(FEATURE_DISPLAY),$(call feature_dump_check,$(call feature_assign,$(feat)),feature_display)) 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun# 209*4882a593Smuzhiyun# Now also check if any other test changed, 210*4882a593Smuzhiyun# so we force FEATURE-DUMP generation 211*4882a593Smuzhiyun$(foreach feat,$(FEATURE_TESTS),$(call feature_dump_check,$(call feature_assign,$(feat)),feature_dump_changed)) 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun# The $(feature_display) controls the default detection message 214*4882a593Smuzhiyun# output. It's set if: 215*4882a593Smuzhiyun# - detected features differes from stored features from 216*4882a593Smuzhiyun# last build (in $(FEATURE_DUMP_FILENAME) file) 217*4882a593Smuzhiyun# - one of the $(FEATURE_DISPLAY) is not detected 218*4882a593Smuzhiyun# - VF is enabled 219*4882a593Smuzhiyun 220*4882a593Smuzhiyunifeq ($(feature_dump_changed),1) 221*4882a593Smuzhiyun $(shell rm -f $(FEATURE_DUMP_FILENAME)) 222*4882a593Smuzhiyun $(foreach feat,$(FEATURE_TESTS),$(shell echo "$(call feature_assign,$(feat))" >> $(FEATURE_DUMP_FILENAME))) 223*4882a593Smuzhiyunendif 224*4882a593Smuzhiyun 225*4882a593Smuzhiyunfeature_display_check = $(eval $(feature_check_display_code)) 226*4882a593Smuzhiyundefine feature_check_display_code 227*4882a593Smuzhiyun ifneq ($(feature-$(1)), 1) 228*4882a593Smuzhiyun feature_display := 1 229*4882a593Smuzhiyun endif 230*4882a593Smuzhiyunendef 231*4882a593Smuzhiyun 232*4882a593Smuzhiyun$(foreach feat,$(FEATURE_DISPLAY),$(call feature_display_check,$(feat))) 233*4882a593Smuzhiyun 234*4882a593Smuzhiyunifeq ($(VF),1) 235*4882a593Smuzhiyun feature_display := 1 236*4882a593Smuzhiyun feature_verbose := 1 237*4882a593Smuzhiyunendif 238*4882a593Smuzhiyun 239*4882a593Smuzhiyunifeq ($(feature_display),1) 240*4882a593Smuzhiyun $(info ) 241*4882a593Smuzhiyun $(info Auto-detecting system features:) 242*4882a593Smuzhiyun $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),)) 243*4882a593Smuzhiyun ifneq ($(feature_verbose),1) 244*4882a593Smuzhiyun $(info ) 245*4882a593Smuzhiyun endif 246*4882a593Smuzhiyunendif 247*4882a593Smuzhiyun 248*4882a593Smuzhiyunifeq ($(feature_verbose),1) 249*4882a593Smuzhiyun TMP := $(filter-out $(FEATURE_DISPLAY),$(FEATURE_TESTS)) 250*4882a593Smuzhiyun $(foreach feat,$(TMP),$(call feature_print_status,$(feat),)) 251*4882a593Smuzhiyun $(info ) 252*4882a593Smuzhiyunendif 253