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