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