|
| 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 <[email protected]> |
| 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 "$@" |
0 commit comments