Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: add build/cross-build dependency check script

Add build/cross-build dependency check script kselftest_deps.sh
This script does the following:

Usage: ./kselftest_deps.sh -[p] <compiler> [test_name]

kselftest_deps.sh [-p] gcc
kselftest_deps.sh [-p] gcc vm
kselftest_deps.sh [-p] aarch64-linux-gnu-gcc
kselftest_deps.sh [-p] aarch64-linux-gnu-gcc vm

- Should be run in selftests directory in the kernel repo.
- Checks if Kselftests can be built/cross-built on a system.
- Parses all test/sub-test Makefile to find library dependencies.
- Runs compile test on a trivial C file with LDLIBS specified
in the test Makefiles to identify missing library dependencies.
- Prints suggested target list for a system filtering out tests
failed the build dependency check from the TARGETS in Selftests
the main Makefile when optional -p is specified.
- Prints pass/fail dependency check for each tests/sub-test.
- Prints pass/fail targets and libraries.
- Default: runs dependency checks on all tests.
- Optional test name can be specified to check dependencies for it.

To make LDLIBS parsing easier
- change gpio and memfd Makefiles to use the same temporary variable used
to find and add libraries to LDLIBS.
- simlify LDLIBS append logic in intel_pstate/Makefile.

Results from run on x86_64 system (trimmed detailed pass/fail list):
========================================================
Kselftest Dependency Check for [./kselftest_deps.sh gcc ] results...
========================================================
Checked tests defining LDLIBS dependencies
--------------------------------------------------------
Total tests with Dependencies:
55 Pass: 53 Fail: 2
--------------------------------------------------------
Targets passed build dependency check on system:
bpf capabilities filesystems futex gpio intel_pstate membarrier memfd
mqueue net powerpc ptp rseq rtc safesetid timens timers vDSO vm
--------------------------------------------------------
FAIL: netfilter/Makefile dependency check: -lmnl
FAIL: gpio/Makefile dependency check: -lmount
--------------------------------------------------------
Targets failed build dependency check on system:
gpio netfilter
--------------------------------------------------------
Missing libraries system
-lmnl -lmount
--------------------------------------------------------
========================================================

Results from run on x86_64 system with aarch64-linux-gnu-gcc:
(trimmed detailed pass/fail list):
========================================================
Kselftest Dependency Check for [./kselftest_deps.sh aarch64-linux-gnu-gcc ]
results...
========================================================
Checked tests defining LDLIBS dependencies
--------------------------------------------------------
Total tests with Dependencies:
55 Pass: 41 Fail: 14
--------------------------------------------------------
Targets failed build dependency check on system:
bpf capabilities filesystems futex gpio intel_pstate membarrier memfd
mqueue net powerpc ptp rseq rtc timens timers vDSO vm
--------------------------------------------------------
--------------------------------------------------------
Targets failed build dependency check on system:
bpf capabilities gpio memfd mqueue net netfilter safesetid vm
--------------------------------------------------------
Missing libraries system
-lcap -lcap-ng -lelf -lfuse -lmnl -lmount -lnuma -lpopt -lz
--------------------------------------------------------
========================================================

Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>

