| #!/bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| |
| # Test runner for nolibc tests |
| |
| set -e |
| |
| trap 'echo Aborting...' 'ERR' |
| |
| crosstool_version=13.2.0 |
| hostarch=x86_64 |
| nproc=$(( $(nproc) + 2)) |
| cache_dir="${XDG_CACHE_HOME:-"$HOME"/.cache}" |
| download_location="${cache_dir}/crosstools/" |
| build_location="$(realpath "${cache_dir}"/nolibc-tests/)" |
| perform_download=0 |
| test_mode=system |
| werror=1 |
| llvm= |
| archs="i386 x86_64 arm64 arm mips32le mips32be ppc ppc64 ppc64le riscv s390 loongarch" |
| |
| TEMP=$(getopt -o 'j:d:c:b:a:m:pelh' -n "$0" -- "$@") |
| |
| eval set -- "$TEMP" |
| unset TEMP |
| |
| print_usage() { |
| cat <<EOF |
| Run nolibc testsuite for multiple architectures with crosstools |
| |
| Usage: |
| $0 [options] <architectures> |
| |
| Known architectures: |
| ${archs} |
| |
| Options: |
| -j [N] Allow N jobs at once (default: ${nproc}) |
| -p Allow download of toolchains |
| -d [DIR] Download location for toolchains (default: ${download_location}) |
| -c [VERSION] Version of toolchains to use (default: ${crosstool_version}) |
| -a [ARCH] Host architecture of toolchains to use (default: ${hostarch}) |
| -b [DIR] Build location (default: ${build_location}) |
| -m [MODE] Test mode user/system (default: ${test_mode}) |
| -e Disable -Werror |
| -l Build with LLVM/clang |
| EOF |
| } |
| |
| while true; do |
| case "$1" in |
| '-j') |
| nproc="$2" |
| shift 2; continue ;; |
| '-p') |
| perform_download=1 |
| shift; continue ;; |
| '-d') |
| download_location="$2" |
| shift 2; continue ;; |
| '-c') |
| crosstool_version="$2" |
| shift 2; continue ;; |
| '-a') |
| hostarch="$2" |
| shift 2; continue ;; |
| '-b') |
| build_location="$(realpath "$2")" |
| shift 2; continue ;; |
| '-m') |
| test_mode="$2" |
| shift 2; continue ;; |
| '-e') |
| werror=0 |
| shift; continue ;; |
| '-l') |
| llvm=1 |
| shift; continue ;; |
| '-h') |
| print_usage |
| exit 0 |
| ;; |
| '--') |
| shift; break ;; |
| *) |
| echo 'Internal error!' >&2; exit 1 ;; |
| esac |
| done |
| |
| if [[ -n "$*" ]]; then |
| archs="$*" |
| fi |
| |
| crosstool_arch() { |
| case "$1" in |
| arm64) echo aarch64;; |
| ppc) echo powerpc;; |
| ppc64) echo powerpc64;; |
| ppc64le) echo powerpc64;; |
| riscv) echo riscv64;; |
| loongarch) echo loongarch64;; |
| mips*) echo mips;; |
| *) echo "$1";; |
| esac |
| } |
| |
| crosstool_abi() { |
| case "$1" in |
| arm) echo linux-gnueabi;; |
| *) echo linux;; |
| esac |
| } |
| |
| download_crosstool() { |
| arch="$(crosstool_arch "$1")" |
| abi="$(crosstool_abi "$1")" |
| |
| archive_name="${hostarch}-gcc-${crosstool_version}-nolibc-${arch}-${abi}.tar.gz" |
| url="https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/${hostarch}/${crosstool_version}/${archive_name}" |
| archive="${download_location}${archive_name}" |
| stamp="${archive}.stamp" |
| |
| [ -f "${stamp}" ] && return |
| |
| echo "Downloading crosstools ${arch} ${crosstool_version}" |
| mkdir -p "${download_location}" |
| curl -o "${archive}" --fail --continue-at - "${url}" |
| tar -C "${download_location}" -xf "${archive}" |
| touch "${stamp}" |
| } |
| |
| # capture command output, print it on failure |
| # mimics chronic(1) from moreutils |
| function swallow_output() { |
| if ! OUTPUT="$("$@" 2>&1)"; then |
| echo "$OUTPUT" |
| return 1 |
| fi |
| return 0 |
| } |
| |
| test_arch() { |
| arch=$1 |
| ct_arch=$(crosstool_arch "$arch") |
| ct_abi=$(crosstool_abi "$1") |
| cross_compile=$(realpath "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/${ct_arch}-${ct_abi}-") |
| build_dir="${build_location}/${arch}" |
| if [ "$werror" -ne 0 ]; then |
| CFLAGS_EXTRA="$CFLAGS_EXTRA -Werror" |
| fi |
| MAKE=(make -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" LLVM="${llvm}" O="${build_dir}") |
| |
| mkdir -p "$build_dir" |
| if [ "$test_mode" = "system" ] && [ ! -f "${build_dir}/.config" ]; then |
| swallow_output "${MAKE[@]}" defconfig |
| fi |
| case "$test_mode" in |
| 'system') |
| test_target=run |
| ;; |
| 'user') |
| test_target=run-user |
| ;; |
| *) |
| echo "Unknown mode $test_mode" |
| exit 1 |
| esac |
| printf '%-15s' "$arch:" |
| swallow_output "${MAKE[@]}" CFLAGS_EXTRA="$CFLAGS_EXTRA" "$test_target" V=1 |
| cp run.out run.out."${arch}" |
| "${MAKE[@]}" report | grep passed |
| } |
| |
| if [ "$perform_download" -ne 0 ]; then |
| for arch in $archs; do |
| download_crosstool "$arch" |
| done |
| fi |
| |
| for arch in $archs; do |
| test_arch "$arch" |
| done |