Commit | Line | Data |
---|---|---|
93a4388b SK |
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" | |
baa489fa | 15 | echo -e "\tkselftest_deps.sh [-p] gcc mm" |
93a4388b | 16 | echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc" |
baa489fa | 17 | echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc mm\n" |
93a4388b SK |
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." | |
18afe1bf | 29 | echo "- Optional: test name can be specified to check dependencies for it." |
93a4388b SK |
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 | |
b20ebaa7 | 93 | targets=$(grep -E "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2) |
93a4388b SK |
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 | |
baa489fa | 123 | # e.g: mm/Makefile:$(OUTPUT)/userfaultfd: LDLIBS += -lpthread |
93a4388b SK |
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 | |
999e71c3 | 132 | # memfd and others use pkg-config to find mount and fuse libs |
93a4388b SK |
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: | |
93a4388b SK |
137 | # memfd/Makefile |
138 | # VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null) | |
139 | ||
140 | l3_tests=$(grep -r --include=Makefile "^VAR_LDLIBS" | \ | |
141 | grep -v "pkg-config" | awk -F: '{print $1}') | |
142 | ||
143 | #echo $l1_tests | |
144 | #echo $l2_1_tests | |
145 | #echo $l3_tests | |
146 | ||
147 | all_tests | |
148 | print_results $1 $2 | |
149 | ||
150 | exit $? | |
151 | } | |
152 | # end main() | |
153 | ||
154 | all_tests() | |
155 | { | |
156 | for test in $l1_tests; do | |
157 | l1_test $test | |
158 | done | |
159 | ||
160 | for test in $l2_tests; do | |
161 | l2_test $test | |
162 | done | |
163 | ||
164 | for test in $l3_tests; do | |
165 | l3_test $test | |
166 | done | |
167 | } | |
168 | ||
169 | # Use same parsing used for l1_tests and pick libraries this time. | |
170 | l1_test() | |
171 | { | |
172 | test_libs=$(grep --include=Makefile "^LDLIBS" $test | \ | |
173 | grep -v "VAR_LDLIBS" | \ | |
174 | sed -e 's/\:/ /' | \ | |
175 | sed -e 's/+/ /' | cut -d "=" -f 2) | |
176 | ||
177 | check_libs $test $test_libs | |
178 | } | |
179 | ||
180 | # Use same parsing used for l2__tests and pick libraries this time. | |
181 | l2_test() | |
182 | { | |
183 | test_libs=$(grep --include=Makefile ": LDLIBS" $test | \ | |
184 | grep -v "VAR_LDLIBS" | \ | |
185 | sed -e 's/\:/ /' | sed -e 's/+/ /' | \ | |
186 | cut -d "=" -f 2) | |
187 | ||
188 | check_libs $test $test_libs | |
189 | } | |
190 | ||
191 | l3_test() | |
192 | { | |
193 | test_libs=$(grep --include=Makefile "^VAR_LDLIBS" $test | \ | |
194 | grep -v "pkg-config" | sed -e 's/\:/ /' | | |
195 | sed -e 's/+/ /' | cut -d "=" -f 2) | |
196 | ||
197 | check_libs $test $test_libs | |
198 | } | |
199 | ||
200 | check_libs() | |
201 | { | |
202 | ||
203 | if [[ ! -z "${test_libs// }" ]] | |
204 | then | |
205 | ||
206 | #echo $test_libs | |
207 | ||
208 | for lib in $test_libs; do | |
209 | ||
210 | let total_cnt+=1 | |
211 | $CC -o $tmp_file.bin $lib $tmp_file > /dev/null 2>&1 | |
212 | if [ $? -ne 0 ]; then | |
213 | echo "FAIL: $test dependency check: $lib" >> $fail | |
214 | let fail_cnt+=1 | |
215 | fail_libs+="$lib " | |
216 | fail_target=$(echo "$test" | cut -d "/" -f1) | |
217 | fail_trgts+="$fail_target " | |
218 | targets=$(echo "$targets" | grep -v "$fail_target") | |
219 | else | |
220 | echo "PASS: $test dependency check passed $lib" >> $pass | |
221 | let pass_cnt+=1 | |
222 | pass_libs+="$lib " | |
223 | pass_trgts+="$(echo "$test" | cut -d "/" -f1) " | |
224 | fi | |
225 | ||
226 | done | |
227 | fi | |
228 | } | |
229 | ||
230 | print_results() | |
231 | { | |
232 | echo -e "========================================================"; | |
233 | echo -e "Kselftest Dependency Check for [$0 $1 $2] results..." | |
234 | ||
235 | if [ $print_targets -ne 0 ] | |
236 | then | |
237 | echo -e "Suggested Selftest Targets for your configuration:" | |
238 | echo -e "$targets"; | |
239 | fi | |
240 | ||
241 | echo -e "========================================================"; | |
242 | echo -e "Checked tests defining LDLIBS dependencies" | |
243 | echo -e "--------------------------------------------------------"; | |
244 | echo -e "Total tests with Dependencies:" | |
245 | echo -e "$total_cnt Pass: $pass_cnt Fail: $fail_cnt"; | |
246 | ||
247 | if [ $pass_cnt -ne 0 ]; then | |
248 | echo -e "--------------------------------------------------------"; | |
249 | cat $pass | |
250 | echo -e "--------------------------------------------------------"; | |
251 | echo -e "Targets passed build dependency check on system:" | |
252 | echo -e "$(echo "$pass_trgts" | xargs -n1 | sort -u | xargs)" | |
253 | fi | |
254 | ||
255 | if [ $fail_cnt -ne 0 ]; then | |
256 | echo -e "--------------------------------------------------------"; | |
257 | cat $fail | |
258 | echo -e "--------------------------------------------------------"; | |
259 | echo -e "Targets failed build dependency check on system:" | |
260 | echo -e "$(echo "$fail_trgts" | xargs -n1 | sort -u | xargs)" | |
261 | echo -e "--------------------------------------------------------"; | |
262 | echo -e "Missing libraries system" | |
263 | echo -e "$(echo "$fail_libs" | xargs -n1 | sort -u | xargs)" | |
264 | fi | |
265 | ||
266 | echo -e "--------------------------------------------------------"; | |
267 | echo -e "========================================================"; | |
268 | } | |
269 | ||
270 | main "$@" |