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