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