+291 -9
+6 -6
tools/testing/selftests/gpio/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 - MOUNT_CFLAGS := $(shell pkg-config --cflags mount 2>/dev/null) 4 - MOUNT_LDLIBS := $(shell pkg-config --libs mount 2>/dev/null) 5 - ifeq ($(MOUNT_LDLIBS),) 6 - MOUNT_LDLIBS := -lmount -I/usr/include/libmount 3 + VAR_CFLAGS := $(shell pkg-config --cflags mount 2>/dev/null) 4 + VAR_LDLIBS := $(shell pkg-config --libs mount 2>/dev/null) 5 + ifeq ($(VAR_LDLIBS),) 6 + VAR_LDLIBS := -lmount -I/usr/include/libmount 7 7 endif 8 8 9 - CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(MOUNT_CFLAGS) 10 - LDLIBS += $(MOUNT_LDLIBS) 9 + CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(VAR_CFLAGS) 10 + LDLIBS += $(VAR_LDLIBS) 11 11 12 12 TEST_PROGS := gpio-mockup.sh 13 13 TEST_FILES := gpio-mockup-sysfs.sh
+1 -1
tools/testing/selftests/intel_pstate/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE 3 - LDLIBS := $(LDLIBS) -lm 3 + LDLIBS += -lm 4 4 5 5 uname_M := $(shell uname -m 2>/dev/null || echo not) 6 6 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
+272
tools/testing/selftests/kselftest_deps.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + # kselftest_deps.sh 4 + # 5 + # Checks for kselftest build dependencies on the build system. 6 + # Copyright (c) 2020 Shuah Khan <skhan@linuxfoundation.org> 7 + # 8 + # 9 + 10 + usage() 11 + { 12 + 13 + echo -e "Usage: $0 -[p] <compiler> [test_name]\n" 14 + echo -e "\tkselftest_deps.sh [-p] gcc" 15 + echo -e "\tkselftest_deps.sh [-p] gcc vm" 16 + echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc" 17 + echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc vm\n" 18 + echo "- Should be run in selftests directory in the kernel repo." 19 + echo "- Checks if Kselftests can be built/cross-built on a system." 20 + echo "- Parses all test/sub-test Makefile to find library dependencies." 21 + echo "- Runs compile test on a trivial C file with LDLIBS specified" 22 + echo " in the test Makefiles to identify missing library dependencies." 23 + echo "- Prints suggested target list for a system filtering out tests" 24 + echo " failed the build dependency check from the TARGETS in Selftests" 25 + echo " main Makefile when optional -p is specified." 26 + echo "- Prints pass/fail dependency check for each tests/sub-test." 27 + echo "- Prints pass/fail targets and libraries." 28 + echo "- Default: runs dependency checks on all tests." 29 + echo "- Optional test name can be specified to check dependencies for it." 30 + exit 1 31 + 32 + } 33 + 34 + # Start main() 35 + main() 36 + { 37 + 38 + base_dir=`pwd` 39 + # Make sure we're in the selftests top-level directory. 40 + if [ $(basename "$base_dir") != "selftests" ]; then 41 + echo -e "\tPlease run $0 in" 42 + echo -e "\ttools/testing/selftests directory ..." 43 + exit 1 44 + fi 45 + 46 + print_targets=0 47 + 48 + while getopts "p" arg; do 49 + case $arg in 50 + p) 51 + print_targets=1 52 + shift;; 53 + esac 54 + done 55 + 56 + if [ $# -eq 0 ] 57 + then 58 + usage 59 + fi 60 + 61 + # Compiler 62 + CC=$1 63 + 64 + tmp_file=$(mktemp).c 65 + trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT 66 + #echo $tmp_file 67 + 68 + pass=$(mktemp).out 69 + trap "rm -f $pass" EXIT 70 + #echo $pass 71 + 72 + fail=$(mktemp).out 73 + trap "rm -f $fail" EXIT 74 + #echo $fail 75 + 76 + # Generate tmp source fire for compile test 77 + cat << "EOF" > $tmp_file 78 + int main() 79 + { 80 + } 81 + EOF 82 + 83 + # Save results 84 + total_cnt=0 85 + fail_trgts=() 86 + fail_libs=() 87 + fail_cnt=0 88 + pass_trgts=() 89 + pass_libs=() 90 + pass_cnt=0 91 + 92 + # Get all TARGETS from selftests Makefile 93 + targets=$(egrep "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2) 94 + 95 + # Single test case 96 + if [ $# -eq 2 ] 97 + then 98 + test=$2/Makefile 99 + 100 + l1_test $test 101 + l2_test $test 102 + l3_test $test 103 + 104 + print_results $1 $2 105 + exit $? 106 + fi 107 + 108 + # Level 1: LDLIBS set static. 109 + # 110 + # Find all LDLIBS set statically for all executables built by a Makefile 111 + # and filter out VAR_LDLIBS to discard the following: 112 + # gpio/Makefile:LDLIBS += $(VAR_LDLIBS) 113 + # Append space at the end of the list to append more tests. 114 + 115 + l1_tests=$(grep -r --include=Makefile "^LDLIBS" | \ 116 + grep -v "VAR_LDLIBS" | awk -F: '{print $1}') 117 + 118 + # Level 2: LDLIBS set dynamically. 119 + # 120 + # Level 2 121 + # Some tests have multiple valid LDLIBS lines for individual sub-tests 122 + # that need dependency checks. Find them and append them to the tests 123 + # e.g: vm/Makefile:$(OUTPUT)/userfaultfd: LDLIBS += -lpthread 124 + # Filter out VAR_LDLIBS to discard the following: 125 + # memfd/Makefile:$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS) 126 + # Append space at the end of the list to append more tests. 127 + 128 + l2_tests=$(grep -r --include=Makefile ": LDLIBS" | \ 129 + grep -v "VAR_LDLIBS" | awk -F: '{print $1}') 130 + 131 + # Level 3 132 + # gpio, memfd and others use pkg-config to find mount and fuse libs 133 + # respectively and save it in VAR_LDLIBS. If pkg-config doesn't find 134 + # any, VAR_LDLIBS set to default. 135 + # Use the default value and filter out pkg-config for dependency check. 136 + # e.g: 137 + # gpio/Makefile 138 + # VAR_LDLIBS := $(shell pkg-config --libs mount) 2>/dev/null) 139 + # memfd/Makefile 140 + # VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null) 141 + 142 + l3_tests=$(grep -r --include=Makefile "^VAR_LDLIBS" | \ 143 + grep -v "pkg-config" | awk -F: '{print $1}') 144 + 145 + #echo $l1_tests 146 + #echo $l2_1_tests 147 + #echo $l3_tests 148 + 149 + all_tests 150 + print_results $1 $2 151 + 152 + exit $? 153 + } 154 + # end main() 155 + 156 + all_tests() 157 + { 158 + for test in $l1_tests; do 159 + l1_test $test 160 + done 161 + 162 + for test in $l2_tests; do 163 + l2_test $test 164 + done 165 + 166 + for test in $l3_tests; do 167 + l3_test $test 168 + done 169 + } 170 + 171 + # Use same parsing used for l1_tests and pick libraries this time. 172 + l1_test() 173 + { 174 + test_libs=$(grep --include=Makefile "^LDLIBS" $test | \ 175 + grep -v "VAR_LDLIBS" | \ 176 + sed -e 's/\:/ /' | \ 177 + sed -e 's/+/ /' | cut -d "=" -f 2) 178 + 179 + check_libs $test $test_libs 180 + } 181 + 182 + # Use same parsing used for l2__tests and pick libraries this time. 183 + l2_test() 184 + { 185 + test_libs=$(grep --include=Makefile ": LDLIBS" $test | \ 186 + grep -v "VAR_LDLIBS" | \ 187 + sed -e 's/\:/ /' | sed -e 's/+/ /' | \ 188 + cut -d "=" -f 2) 189 + 190 + check_libs $test $test_libs 191 + } 192 + 193 + l3_test() 194 + { 195 + test_libs=$(grep --include=Makefile "^VAR_LDLIBS" $test | \ 196 + grep -v "pkg-config" | sed -e 's/\:/ /' | 197 + sed -e 's/+/ /' | cut -d "=" -f 2) 198 + 199 + check_libs $test $test_libs 200 + } 201 + 202 + check_libs() 203 + { 204 + 205 + if [[ ! -z "${test_libs// }" ]] 206 + then 207 + 208 + #echo $test_libs 209 + 210 + for lib in $test_libs; do 211 + 212 + let total_cnt+=1 213 + $CC -o $tmp_file.bin $lib $tmp_file > /dev/null 2>&1 214 + if [ $? -ne 0 ]; then 215 + echo "FAIL: $test dependency check: $lib" >> $fail 216 + let fail_cnt+=1 217 + fail_libs+="$lib " 218 + fail_target=$(echo "$test" | cut -d "/" -f1) 219 + fail_trgts+="$fail_target " 220 + targets=$(echo "$targets" | grep -v "$fail_target") 221 + else 222 + echo "PASS: $test dependency check passed $lib" >> $pass 223 + let pass_cnt+=1 224 + pass_libs+="$lib " 225 + pass_trgts+="$(echo "$test" | cut -d "/" -f1) " 226 + fi 227 + 228 + done 229 + fi 230 + } 231 + 232 + print_results() 233 + { 234 + echo -e "========================================================"; 235 + echo -e "Kselftest Dependency Check for [$0 $1 $2] results..." 236 + 237 + if [ $print_targets -ne 0 ] 238 + then 239 + echo -e "Suggested Selftest Targets for your configuration:" 240 + echo -e "$targets"; 241 + fi 242 + 243 + echo -e "========================================================"; 244 + echo -e "Checked tests defining LDLIBS dependencies" 245 + echo -e "--------------------------------------------------------"; 246 + echo -e "Total tests with Dependencies:" 247 + echo -e "$total_cnt Pass: $pass_cnt Fail: $fail_cnt"; 248 + 249 + if [ $pass_cnt -ne 0 ]; then 250 + echo -e "--------------------------------------------------------"; 251 + cat $pass 252 + echo -e "--------------------------------------------------------"; 253 + echo -e "Targets passed build dependency check on system:" 254 + echo -e "$(echo "$pass_trgts" | xargs -n1 | sort -u | xargs)" 255 + fi 256 + 257 + if [ $fail_cnt -ne 0 ]; then 258 + echo -e "--------------------------------------------------------"; 259 + cat $fail 260 + echo -e "--------------------------------------------------------"; 261 + echo -e "Targets failed build dependency check on system:" 262 + echo -e "$(echo "$fail_trgts" | xargs -n1 | sort -u | xargs)" 263 + echo -e "--------------------------------------------------------"; 264 + echo -e "Missing libraries system" 265 + echo -e "$(echo "$fail_libs" | xargs -n1 | sort -u | xargs)" 266 + fi 267 + 268 + echo -e "--------------------------------------------------------"; 269 + echo -e "========================================================"; 270 + } 271 + 272 + main "$@"
+12 -2
tools/testing/selftests/memfd/Makefile
··· 8 8 TEST_PROGS := run_fuse_test.sh run_hugetlbfs_test.sh 9 9 TEST_GEN_FILES := fuse_test fuse_mnt 10 10 11 - fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags) 11 + VAR_CFLAGS := $(shell pkg-config fuse --cflags 2>/dev/null) 12 + ifeq ($(VAR_CFLAGS),) 13 + VAR_CFLAGS := -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse 14 + endif 15 + 16 + VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null) 17 + ifeq ($(VAR_LDLIBS),) 18 + VAR_LDLIBS := -lfuse -pthread 19 + endif 20 + 21 + fuse_mnt.o: CFLAGS += $(VAR_CFLAGS) 12 22 13 23 include ../lib.mk 14 24 15 - $(OUTPUT)/fuse_mnt: LDLIBS += $(shell pkg-config fuse --libs) 25 + $(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS) 16 26 17 27 $(OUTPUT)/memfd_test: memfd_test.c common.c 18 28 $(OUTPUT)/fuse_test: fuse_test.c common.c