xref: /linux/tools/testing/selftests/nolibc/run-tests.sh (revision 7fc2cd2e4b398c57c9cf961cfea05eadbf34c05c)
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 x32
22	arm64 arm armthumb
23	mips32le mips32be mipsn32le mipsn32be mips64le mips64be
24	ppc ppc64 ppc64le
25	riscv32 riscv64
26	s390x
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	x32*) echo x86_64;;
119	*) echo "$1";;
120	esac
121}
122
123crosstool_abi() {
124	case "$1" in
125	arm | armthumb) echo linux-gnueabi;;
126	*) echo linux;;
127	esac
128}
129
130download_crosstool() {
131	arch="$(crosstool_arch "$1")"
132	abi="$(crosstool_abi "$1")"
133
134	archive_name="${hostarch}-gcc-${crosstool_version}-nolibc-${arch}-${abi}.tar.gz"
135	url="https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/${hostarch}/${crosstool_version}/${archive_name}"
136	archive="${download_location}${archive_name}"
137	stamp="${archive}.stamp"
138
139	[ -f "${stamp}" ] && return
140
141	echo "Downloading crosstools ${arch} ${crosstool_version}"
142	mkdir -p "${download_location}"
143	curl -o "${archive}" --fail --continue-at - "${url}"
144	tar -C "${download_location}" -xf "${archive}"
145	touch "${stamp}"
146}
147
148# capture command output, print it on failure
149# mimics chronic(1) from moreutils
150function swallow_output() {
151	if ! OUTPUT="$("$@" 2>&1)"; then
152		echo "$OUTPUT"
153		return 1
154	fi
155	return 0
156}
157
158test_arch() {
159	arch=$1
160	ct_arch=$(crosstool_arch "$arch")
161	ct_abi=$(crosstool_abi "$1")
162
163	if [ ! -d "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/." ]; then
164		echo "No toolchain found in ${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}."
165		echo "Did you install the toolchains or set the correct arch ? Rerun with -h for help."
166		return 1
167	fi
168
169	cross_compile=$(realpath "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/${ct_arch}-${ct_abi}-")
170	build_dir="${build_location}/${arch}"
171	if [ "$werror" -ne 0 ]; then
172		CFLAGS_EXTRA="$CFLAGS_EXTRA -Werror -Wl,--fatal-warnings"
173	fi
174	MAKE=(make -f Makefile.nolibc -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" LLVM="${llvm}" O="${build_dir}")
175
176	case "$test_mode" in
177		'system')
178			test_target=run
179			;;
180		'user')
181			test_target=run-user
182			;;
183		*)
184			echo "Unknown mode $test_mode"
185			exit 1
186	esac
187	printf '%-15s' "$arch:"
188	if [ "$arch" = "m68k" -o "$arch" = "sh4" ] && [ "$llvm" = "1" ]; then
189		echo "Unsupported configuration"
190		return
191	fi
192	if [ "$arch" = "x32" ] && [ "$test_mode" = "user" ]; then
193		echo "Unsupported configuration"
194		return
195	fi
196
197	mkdir -p "$build_dir"
198	swallow_output "${MAKE[@]}" defconfig
199	swallow_output "${MAKE[@]}" CFLAGS_EXTRA="$CFLAGS_EXTRA" "$test_target" V=1
200	cp run.out run.out."${arch}"
201	"${MAKE[@]}" report | grep passed
202}
203
204if [ "$perform_download" -ne 0 ]; then
205	for arch in $archs; do
206		download_crosstool "$arch"
207	done
208fi
209
210for arch in $archs; do
211	test_arch "$arch"
212done
213