xref: /linux/tools/testing/selftests/nolibc/run-tests.sh (revision bb29b957eaaa15be33243550d9ee576c2d601669)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# Test runner for nolibc tests
5
6set -e
7
8trap 'echo Aborting...' 'ERR'
9
10crosstool_version=15.2.0
11hostarch=x86_64
12nproc=$(( $(nproc) + 2))
13cache_dir="${XDG_CACHE_HOME:-"$HOME"/.cache}"
14download_location="${cache_dir}/crosstools/"
15build_location="$(realpath "${cache_dir}"/nolibc-tests/)"
16perform_download=0
17test_mode=system
18werror=1
19llvm=
20all_archs=(
21	i386 x86_64 x32
22	arm64 arm armthumb
23	mips32le mips32be mipsn32le mipsn32be mips64le mips64be
24	openrisc
25	ppc ppc64 ppc64le
26	riscv32 riscv64
27	s390x
28	loongarch
29	sparc32 sparc64
30	m68k
31	sh4
32	parisc32 parisc64
33	alpha
34	hexagon
35)
36archs="${all_archs[@]}"
37
38TEMP=$(getopt -o 'j:d:c:b:a:m:pelh' -n "$0" -- "$@")
39
40eval set -- "$TEMP"
41unset TEMP
42
43print_usage() {
44	cat <<EOF
45Run nolibc testsuite for multiple architectures with crosstools
46
47Usage:
48 $0 [options] <architectures>
49
50Known architectures:
51 ${archs}
52
53Options:
54 -j [N]         Allow N jobs at once (default: ${nproc})
55 -p             Allow download of toolchains
56 -d [DIR]       Download location for toolchains (default: ${download_location})
57 -c [VERSION]   Version of toolchains to use (default: ${crosstool_version})
58 -a [ARCH]      Host architecture of toolchains to use (default: ${hostarch})
59 -b [DIR]       Build location (default: ${build_location})
60 -m [MODE]      Test mode user/system (default: ${test_mode})
61 -e             Disable -Werror
62 -l             Build with LLVM/clang
63EOF
64}
65
66while true; do
67	case "$1" in
68		'-j')
69			nproc="$2"
70			shift 2; continue ;;
71		'-p')
72			perform_download=1
73			shift; continue ;;
74		'-d')
75			download_location="$2"
76			shift 2; continue ;;
77		'-c')
78			crosstool_version="$2"
79			shift 2; continue ;;
80		'-a')
81			hostarch="$2"
82			shift 2; continue ;;
83		'-b')
84			build_location="$(realpath "$2")"
85			shift 2; continue ;;
86		'-m')
87			test_mode="$2"
88			shift 2; continue ;;
89		'-e')
90			werror=0
91			shift; continue ;;
92		'-l')
93			llvm=1
94			shift; continue ;;
95		'-h')
96			print_usage
97			exit 0
98			;;
99		'--')
100			shift; break ;;
101		*)
102			echo 'Internal error!' >&2; exit 1 ;;
103	esac
104done
105
106if [[ -n "$*" ]]; then
107	archs="$*"
108fi
109
110crosstool_arch() {
111	case "$1" in
112	arm64) echo aarch64;;
113	armthumb) echo arm;;
114	openrisc) echo or1k;;
115	ppc) echo powerpc;;
116	ppc64) echo powerpc64;;
117	ppc64le) echo powerpc64;;
118	riscv) echo riscv64;;
119	loongarch) echo loongarch64;;
120	mips*) echo mips;;
121	s390*) echo s390;;
122	sparc*) echo sparc64;;
123	x32*) echo x86_64;;
124	parisc32) echo hppa;;
125	parisc64) echo hppa64;;
126	*) echo "$1";;
127	esac
128}
129
130crosstool_abi() {
131	case "$1" in
132	arm | armthumb) echo linux-gnueabi;;
133	*) echo linux;;
134	esac
135}
136
137need_gcc() {
138	case "$1" in
139	hexagon);;
140	*) echo "1";;
141	esac
142}
143
144download_crosstool() {
145	arch="$(crosstool_arch "$1")"
146	abi="$(crosstool_abi "$1")"
147
148	archive_name="${hostarch}-gcc-${crosstool_version}-nolibc-${arch}-${abi}.tar.gz"
149	url="https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/${hostarch}/${crosstool_version}/${archive_name}"
150	archive="${download_location}${archive_name}"
151	stamp="${archive}.stamp"
152
153	[ -f "${stamp}" ] && return
154
155	echo "Downloading crosstools ${arch} ${crosstool_version}"
156	mkdir -p "${download_location}"
157	curl -o "${archive}" --fail --continue-at - "${url}"
158	tar -C "${download_location}" -xf "${archive}"
159	touch "${stamp}"
160}
161
162# capture command output, print it on failure
163# mimics chronic(1) from moreutils
164function swallow_output() {
165	if ! OUTPUT="$("$@" 2>&1)"; then
166		echo "$OUTPUT"
167		return 1
168	fi
169	return 0
170}
171
172test_arch() {
173	arch=$1
174	ct_arch=$(crosstool_arch "$arch")
175	ct_abi=$(crosstool_abi "$1")
176	gcc="$(need_gcc "$1")"
177	cross_compile=
178
179	if [ -n "$gcc" ] && [ ! -d "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/." ]; then
180		echo "No toolchain found in ${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}."
181		echo "Did you install the toolchains or set the correct arch ? Rerun with -h for help."
182		return 1
183	fi
184
185	if [ -n "$gcc" ]; then
186		cross_compile=$(realpath "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/${ct_arch}-${ct_abi}-")
187	fi
188	build_dir="${build_location}/${arch}"
189	if [ "$werror" -ne 0 ]; then
190		CFLAGS_EXTRA="$CFLAGS_EXTRA -Werror -Wl,--fatal-warnings"
191	fi
192	MAKE=(make -f Makefile.nolibc -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" LLVM="${llvm}" O="${build_dir}")
193
194	if [ "$arch" = "parisc32" ]; then
195		MAKE+=("CROSS32CC=${cross_compile}gcc")
196	fi
197
198	case "$test_mode" in
199		'system')
200			test_target=run
201			;;
202		'user')
203			test_target=run-user
204			;;
205		*)
206			echo "Unknown mode $test_mode"
207			exit 1
208	esac
209	printf '%-15s' "$arch:"
210	if [ "$llvm" = "1" ] && \
211	   [ "$arch" = "m68k" -o "$arch" = "sh4" -o "$arch" = "openrisc" \
212	     -o "$arch" == "parisc32" -o "$arch" == "parisc64" -o "$arch" = "alpha"  \
213	]; then
214		echo "Unsupported configuration"
215		return
216	fi
217	if [ "$test_mode" = "user" ] && [ "$arch" = "x32" -o "$arch" = "parisc64" ]; then
218		echo "Unsupported configuration"
219		return
220	fi
221	if [ -z "$llvm" -o "$test_mode" = "system" ] && [ "$arch" = "hexagon" ]; then
222		echo "Unsupported configuration"
223		return
224	fi
225
226	mkdir -p "$build_dir"
227	swallow_output "${MAKE[@]}" defconfig
228	swallow_output "${MAKE[@]}" CFLAGS_EXTRA="$CFLAGS_EXTRA" "$test_target" V=1
229	cp run.out run.out."${arch}"
230	"${MAKE[@]}" report | grep passed
231}
232
233if [ "$perform_download" -ne 0 ]; then
234	for arch in $archs; do
235		download_crosstool "$arch"
236	done
237fi
238
239for arch in $archs; do
240	test_arch "$arch"
241done
242