1 #!/bin/bash 1 #!/bin/bash 2 # SPDX-License-Identifier: GPL-2.0 2 # SPDX-License-Identifier: GPL-2.0 3 # kselftest_deps.sh 3 # kselftest_deps.sh 4 # 4 # 5 # Checks for kselftest build dependencies on t 5 # Checks for kselftest build dependencies on the build system. 6 # Copyright (c) 2020 Shuah Khan <skhan@linuxfou 6 # Copyright (c) 2020 Shuah Khan <skhan@linuxfoundation.org> 7 # 7 # 8 # 8 # 9 9 10 usage() 10 usage() 11 { 11 { 12 12 13 echo -e "Usage: $0 -[p] <compiler> [test_name] 13 echo -e "Usage: $0 -[p] <compiler> [test_name]\n" 14 echo -e "\tkselftest_deps.sh [-p] gcc" 14 echo -e "\tkselftest_deps.sh [-p] gcc" 15 echo -e "\tkselftest_deps.sh [-p] gcc mm" 15 echo -e "\tkselftest_deps.sh [-p] gcc mm" 16 echo -e "\tkselftest_deps.sh [-p] aarch64-linu 16 echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc" 17 echo -e "\tkselftest_deps.sh [-p] aarch64-linu 17 echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc mm\n" 18 echo "- Should be run in selftests directory i 18 echo "- Should be run in selftests directory in the kernel repo." 19 echo "- Checks if Kselftests can be built/cros 19 echo "- Checks if Kselftests can be built/cross-built on a system." 20 echo "- Parses all test/sub-test Makefile to f 20 echo "- Parses all test/sub-test Makefile to find library dependencies." 21 echo "- Runs compile test on a trivial C file 21 echo "- Runs compile test on a trivial C file with LDLIBS specified" 22 echo " in the test Makefiles to identify miss 22 echo " in the test Makefiles to identify missing library dependencies." 23 echo "- Prints suggested target list for a sys 23 echo "- Prints suggested target list for a system filtering out tests" 24 echo " failed the build dependency check from 24 echo " failed the build dependency check from the TARGETS in Selftests" 25 echo " main Makefile when optional -p is spec 25 echo " main Makefile when optional -p is specified." 26 echo "- Prints pass/fail dependency check for 26 echo "- Prints pass/fail dependency check for each tests/sub-test." 27 echo "- Prints pass/fail targets and libraries 27 echo "- Prints pass/fail targets and libraries." 28 echo "- Default: runs dependency checks on all 28 echo "- Default: runs dependency checks on all tests." 29 echo "- Optional: test name can be specified t 29 echo "- Optional: test name can be specified to check dependencies for it." 30 exit 1 30 exit 1 31 31 32 } 32 } 33 33 34 # Start main() 34 # Start main() 35 main() 35 main() 36 { 36 { 37 37 38 base_dir=`pwd` 38 base_dir=`pwd` 39 # Make sure we're in the selftests top-level d 39 # Make sure we're in the selftests top-level directory. 40 if [ $(basename "$base_dir") != "selftests" ] 40 if [ $(basename "$base_dir") != "selftests" ]; then 41 echo -e "\tPlease run $0 in" 41 echo -e "\tPlease run $0 in" 42 echo -e "\ttools/testing/selftests dir 42 echo -e "\ttools/testing/selftests directory ..." 43 exit 1 43 exit 1 44 fi 44 fi 45 45 46 print_targets=0 46 print_targets=0 47 47 48 while getopts "p" arg; do 48 while getopts "p" arg; do 49 case $arg in 49 case $arg in 50 p) 50 p) 51 print_targets=1 51 print_targets=1 52 shift;; 52 shift;; 53 esac 53 esac 54 done 54 done 55 55 56 if [ $# -eq 0 ] 56 if [ $# -eq 0 ] 57 then 57 then 58 usage 58 usage 59 fi 59 fi 60 60 61 # Compiler 61 # Compiler 62 CC=$1 62 CC=$1 63 63 64 tmp_file=$(mktemp).c 64 tmp_file=$(mktemp).c 65 trap "rm -f $tmp_file.o $tmp_file $tmp_file.bi 65 trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT 66 #echo $tmp_file 66 #echo $tmp_file 67 67 68 pass=$(mktemp).out 68 pass=$(mktemp).out 69 trap "rm -f $pass" EXIT 69 trap "rm -f $pass" EXIT 70 #echo $pass 70 #echo $pass 71 71 72 fail=$(mktemp).out 72 fail=$(mktemp).out 73 trap "rm -f $fail" EXIT 73 trap "rm -f $fail" EXIT 74 #echo $fail 74 #echo $fail 75 75 76 # Generate tmp source fire for compile test 76 # Generate tmp source fire for compile test 77 cat << "EOF" > $tmp_file 77 cat << "EOF" > $tmp_file 78 int main() 78 int main() 79 { 79 { 80 } 80 } 81 EOF 81 EOF 82 82 83 # Save results 83 # Save results 84 total_cnt=0 84 total_cnt=0 85 fail_trgts=() 85 fail_trgts=() 86 fail_libs=() 86 fail_libs=() 87 fail_cnt=0 87 fail_cnt=0 88 pass_trgts=() 88 pass_trgts=() 89 pass_libs=() 89 pass_libs=() 90 pass_cnt=0 90 pass_cnt=0 91 91 92 # Get all TARGETS from selftests Makefile 92 # Get all TARGETS from selftests Makefile 93 targets=$(grep -E "^TARGETS +|^TARGETS =" Make 93 targets=$(grep -E "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2) 94 94 95 # Initially, in LDLIBS related lines, the dep 95 # Initially, in LDLIBS related lines, the dep checker needs 96 # to ignore lines containing the following str 96 # to ignore lines containing the following strings: 97 filter="\$(VAR_LDLIBS)\|pkg-config\|PKG_CONFIG 97 filter="\$(VAR_LDLIBS)\|pkg-config\|PKG_CONFIG\|IOURING_EXTRA_LIBS" 98 98 99 # Single test case 99 # Single test case 100 if [ $# -eq 2 ] 100 if [ $# -eq 2 ] 101 then 101 then 102 test=$2/Makefile 102 test=$2/Makefile 103 103 104 l1_test $test 104 l1_test $test 105 l2_test $test 105 l2_test $test 106 l3_test $test 106 l3_test $test 107 l4_test $test 107 l4_test $test 108 l5_test $test 108 l5_test $test 109 109 110 print_results $1 $2 110 print_results $1 $2 111 exit $? 111 exit $? 112 fi 112 fi 113 113 114 # Level 1: LDLIBS set static. 114 # Level 1: LDLIBS set static. 115 # 115 # 116 # Find all LDLIBS set statically for all execu 116 # Find all LDLIBS set statically for all executables built by a Makefile 117 # and filter out VAR_LDLIBS to discard the fol 117 # and filter out VAR_LDLIBS to discard the following: 118 # gpio/Makefile:LDLIBS += $(VAR_LDLIBS) 118 # gpio/Makefile:LDLIBS += $(VAR_LDLIBS) 119 # Append space at the end of the list to appen 119 # Append space at the end of the list to append more tests. 120 120 121 l1_tests=$(grep -r --include=Makefile "^LDLIBS 121 l1_tests=$(grep -r --include=Makefile "^LDLIBS" | \ 122 grep -v "$filter" | awk -F: '{ 122 grep -v "$filter" | awk -F: '{print $1}' | uniq) 123 123 124 # Level 2: LDLIBS set dynamically. 124 # Level 2: LDLIBS set dynamically. 125 # 125 # 126 # Level 2 126 # Level 2 127 # Some tests have multiple valid LDLIBS lines 127 # Some tests have multiple valid LDLIBS lines for individual sub-tests 128 # that need dependency checks. Find them and a 128 # that need dependency checks. Find them and append them to the tests 129 # e.g: mm/Makefile:$(OUTPUT)/userfaultfd: LDLI 129 # e.g: mm/Makefile:$(OUTPUT)/userfaultfd: LDLIBS += -lpthread 130 # Filter out VAR_LDLIBS to discard the followi 130 # Filter out VAR_LDLIBS to discard the following: 131 # memfd/Makefile:$(OUTPUT)/fuse_mnt: LDL 131 # memfd/Makefile:$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS) 132 # Append space at the end of the list to appen 132 # Append space at the end of the list to append more tests. 133 133 134 l2_tests=$(grep -r --include=Makefile ": LDLIB 134 l2_tests=$(grep -r --include=Makefile ": LDLIBS" | \ 135 grep -v "$filter" | awk -F: '{ 135 grep -v "$filter" | awk -F: '{print $1}' | uniq) 136 136 137 # Level 3 137 # Level 3 138 # memfd and others use pkg-config to find moun 138 # memfd and others use pkg-config to find mount and fuse libs 139 # respectively and save it in VAR_LDLIBS. If p 139 # respectively and save it in VAR_LDLIBS. If pkg-config doesn't find 140 # any, VAR_LDLIBS set to default. 140 # any, VAR_LDLIBS set to default. 141 # Use the default value and filter out pkg-con 141 # Use the default value and filter out pkg-config for dependency check. 142 # e.g: 142 # e.g: 143 # memfd/Makefile 143 # memfd/Makefile 144 # VAR_LDLIBS := $(shell pkg-config fuse 144 # VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null) 145 145 146 l3_tests=$(grep -r --include=Makefile "^VAR_LD 146 l3_tests=$(grep -r --include=Makefile "^VAR_LDLIBS" | \ 147 grep -v "pkg-config\|PKG_CONFI 147 grep -v "pkg-config\|PKG_CONFIG" | awk -F: '{print $1}' | uniq) 148 148 149 # Level 4 149 # Level 4 150 # some tests may fall back to default using `| 150 # some tests may fall back to default using `|| echo -l<libname>` 151 # if pkg-config doesn't find the libs, instead 151 # if pkg-config doesn't find the libs, instead of using VAR_LDLIBS 152 # as per level 3 checks. 152 # as per level 3 checks. 153 # e.g: 153 # e.g: 154 # netfilter/Makefile 154 # netfilter/Makefile 155 # LDLIBS += $(shell $(HOSTPKG_CONFIG) -- 155 # LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl) 156 l4_tests=$(grep -r --include=Makefile "^LDLIBS 156 l4_tests=$(grep -r --include=Makefile "^LDLIBS" | \ 157 grep "pkg-config\|PKG_CONFIG" 157 grep "pkg-config\|PKG_CONFIG" | awk -F: '{print $1}' | uniq) 158 158 159 # Level 5 159 # Level 5 160 # some tests may use IOURING_EXTRA_LIBS to add 160 # some tests may use IOURING_EXTRA_LIBS to add extra libs to LDLIBS, 161 # which in turn may be defined in a sub-Makefi 161 # which in turn may be defined in a sub-Makefile 162 # e.g.: 162 # e.g.: 163 # mm/Makefile 163 # mm/Makefile 164 # $(OUTPUT)/gup_longterm: LDLIBS += $(IO 164 # $(OUTPUT)/gup_longterm: LDLIBS += $(IOURING_EXTRA_LIBS) 165 l5_tests=$(grep -r --include=Makefile "LDLIBS 165 l5_tests=$(grep -r --include=Makefile "LDLIBS +=.*\$(IOURING_EXTRA_LIBS)" | \ 166 awk -F: '{print $1}' | uniq) 166 awk -F: '{print $1}' | uniq) 167 167 168 #echo l1_tests $l1_tests 168 #echo l1_tests $l1_tests 169 #echo l2_tests $l2_tests 169 #echo l2_tests $l2_tests 170 #echo l3_tests $l3_tests 170 #echo l3_tests $l3_tests 171 #echo l4_tests $l4_tests 171 #echo l4_tests $l4_tests 172 #echo l5_tests $l5_tests 172 #echo l5_tests $l5_tests 173 173 174 all_tests 174 all_tests 175 print_results $1 $2 175 print_results $1 $2 176 176 177 exit $? 177 exit $? 178 } 178 } 179 # end main() 179 # end main() 180 180 181 all_tests() 181 all_tests() 182 { 182 { 183 for test in $l1_tests; do 183 for test in $l1_tests; do 184 l1_test $test 184 l1_test $test 185 done 185 done 186 186 187 for test in $l2_tests; do 187 for test in $l2_tests; do 188 l2_test $test 188 l2_test $test 189 done 189 done 190 190 191 for test in $l3_tests; do 191 for test in $l3_tests; do 192 l3_test $test 192 l3_test $test 193 done 193 done 194 194 195 for test in $l4_tests; do 195 for test in $l4_tests; do 196 l4_test $test 196 l4_test $test 197 done 197 done 198 198 199 for test in $l5_tests; do 199 for test in $l5_tests; do 200 l5_test $test 200 l5_test $test 201 done 201 done 202 } 202 } 203 203 204 # Use same parsing used for l1_tests and pick 204 # Use same parsing used for l1_tests and pick libraries this time. 205 l1_test() 205 l1_test() 206 { 206 { 207 test_libs=$(grep --include=Makefile "^ 207 test_libs=$(grep --include=Makefile "^LDLIBS" $test | \ 208 grep -v "$filter" | \ 208 grep -v "$filter" | \ 209 sed -e 's/\:/ /' | \ 209 sed -e 's/\:/ /' | \ 210 sed -e 's/+/ /' | cut 210 sed -e 's/+/ /' | cut -d "=" -f 2) 211 211 212 check_libs $test $test_libs 212 check_libs $test $test_libs 213 } 213 } 214 214 215 # Use same parsing used for l2_tests and pick 215 # Use same parsing used for l2_tests and pick libraries this time. 216 l2_test() 216 l2_test() 217 { 217 { 218 test_libs=$(grep --include=Makefile ": 218 test_libs=$(grep --include=Makefile ": LDLIBS" $test | \ 219 grep -v "$filter" | \ 219 grep -v "$filter" | \ 220 sed -e 's/\:/ /' | sed 220 sed -e 's/\:/ /' | sed -e 's/+/ /' | \ 221 cut -d "=" -f 2) 221 cut -d "=" -f 2) 222 222 223 check_libs $test $test_libs 223 check_libs $test $test_libs 224 } 224 } 225 225 226 l3_test() 226 l3_test() 227 { 227 { 228 test_libs=$(grep --include=Makefile "^ 228 test_libs=$(grep --include=Makefile "^VAR_LDLIBS" $test | \ 229 grep -v "pkg-config" | 229 grep -v "pkg-config" | sed -e 's/\:/ /' | 230 sed -e 's/+/ /' | cut 230 sed -e 's/+/ /' | cut -d "=" -f 2) 231 231 232 check_libs $test $test_libs 232 check_libs $test $test_libs 233 } 233 } 234 234 235 l4_test() 235 l4_test() 236 { 236 { 237 test_libs=$(grep --include=Makefile "^ 237 test_libs=$(grep --include=Makefile "^VAR_LDLIBS\|^LDLIBS" $test | \ 238 grep "\(pkg-config\|PK 238 grep "\(pkg-config\|PKG_CONFIG\).*|| echo " | \ 239 sed -e 's/.*|| echo // 239 sed -e 's/.*|| echo //' | sed -e 's/)$//') 240 240 241 check_libs $test $test_libs 241 check_libs $test $test_libs 242 } 242 } 243 243 244 l5_test() 244 l5_test() 245 { 245 { 246 tests=$(find $(dirname "$test") -type 246 tests=$(find $(dirname "$test") -type f -name "*.mk") 247 [[ -z "${tests// }" ]] && return 247 [[ -z "${tests// }" ]] && return 248 test_libs=$(grep "^IOURING_EXTRA_LIBS 248 test_libs=$(grep "^IOURING_EXTRA_LIBS +\?=" $tests | \ 249 cut -d "=" -f 2) 249 cut -d "=" -f 2) 250 250 251 check_libs $test $test_libs 251 check_libs $test $test_libs 252 } 252 } 253 253 254 check_libs() 254 check_libs() 255 { 255 { 256 256 257 if [[ ! -z "${test_libs// }" ]] 257 if [[ ! -z "${test_libs// }" ]] 258 then 258 then 259 259 260 #echo $test_libs 260 #echo $test_libs 261 261 262 for lib in $test_libs; do 262 for lib in $test_libs; do 263 263 264 let total_cnt+=1 264 let total_cnt+=1 265 $CC -o $tmp_file.bin $lib $tmp_file > 265 $CC -o $tmp_file.bin $lib $tmp_file > /dev/null 2>&1 266 if [ $? -ne 0 ]; then 266 if [ $? -ne 0 ]; then 267 echo "FAIL: $test dependency c 267 echo "FAIL: $test dependency check: $lib" >> $fail 268 let fail_cnt+=1 268 let fail_cnt+=1 269 fail_libs+="$lib " 269 fail_libs+="$lib " 270 fail_target=$(echo "$test" | c 270 fail_target=$(echo "$test" | cut -d "/" -f1) 271 fail_trgts+="$fail_target " 271 fail_trgts+="$fail_target " 272 targets=$(echo "$targets" | gr 272 targets=$(echo "$targets" | grep -v "$fail_target") 273 else 273 else 274 echo "PASS: $test dependency c 274 echo "PASS: $test dependency check passed $lib" >> $pass 275 let pass_cnt+=1 275 let pass_cnt+=1 276 pass_libs+="$lib " 276 pass_libs+="$lib " 277 pass_trgts+="$(echo "$test" | 277 pass_trgts+="$(echo "$test" | cut -d "/" -f1) " 278 fi 278 fi 279 279 280 done 280 done 281 fi 281 fi 282 } 282 } 283 283 284 print_results() 284 print_results() 285 { 285 { 286 echo -e "============================= 286 echo -e "========================================================"; 287 echo -e "Kselftest Dependency Check fo 287 echo -e "Kselftest Dependency Check for [$0 $1 $2] results..." 288 288 289 if [ $print_targets -ne 0 ] 289 if [ $print_targets -ne 0 ] 290 then 290 then 291 echo -e "Suggested Selftest Targets fo 291 echo -e "Suggested Selftest Targets for your configuration:" 292 echo -e "$targets"; 292 echo -e "$targets"; 293 fi 293 fi 294 294 295 echo -e "============================= 295 echo -e "========================================================"; 296 echo -e "Checked tests defining LDLIBS 296 echo -e "Checked tests defining LDLIBS dependencies" 297 echo -e "----------------------------- 297 echo -e "--------------------------------------------------------"; 298 echo -e "Total tests with Dependencies 298 echo -e "Total tests with Dependencies:" 299 echo -e "$total_cnt Pass: $pass_cnt Fa 299 echo -e "$total_cnt Pass: $pass_cnt Fail: $fail_cnt"; 300 300 301 if [ $pass_cnt -ne 0 ]; then 301 if [ $pass_cnt -ne 0 ]; then 302 echo -e "----------------------------- 302 echo -e "--------------------------------------------------------"; 303 cat $pass 303 cat $pass 304 echo -e "----------------------------- 304 echo -e "--------------------------------------------------------"; 305 echo -e "Targets passed build dependen 305 echo -e "Targets passed build dependency check on system:" 306 echo -e "$(echo "$pass_trgts" | xargs 306 echo -e "$(echo "$pass_trgts" | xargs -n1 | sort -u | xargs)" 307 fi 307 fi 308 308 309 if [ $fail_cnt -ne 0 ]; then 309 if [ $fail_cnt -ne 0 ]; then 310 echo -e "----------------------------- 310 echo -e "--------------------------------------------------------"; 311 cat $fail 311 cat $fail 312 echo -e "----------------------------- 312 echo -e "--------------------------------------------------------"; 313 echo -e "Targets failed build dependen 313 echo -e "Targets failed build dependency check on system:" 314 echo -e "$(echo "$fail_trgts" | xargs 314 echo -e "$(echo "$fail_trgts" | xargs -n1 | sort -u | xargs)" 315 echo -e "----------------------------- 315 echo -e "--------------------------------------------------------"; 316 echo -e "Missing libraries system" 316 echo -e "Missing libraries system" 317 echo -e "$(echo "$fail_libs" | xargs - 317 echo -e "$(echo "$fail_libs" | xargs -n1 | sort -u | xargs)" 318 fi 318 fi 319 319 320 echo -e "----------------------------- 320 echo -e "--------------------------------------------------------"; 321 echo -e "============================= 321 echo -e "========================================================"; 322 } 322 } 323 323 324 main "$@" 324 main "$@"
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.