Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/kselftest_deps.sh
26298 views
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 mm"
16
echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc"
17
echo -e "\tkselftest_deps.sh [-p] aarch64-linux-gnu-gcc mm\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=$(grep -E "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2)
94
95
# Initially, in LDLIBS related lines, the dep checker needs
96
# to ignore lines containing the following strings:
97
filter="\$(VAR_LDLIBS)\|pkg-config\|PKG_CONFIG\|IOURING_EXTRA_LIBS"
98
99
# Single test case
100
if [ $# -eq 2 ]
101
then
102
test=$2/Makefile
103
104
l1_test $test
105
l2_test $test
106
l3_test $test
107
l4_test $test
108
l5_test $test
109
110
print_results $1 $2
111
exit $?
112
fi
113
114
# Level 1: LDLIBS set static.
115
#
116
# Find all LDLIBS set statically for all executables built by a Makefile
117
# and filter out VAR_LDLIBS to discard the following:
118
# gpio/Makefile:LDLIBS += $(VAR_LDLIBS)
119
# Append space at the end of the list to append more tests.
120
121
l1_tests=$(grep -r --include=Makefile "^LDLIBS" | \
122
grep -v "$filter" | awk -F: '{print $1}' | uniq)
123
124
# Level 2: LDLIBS set dynamically.
125
#
126
# Level 2
127
# Some tests have multiple valid LDLIBS lines for individual sub-tests
128
# that need dependency checks. Find them and append them to the tests
129
# e.g: mm/Makefile:$(OUTPUT)/userfaultfd: LDLIBS += -lpthread
130
# Filter out VAR_LDLIBS to discard the following:
131
# memfd/Makefile:$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS)
132
# Append space at the end of the list to append more tests.
133
134
l2_tests=$(grep -r --include=Makefile ": LDLIBS" | \
135
grep -v "$filter" | awk -F: '{print $1}' | uniq)
136
137
# Level 3
138
# memfd and others use pkg-config to find mount and fuse libs
139
# respectively and save it in VAR_LDLIBS. If pkg-config doesn't find
140
# any, VAR_LDLIBS set to default.
141
# Use the default value and filter out pkg-config for dependency check.
142
# e.g:
143
# memfd/Makefile
144
# VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null)
145
146
l3_tests=$(grep -r --include=Makefile "^VAR_LDLIBS" | \
147
grep -v "pkg-config\|PKG_CONFIG" | awk -F: '{print $1}' | uniq)
148
149
# Level 4
150
# some tests may fall back to default using `|| echo -l<libname>`
151
# if pkg-config doesn't find the libs, instead of using VAR_LDLIBS
152
# as per level 3 checks.
153
# e.g:
154
# netfilter/Makefile
155
# LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl)
156
l4_tests=$(grep -r --include=Makefile "^LDLIBS" | \
157
grep "pkg-config\|PKG_CONFIG" | awk -F: '{print $1}' | uniq)
158
159
# Level 5
160
# some tests may use IOURING_EXTRA_LIBS to add extra libs to LDLIBS,
161
# which in turn may be defined in a sub-Makefile
162
# e.g.:
163
# mm/Makefile
164
# $(OUTPUT)/gup_longterm: LDLIBS += $(IOURING_EXTRA_LIBS)
165
l5_tests=$(grep -r --include=Makefile "LDLIBS +=.*\$(IOURING_EXTRA_LIBS)" | \
166
awk -F: '{print $1}' | uniq)
167
168
#echo l1_tests $l1_tests
169
#echo l2_tests $l2_tests
170
#echo l3_tests $l3_tests
171
#echo l4_tests $l4_tests
172
#echo l5_tests $l5_tests
173
174
all_tests
175
print_results $1 $2
176
177
exit $?
178
}
179
# end main()
180
181
all_tests()
182
{
183
for test in $l1_tests; do
184
l1_test $test
185
done
186
187
for test in $l2_tests; do
188
l2_test $test
189
done
190
191
for test in $l3_tests; do
192
l3_test $test
193
done
194
195
for test in $l4_tests; do
196
l4_test $test
197
done
198
199
for test in $l5_tests; do
200
l5_test $test
201
done
202
}
203
204
# Use same parsing used for l1_tests and pick libraries this time.
205
l1_test()
206
{
207
test_libs=$(grep --include=Makefile "^LDLIBS" $test | \
208
grep -v "$filter" | \
209
sed -e 's/\:/ /' | \
210
sed -e 's/+/ /' | cut -d "=" -f 2)
211
212
check_libs $test $test_libs
213
}
214
215
# Use same parsing used for l2_tests and pick libraries this time.
216
l2_test()
217
{
218
test_libs=$(grep --include=Makefile ": LDLIBS" $test | \
219
grep -v "$filter" | \
220
sed -e 's/\:/ /' | sed -e 's/+/ /' | \
221
cut -d "=" -f 2)
222
223
check_libs $test $test_libs
224
}
225
226
l3_test()
227
{
228
test_libs=$(grep --include=Makefile "^VAR_LDLIBS" $test | \
229
grep -v "pkg-config" | sed -e 's/\:/ /' |
230
sed -e 's/+/ /' | cut -d "=" -f 2)
231
232
check_libs $test $test_libs
233
}
234
235
l4_test()
236
{
237
test_libs=$(grep --include=Makefile "^VAR_LDLIBS\|^LDLIBS" $test | \
238
grep "\(pkg-config\|PKG_CONFIG\).*|| echo " | \
239
sed -e 's/.*|| echo //' | sed -e 's/)$//')
240
241
check_libs $test $test_libs
242
}
243
244
l5_test()
245
{
246
tests=$(find $(dirname "$test") -type f -name "*.mk")
247
[[ -z "${tests// }" ]] && return
248
test_libs=$(grep "^IOURING_EXTRA_LIBS +\?=" $tests | \
249
cut -d "=" -f 2)
250
251
check_libs $test $test_libs
252
}
253
254
check_libs()
255
{
256
257
if [[ ! -z "${test_libs// }" ]]
258
then
259
260
#echo $test_libs
261
262
for lib in $test_libs; do
263
264
let total_cnt+=1
265
$CC -o $tmp_file.bin $lib $tmp_file > /dev/null 2>&1
266
if [ $? -ne 0 ]; then
267
echo "FAIL: $test dependency check: $lib" >> $fail
268
let fail_cnt+=1
269
fail_libs+="$lib "
270
fail_target=$(echo "$test" | cut -d "/" -f1)
271
fail_trgts+="$fail_target "
272
targets=$(echo "$targets" | grep -v "$fail_target")
273
else
274
echo "PASS: $test dependency check passed $lib" >> $pass
275
let pass_cnt+=1
276
pass_libs+="$lib "
277
pass_trgts+="$(echo "$test" | cut -d "/" -f1) "
278
fi
279
280
done
281
fi
282
}
283
284
print_results()
285
{
286
echo -e "========================================================";
287
echo -e "Kselftest Dependency Check for [$0 $1 $2] results..."
288
289
if [ $print_targets -ne 0 ]
290
then
291
echo -e "Suggested Selftest Targets for your configuration:"
292
echo -e "$targets";
293
fi
294
295
echo -e "========================================================";
296
echo -e "Checked tests defining LDLIBS dependencies"
297
echo -e "--------------------------------------------------------";
298
echo -e "Total tests with Dependencies:"
299
echo -e "$total_cnt Pass: $pass_cnt Fail: $fail_cnt";
300
301
if [ $pass_cnt -ne 0 ]; then
302
echo -e "--------------------------------------------------------";
303
cat $pass
304
echo -e "--------------------------------------------------------";
305
echo -e "Targets passed build dependency check on system:"
306
echo -e "$(echo "$pass_trgts" | xargs -n1 | sort -u | xargs)"
307
fi
308
309
if [ $fail_cnt -ne 0 ]; then
310
echo -e "--------------------------------------------------------";
311
cat $fail
312
echo -e "--------------------------------------------------------";
313
echo -e "Targets failed build dependency check on system:"
314
echo -e "$(echo "$fail_trgts" | xargs -n1 | sort -u | xargs)"
315
echo -e "--------------------------------------------------------";
316
echo -e "Missing libraries system"
317
echo -e "$(echo "$fail_libs" | xargs -n1 | sort -u | xargs)"
318
fi
319
320
echo -e "--------------------------------------------------------";
321
echo -e "========================================================";
322
}
323
324
main "$@"
325
326