1#!/usr/bin/env bash 2 3readonly SCRIPT_FOLDER=$(cd -P -- "$(dirname -- "$0")" && pwd -P) 4readonly PROJECT_FOLDER="${SCRIPT_FOLDER}/.." 5readonly ARCHIVE_FOLDER=~/cpu_features_archives 6readonly QEMU_INSTALL=${ARCHIVE_FOLDER}/qemu 7readonly DEFAULT_CMAKE_ARGS=" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON" 8 9function extract() { 10 case $1 in 11 *.tar.bz2) tar xjf "$1" ;; 12 *.tar.xz) tar xJf "$1" ;; 13 *.tar.gz) tar xzf "$1" ;; 14 *) 15 echo "don't know how to extract '$1'..." 16 exit 1 17 esac 18} 19 20function unpackifnotexists() { 21 mkdir -p "${ARCHIVE_FOLDER}" 22 cd "${ARCHIVE_FOLDER}" || exit 23 local URL=$1 24 local RELATIVE_FOLDER=$2 25 local DESTINATION="${ARCHIVE_FOLDER}/${RELATIVE_FOLDER}" 26 if [[ ! -d "${DESTINATION}" ]] ; then 27 local ARCHIVE_NAME=$(echo ${URL} | sed 's/.*\///') 28 test -f "${ARCHIVE_NAME}" || wget -q "${URL}" 29 extract "${ARCHIVE_NAME}" 30 rm -f "${ARCHIVE_NAME}" 31 fi 32} 33 34function installqemuifneeded() { 35 local VERSION=${QEMU_VERSION:=2.11.1} 36 local ARCHES=${QEMU_ARCHES:=arm aarch64 i386 x86_64 mips mipsel mips64 mips64el} 37 local TARGETS=${QEMU_TARGETS:=$(echo "$ARCHES" | sed 's#$# #;s#\([^ ]*\) #\1-linux-user #g')} 38 39 if echo "${VERSION} ${TARGETS}" | cmp --silent ${QEMU_INSTALL}/.build -; then 40 echo "qemu ${VERSION} up to date!" 41 return 0 42 fi 43 44 echo "VERSION: ${VERSION}" 45 echo "TARGETS: ${TARGETS}" 46 47 rm -rf ${QEMU_INSTALL} 48 49 # Checking for a tarball before downloading makes testing easier :-) 50 local QEMU_URL="http://wiki.qemu-project.org/download/qemu-${VERSION}.tar.xz" 51 local QEMU_FOLDER="qemu-${VERSION}" 52 unpackifnotexists ${QEMU_URL} ${QEMU_FOLDER} 53 cd ${QEMU_FOLDER} || exit 54 55 ./configure \ 56 --prefix="${QEMU_INSTALL}" \ 57 --target-list="${TARGETS}" \ 58 --disable-docs \ 59 --disable-sdl \ 60 --disable-gtk \ 61 --disable-gnutls \ 62 --disable-gcrypt \ 63 --disable-nettle \ 64 --disable-curses \ 65 --static 66 67 make -j4 68 make install 69 70 echo "$VERSION $TARGETS" > ${QEMU_INSTALL}/.build 71} 72 73function assert_defined(){ 74 local VALUE=${1} 75 : "${VALUE?"${1} needs to be defined"}" 76} 77 78function integrate() { 79 cd "${PROJECT_FOLDER}" 80 case "${OS}" in 81 "Windows_NT") CMAKE_BUILD_ARGS="--config Debug --target ALL_BUILD" 82 CMAKE_TEST_FILES="${BUILD_DIR}/test/Debug/*_test.exe" 83 DEMO=${BUILD_DIR}/Debug/list_cpu_features.exe 84 ;; 85 *) CMAKE_BUILD_ARGS="--target all" 86 CMAKE_TEST_FILES="${BUILD_DIR}/test/*_test" 87 DEMO=${BUILD_DIR}/list_cpu_features 88 ;; 89 esac 90 91 # Generating CMake configuration 92 cmake -H. -B"${BUILD_DIR}" ${DEFAULT_CMAKE_ARGS} "${CMAKE_ADDITIONAL_ARGS[@]}" -G"${CMAKE_GENERATOR:-Unix Makefiles}" 93 94 # Building 95 cmake --build "${BUILD_DIR}" ${CMAKE_BUILD_ARGS} 96 97 # Running tests if needed 98 if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then 99 return 100 fi 101 RUN_CMD="" 102 if [[ -n "${QEMU_ARCH}" ]]; then 103 installqemuifneeded 104 RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[@]}" 105 fi 106 for test_binary in ${CMAKE_TEST_FILES}; do 107 ${RUN_CMD} ${test_binary} 108 done 109 ${RUN_CMD} ${DEMO} 110} 111 112function expand_linaro_config() { 113 assert_defined TARGET 114 local LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11 115 116 local GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}.tar.xz 117 local GCC_RELATIVE_FOLDER="gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}" 118 unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}" 119 120 local SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-2.25-2017.11-${TARGET}.tar.xz 121 local SYSROOT_RELATIVE_FOLDER=sysroot-glibc-linaro-2.25-2017.11-${TARGET} 122 unpackifnotexists "${SYSROOT_URL}" "${SYSROOT_RELATIVE_FOLDER}" 123 124 local SYSROOT_FOLDER=${ARCHIVE_FOLDER}/${SYSROOT_RELATIVE_FOLDER} 125 local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER} 126 127 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) 128 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) 129 130 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSROOT=${SYSROOT_FOLDER}) 131 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=${GCC_FOLDER}/bin/${TARGET}-gcc) 132 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=${GCC_FOLDER}/bin/${TARGET}-g++) 133 134 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER) 135 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY) 136 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY) 137 138 QEMU_ARGS+=(-L ${SYSROOT_FOLDER}) 139 QEMU_ARGS+=(-E LD_LIBRARY_PATH=/lib) 140} 141 142function expand_codescape_config() { 143 assert_defined TARGET 144 local DATE=2017.10-08 145 local CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz 146 local GCC_URL=${CODESCAPE_URL} 147 local GCC_RELATIVE_FOLDER="mips-mti-linux-gnu/${DATE}" 148 unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}" 149 150 local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER} 151 local MIPS_FLAGS="" 152 local LIBC_FOLDER_SUFFIX="" 153 local FLAVOUR="" 154 case "${TARGET}" in 155 "mips32") MIPS_FLAGS="-EB -mabi=32"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;; 156 "mips32el") MIPS_FLAGS="-EL -mabi=32"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;; 157 "mips64") MIPS_FLAGS="-EB -mabi=64"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;; 158 "mips64el") MIPS_FLAGS="-EL -mabi=64"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;; 159 *) echo 'unknown mips platform'; exit 1;; 160 esac 161 162 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH=${GCC_FOLDER}) 163 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) 164 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) 165 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=mips-mti-linux-gnu-gcc) 166 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=mips-mti-linux-gnu-g++) 167 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER_ARG1="${MIPS_FLAGS}") 168 CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER_ARG1="${MIPS_FLAGS}") 169 170 local SYSROOT_FOLDER=${GCC_FOLDER}/sysroot/${FLAVOUR} 171 172 # Keeping only the sysroot of interest to save on travis cache. 173 if [[ "${CONTINUOUS_INTEGRATION}" = "true" ]]; then 174 for folder in ${GCC_FOLDER}/sysroot/*; do 175 if [[ "${folder}" != "${SYSROOT_FOLDER}" ]]; then 176 rm -rf ${folder} 177 fi 178 done 179 fi 180 181 local LIBC_FOLDER=${GCC_FOLDER}/mips-mti-linux-gnu/lib/${FLAVOUR}/${LIBC_FOLDER_SUFFIX} 182 QEMU_ARGS+=(-L ${SYSROOT_FOLDER}) 183 QEMU_ARGS+=(-E LD_PRELOAD=${LIBC_FOLDER}/libstdc++.so.6:${LIBC_FOLDER}/libgcc_s.so.1) 184} 185 186function expand_environment_and_integrate() { 187 assert_defined PROJECT_FOLDER 188 assert_defined TARGET 189 190 BUILD_DIR="${PROJECT_FOLDER}/cmake_build/${TARGET}" 191 mkdir -p "${BUILD_DIR}" 192 193 declare -a CONFIG_NAMES=() 194 declare -a QEMU_ARGS=() 195 declare -a CMAKE_ADDITIONAL_ARGS=() 196 197 case ${TOOLCHAIN} in 198 LINARO) expand_linaro_config ;; 199 CODESCAPE) expand_codescape_config ;; 200 NATIVE) QEMU_ARCH="" ;; 201 *) echo "Unknown toolchain '${TOOLCHAIN}'..."; exit 1;; 202 esac 203 integrate 204} 205 206if [ "${CONTINUOUS_INTEGRATION}" = "true" ]; then 207 QEMU_ARCHES=${QEMU_ARCH} 208 expand_environment_and_integrate 209fi 210