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