From 8971bf0b0e243113e12da7cfd273ffe8acd7b5d1 Mon Sep 17 00:00:00 2001 From: Corentin Le Molgat Date: Mon, 25 Oct 2021 11:34:59 +0200 Subject: [PATCH] tools: Rework cross compilation scripts - Use stderr for issues - Add usage to run_integration.sh (-h or --help) - deduce toolchain and qemu config from TARGET - Bump QEMU from 2.11.1 to 5.2.0 - fix qemu build on Archlinux - Bump Linaro: toolchain 7.2-2017.11 -> 7.5-2019.12 sysroot 2.25-2017.11 -> 2.25-2019.12 - Bump codescape from 2017.10-08 to 2020.06-01 - migrate from mips-r2-hard to mips-r6-hard --- scripts/run_integration.sh | 435 ++++++++++++++++++++++++------------ scripts/test_integration.sh | 59 ++--- 2 files changed, 311 insertions(+), 183 deletions(-) diff --git a/scripts/run_integration.sh b/scripts/run_integration.sh index fd88d60..e1487b2 100755 --- a/scripts/run_integration.sh +++ b/scripts/run_integration.sh @@ -1,209 +1,364 @@ #!/usr/bin/env bash -readonly SCRIPT_FOLDER=$(cd -P -- "$(dirname -- "$0")" && pwd -P) -readonly PROJECT_FOLDER="${SCRIPT_FOLDER}/.." -readonly ARCHIVE_FOLDER=~/cpu_features_archives -readonly QEMU_INSTALL=${ARCHIVE_FOLDER}/qemu -readonly DEFAULT_CMAKE_ARGS=" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON" +set -eo pipefail function extract() { + echo "Extracting ${1}..." case $1 in *.tar.bz2) tar xjf "$1" ;; *.tar.xz) tar xJf "$1" ;; *.tar.gz) tar xzf "$1" ;; *) - echo "don't know how to extract '$1'..." + >&2 echo "don't know how to extract '$1'..." exit 1 esac } -function unpackifnotexists() { - mkdir -p "${ARCHIVE_FOLDER}" - cd "${ARCHIVE_FOLDER}" || exit - local URL=$1 - local RELATIVE_FOLDER=$2 - local DESTINATION="${ARCHIVE_FOLDER}/${RELATIVE_FOLDER}" +function unpack() { + mkdir -p "${ARCHIVE_DIR}" + cd "${ARCHIVE_DIR}" || exit 2 + local -r URL=$1 + local -r RELATIVE_DIR=$2 + local -r DESTINATION="${ARCHIVE_DIR}/${RELATIVE_DIR}" if [[ ! -d "${DESTINATION}" ]] ; then - local ARCHIVE_NAME=$(echo ${URL} | sed 's/.*\///') - test -f "${ARCHIVE_NAME}" || wget -q "${URL}" + echo "Downloading ${URL}..." + local -r ARCHIVE_NAME=$(basename "${URL}") + test -f "${ARCHIVE_NAME}" || wget --no-verbose "${URL}" extract "${ARCHIVE_NAME}" rm -f "${ARCHIVE_NAME}" fi } -function installqemuifneeded() { - local VERSION=${QEMU_VERSION:=2.11.1} - local ARCHES=${QEMU_ARCHES:=arm aarch64 i386 x86_64 mips mipsel mips64 mips64el} - local TARGETS=${QEMU_TARGETS:=$(echo "$ARCHES" | sed 's#$# #;s#\([^ ]*\) #\1-linux-user #g')} +function install_qemu() { + if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then + >&2 echo 'QEMU is disabled !' + return 0 + fi + local -r QEMU_VERSION=${QEMU_VERSION:=5.2.0} + local -r QEMU_TARGET=${QEMU_ARCH}-linux-user - if echo "${VERSION} ${TARGETS}" | cmp --silent ${QEMU_INSTALL}/.build -; then - echo "qemu ${VERSION} up to date!" + if echo "${QEMU_VERSION} ${QEMU_TARGET}" | cmp --silent "${QEMU_INSTALL}/.build" -; then + echo "qemu ${QEMU_VERSION} up to date!" return 0 fi - echo "VERSION: ${VERSION}" - echo "TARGETS: ${TARGETS}" + echo "QEMU_VERSION: ${QEMU_VERSION}" + echo "QEMU_TARGET: ${QEMU_TARGET}" - rm -rf ${QEMU_INSTALL} + rm -rf "${QEMU_INSTALL}" # Checking for a tarball before downloading makes testing easier :-) - local QEMU_URL="http://wiki.qemu-project.org/download/qemu-${VERSION}.tar.xz" - local QEMU_FOLDER="qemu-${VERSION}" - unpackifnotexists ${QEMU_URL} ${QEMU_FOLDER} - cd ${QEMU_FOLDER} || exit + local -r QEMU_URL="http://wiki.qemu-project.org/download/qemu-${QEMU_VERSION}.tar.xz" + local -r QEMU_DIR="qemu-${QEMU_VERSION}" + unpack ${QEMU_URL} ${QEMU_DIR} + cd ${QEMU_DIR} || exit 2 + # Qemu (meson based build) depends on: pkgconf, libglib2.0, python3, ninja ./configure \ - --prefix="${QEMU_INSTALL}" \ - --target-list="${TARGETS}" \ - --disable-docs \ - --disable-sdl \ - --disable-gtk \ - --disable-gnutls \ - --disable-gcrypt \ - --disable-nettle \ + --prefix=${QEMU_INSTALL} \ + --target-list=${QEMU_TARGET} \ + --audio-drv-list= \ + --disable-brlapi \ + --disable-curl \ --disable-curses \ - --static + --disable-docs \ + --disable-gcrypt \ + --disable-gnutls \ + --disable-gtk \ + --disable-libnfs \ + --disable-libssh \ + --disable-nettle \ + --disable-opengl \ + --disable-sdl \ + --disable-virglrenderer \ + --disable-vte \ + --enable-modules - make -j4 + # --static Not supported on Archlinux + # so we use --enable-modules + + # wrapper on ninja + make -j8 make install - echo "$VERSION $TARGETS" > ${QEMU_INSTALL}/.build + echo "$QEMU_VERSION $QEMU_TARGET" > "${QEMU_INSTALL}/.build" } function assert_defined(){ - local VALUE=${1} - : "${VALUE?"${1} needs to be defined"}" + if [[ -z "${!1}" ]]; then + >&2 echo "Variable '${1}' must be defined" + exit 1 + fi } -function integrate() { - cd "${PROJECT_FOLDER}" - case "${OS}" in - "Windows_NT") CMAKE_BUILD_ARGS="--config Debug --target ALL_BUILD" - CMAKE_TEST_FILES="${BUILD_DIR}/test/Debug/*_test.exe" - DEMO=${BUILD_DIR}/Debug/list_cpu_features.exe - ;; - *) CMAKE_BUILD_ARGS="--target all" - CMAKE_TEST_FILES="${BUILD_DIR}/test/*_test" - DEMO=${BUILD_DIR}/list_cpu_features - ;; - esac - - # Generating CMake configuration - cmake -H. -B"${BUILD_DIR}" ${DEFAULT_CMAKE_ARGS} "${CMAKE_ADDITIONAL_ARGS[@]}" -G"${CMAKE_GENERATOR:-Unix Makefiles}" - - # Building - cmake --build "${BUILD_DIR}" ${CMAKE_BUILD_ARGS} - - # Running tests if needed - if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then - return - fi - RUN_CMD="" - if [[ -n "${QEMU_ARCH}" ]]; then - installqemuifneeded - RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[@]}" - fi - for test_binary in ${CMAKE_TEST_FILES}; do - ${RUN_CMD} ${test_binary} - done - ${RUN_CMD} ${DEMO} +function clean_build() { + # Cleanup previous build + rm -rf "${BUILD_DIR}" + mkdir -p "${BUILD_DIR}" } function expand_linaro_config() { - assert_defined TARGET - local LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11 + #ref: https://releases.linaro.org/components/toolchain/binaries/ + local -r LINARO_VERSION=7.5-2019.12 + local -r LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/${LINARO_VERSION} - local GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}.tar.xz - local GCC_RELATIVE_FOLDER="gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}" - unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}" + local -r GCC_VERSION=7.5.0-2019.12 + local -r GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-${GCC_VERSION}-x86_64_${TARGET}.tar.xz + local -r GCC_RELATIVE_DIR="gcc-linaro-${GCC_VERSION}-x86_64_${TARGET}" + unpack "${GCC_URL}" "${GCC_RELATIVE_DIR}" - local SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-2.25-2017.11-${TARGET}.tar.xz - local SYSROOT_RELATIVE_FOLDER=sysroot-glibc-linaro-2.25-2017.11-${TARGET} - unpackifnotexists "${SYSROOT_URL}" "${SYSROOT_RELATIVE_FOLDER}" + local -r SYSROOT_VERSION=2.25-2019.12 + local -r SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-${SYSROOT_VERSION}-${TARGET}.tar.xz + local -r SYSROOT_RELATIVE_DIR=sysroot-glibc-linaro-${SYSROOT_VERSION}-${TARGET} + unpack "${SYSROOT_URL}" "${SYSROOT_RELATIVE_DIR}" - local SYSROOT_FOLDER=${ARCHIVE_FOLDER}/${SYSROOT_RELATIVE_FOLDER} - local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER} + local -r SYSROOT_DIR=${ARCHIVE_DIR}/${SYSROOT_RELATIVE_DIR} + local -r STAGING_DIR=${ARCHIVE_DIR}/${SYSROOT_RELATIVE_DIR}-stage + local -r GCC_DIR=${ARCHIVE_DIR}/${GCC_RELATIVE_DIR} - CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) - CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) + # Write a Toolchain file + # note: This is manadatory to use a file in order to have the CMake variable + # 'CMAKE_CROSSCOMPILING' set to TRUE. + # ref: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux + cat >"$TOOLCHAIN_FILE" <&2 echo 'unknown mips platform' + exit 1 ;; esac + local -r SYSROOT_DIR=${GCC_DIR}/sysroot + local -r STAGING_DIR=${SYSROOT_DIR}-stage - CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH=${GCC_FOLDER}) - CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) - CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) - CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=mips-mti-linux-gnu-gcc) - CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=mips-mti-linux-gnu-g++) - CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER_ARG1="${MIPS_FLAGS}") - CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER_ARG1="${MIPS_FLAGS}") + # Write a Toolchain file + # note: This is manadatory to use a file in order to have the CMake variable + # 'CMAKE_CROSSCOMPILING' set to TRUE. + # ref: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux + cat >"${TOOLCHAIN_FILE}" <&2 echo "QEMU is disabled for ${TARGET}" + return + fi + install_qemu + RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[*]}" + + cd "${BUILD_DIR}" || exit 2 + set -x + for test_binary in "${BUILD_DIR}"/list_cpu_feature* ; do + ${RUN_CMD} "${test_binary}" + done + set +x +} + +function usage() { + local -r NAME=$(basename "$0") + echo -e "$NAME - Build using a cross toolchain. + +SYNOPSIS +\t$NAME [-h|--help] [toolchain|build|qemu|test|all] + +DESCRIPTION +\tCross compile using a cross toolchain. + +\tYou MUST define the following variables before running this script: +\t* TARGET: +\t\tx86_64 +\t\taarch64-linux-gnu aarch64_be-linux-gnu +\t\tarm-linux-gnueabihf armv8l-linux-gnueabihf arm-linux-gnueabi +\t\tarmeb-linux-gnueabihf armeb-linux-gnueabi +\t\tmips32 mips32el +\t\tmips64 mips64el + +OPTIONS +\t-h --help: show this help text +\ttoolchain: download, unpack toolchain and generate CMake toolchain file +\tbuild: toolchain + build the project using the toolchain file (note: remove previous build dir) +\tqemu: download, unpack and build qemu +\ttest: qemu + run all executable using qemu (note: don't build !) +\tall: build + test (default) + +EXAMPLES +* Using export: +export TARGET=aarch64-linux-gnu +$0 + +* One-liner: +TARGET=aarch64-linux-gnu $0" +} + +# Main +function main() { + case ${1} in + -h | --help) + usage; exit ;; + esac + assert_defined TARGET - BUILD_DIR="${PROJECT_FOLDER}/cmake_build/${TARGET}" - mkdir -p "${BUILD_DIR}" + declare -r PROJECT_DIR="$(cd -P -- "$(dirname -- "$0")/.." && pwd -P)" + declare -r ARCHIVE_DIR="${PROJECT_DIR}/build_cross/archives" + declare -r BUILD_DIR="${PROJECT_DIR}/build_cross/${TARGET}" + declare -r TOOLCHAIN_FILE=${ARCHIVE_DIR}/toolchain_${TARGET}.cmake - declare -a CONFIG_NAMES=() - declare -a QEMU_ARGS=() + echo "Target: '${TARGET}'" + + echo "Project dir: '${PROJECT_DIR}'" + echo "Archive dir: '${ARCHIVE_DIR}'" + echo "Build dir: '${BUILD_DIR}'" + echo "toolchain file: '${TOOLCHAIN_FILE}'" + + declare -a CMAKE_DEFAULT_ARGS=( -G ${CMAKE_GENERATOR:-"Ninja"} ) declare -a CMAKE_ADDITIONAL_ARGS=() - case ${TOOLCHAIN} in - LINARO) expand_linaro_config ;; - CODESCAPE) expand_codescape_config ;; - NATIVE) QEMU_ARCH="" ;; - *) echo "Unknown toolchain '${TOOLCHAIN}'..."; exit 1;; + declare -a QEMU_ARGS=() + case ${TARGET} in + x86_64) + declare -r QEMU_ARCH=x86_64 ;; + arm-linux-gnueabihf | armv8l-linux-gnueabihf | arm-linux-gnueabi) + expand_linaro_config + declare -r QEMU_ARCH=arm ;; + armeb-linux-gnueabihf | armeb-linux-gnueabi) + expand_linaro_config + declare -r QEMU_ARCH=DISABLED ;; + aarch64-linux-gnu) + expand_linaro_config + declare -r QEMU_ARCH=aarch64 ;; + aarch64_be-linux-gnu) + expand_linaro_config + declare -r QEMU_ARCH=DISABLED ;; + mips32) + expand_codescape_config + declare -r QEMU_ARCH=mips ;; + mips32el) + expand_codescape_config + declare -r QEMU_ARCH=mipsel ;; + mips64) + expand_codescape_config + declare -r QEMU_ARCH=mips64 ;; + mips64el) + expand_codescape_config + declare -r QEMU_ARCH=mips64el ;; + *) + >&2 echo "Unknown TARGET '${TARGET}'..." + exit 1 ;; + esac + declare -r QEMU_INSTALL=${ARCHIVE_DIR}/qemu-${QEMU_ARCH} + + case ${1} in + toolchain) + exit ;; + build) + build ;; + qemu) + install_qemu ;; + test) + run_test ;; + *) + build + run_test ;; esac - integrate } -if [ "${CONTINUOUS_INTEGRATION}" = "true" ]; then - QEMU_ARCHES=${QEMU_ARCH} - expand_environment_and_integrate -fi +main "${1:-all}" diff --git a/scripts/test_integration.sh b/scripts/test_integration.sh index d1c61b0..0947e36 100755 --- a/scripts/test_integration.sh +++ b/scripts/test_integration.sh @@ -1,84 +1,58 @@ #!/usr/bin/env bash -source "$(dirname -- "$0")"/run_integration.sh - # Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems function set_aarch64-linux-gnu() { - TOOLCHAIN=LINARO - TARGET=aarch64-linux-gnu - QEMU_ARCH=aarch64 + export TARGET=aarch64-linux-gnu } # Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems function set_arm-linux-gnueabihf() { - TOOLCHAIN=LINARO - TARGET=arm-linux-gnueabihf - QEMU_ARCH=arm + export TARGET=arm-linux-gnueabihf } # Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems function set_armv8l-linux-gnueabihf() { - TOOLCHAIN=LINARO - TARGET=armv8l-linux-gnueabihf - QEMU_ARCH=arm + export TARGET=armv8l-linux-gnueabihf } # Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems function set_arm-linux-gnueabi() { - TOOLCHAIN=LINARO - TARGET=arm-linux-gnueabi - QEMU_ARCH=arm + export TARGET=arm-linux-gnueabi } # Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems function set_aarch64_be-linux-gnu() { - TOOLCHAIN=LINARO - TARGET=aarch64_be-linux-gnu - QEMU_ARCH=DISABLED + export TARGET=aarch64_be-linux-gnu } # Toolchains for big-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems function set_armeb-linux-gnueabihf() { - TOOLCHAIN=LINARO - TARGET=armeb-linux-gnueabihf - QEMU_ARCH=DISABLED + export TARGET=armeb-linux-gnueabihf } # Toolchains for big-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems function set_armeb-linux-gnueabi() { - TOOLCHAIN=LINARO - TARGET=armeb-linux-gnueabi - QEMU_ARCH=DISABLED + export TARGET=armeb-linux-gnueabi } function set_mips32() { - TOOLCHAIN=CODESCAPE - TARGET=mips32 - QEMU_ARCH=mips + export TARGET=mips32 } function set_mips32el() { - TOOLCHAIN=CODESCAPE - TARGET=mips32el - QEMU_ARCH=mipsel + export TARGET=mips32el } function set_mips64() { - TOOLCHAIN=CODESCAPE - TARGET=mips64 - QEMU_ARCH=mips64 + export TARGET=mips64 } function set_mips64el() { - TOOLCHAIN=CODESCAPE - TARGET=mips64el - QEMU_ARCH=mips64el + export TARGET=mips64el } -function set_native() { - TOOLCHAIN=NATIVE - TARGET=native - QEMU_ARCH="" +function set_x86_64() { + export TARGET=x86_64 } ENVIRONMENTS=" @@ -93,14 +67,13 @@ ENVIRONMENTS=" set_mips32el set_mips64 set_mips64el - set_native + set_x86_64 " set -e -CMAKE_GENERATOR="Ninja" - for SET_ENVIRONMENT in ${ENVIRONMENTS}; do + echo "testing ${SET_ENVIRONMENT}" ${SET_ENVIRONMENT} - expand_environment_and_integrate + ./"$(dirname -- "$0")"/run_integration.sh done