#!/bin/bash -e # # Kangaroo Punch Toolchains # Copyright 2023-2024 Scott Duensing # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # TC_G_SCRIPT_PATH="${BASH_SOURCE}" while [ -L "${TC_G_SCRIPT_PATH}" ]; do TC_G_SCRIPT_DIR="$(cd -P "$(dirname "${TC_G_SCRIPT_PATH}")" >/dev/null 2>&1 && pwd)" TC_G_SCRIPT_PATH="$(readlink "${TC_G_SCRIPT_PATH}")" [[ ${TC_G_SCRIPT_PATH} != /* ]] && TC_G_SCRIPT_PATH="${TC_G_SCRIPT_DIR}/${TC_G_SCRIPT_PATH}" done TC_G_SCRIPT_PATH="$(readlink -f "${TC_G_SCRIPT_PATH}")" TC_G_SCRIPT_DIR="$(cd -P "$(dirname -- "${TC_G_SCRIPT_PATH}")" >/dev/null 2>&1 && pwd)" TC_G_SCRIPT=$(basename ${TC_G_SCRIPT_PATH}) TC_G_PIURL=https://github.com/tttapa/docker-arm-cross-toolchain/releases/latest/download/x-tools- TC_G_PI64=https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2023-12-11/2023-12-11-raspios-bookworm-arm64-lite.img.xz TC_G_PI32=https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2023-12-11/2023-12-11-raspios-bookworm-armhf-lite.img.xz function buildMacOSXToolchain() { local SDK=$1 local XCODE=$2 local PLATFORM=$3 local CLANG= local RTPATH= local CROSSTOOLS="${TC_G_SCRIPT_DIR}/x-tools/${PLATFORM}" mkdir -p work if [[ ! -d work/osxcross ]]; then git clone https://github.com/tpoechtrager/osxcross.git work/osxcross sudo work/osxcross/tools/get_dependencies.sh fi if [[ ! -f x-tools/${PLATFORM}/toolchain.cmake ]]; then pushd work/osxcross # Have we built Apple's clang? if [[ ! -d "${TC_G_SCRIPT_DIR}/clang" ]]; then UNATTENDED=1 INSTALLPREFIX=${TC_G_SCRIPT_DIR}/clang ./build_apple_clang.sh pushd build/clang*/build_stage2 make install popd fi # Use our fresh new clang. source <("${CROSSTOOLS}/bin/osxcross-conf" 2>/dev/null) export PATH="${TC_G_SCRIPT_DIR}/clang/bin:${CROSSTOOLS}/bin:${PATH}" export CC="${TC_G_SCRIPT_DIR}/clang/bin/clang" export CXX="${TC_G_SCRIPT_DIR}/clang/bin/clang++" # Do we have an existing SDK tarball? if [[ ! -f "${TC_G_SCRIPT_DIR}/${SDK}" ]]; then # Nope. Build tarball and keep for later. ./tools/gen_sdk_package_pbzx.sh "${TC_G_SCRIPT_DIR}/${XCODE}" mv -f MacOSX* "${TC_G_SCRIPT_DIR}/." fi # Put tarball in place. cp -f "${TC_G_SCRIPT_DIR}/${SDK}" tarballs/. # Build SDK. UNATTENDED=1 TARGET_DIR="${CROSSTOOLS}" ./build.sh # Fix fubar in osxcross. [[ -d target ]] && rm -rf target ln -sf "${CROSSTOOLS}" target :< build_gcc-fixed.sh chmod +x build_gcc-fixed.sh fi TARGET_DIR="${CROSSTOOLS}" ./build_gcc-fixed.sh NO_GCC # Build compiler runtime. #***TODO*** This fails to find for x86. RTPATH="${TC_G_SCRIPT_DIR}/clang/lib/clang" CLANG=$(ls -1 "${RTPATH}" | grep -F . | sort | tail -n1) if [[ "${CLANG}" == "" ]]; then CLANG=$(ls -1 "${RTPATH}" | sort | tail -n1) fi RTPATH="${RTPATH}/${CLANG}/lib/darwin" if [[ -d "${RTPATH}" ]]; then rm -rf "${RTPATH}" fi CXX_FLAGS="-std=c++17" ENABLE_COMPILER_RT_INSTALL=1 ./build_compiler_rt.sh if [[ -d "${RTPATH}" ]]; then mv -f "${RTPATH}" "${CROSSTOOLS}/." echo "RTPATH=\"${RTPATH}\"" > ${CROSSTOOLS}/rtpath.inc fi # Tidy up for next build. ./cleanup.sh popd fi } function build_pi_sysroot() { local BITS=$1 local OS= local IMAGE= local START= local SYSROOT=../x-tools/sysroot-pi${BITS} mkdir -p work pushd work if [[ ! -f sysroot-relativelinks.py ]]; then wget https://raw.githubusercontent.com/riscv/riscv-poky/master/scripts/sysroot-relativelinks.py fi if [[ "${BITS}" == "64" ]]; then OS=${TC_G_PI64} else OS=${TC_G_PI32} fi IMAGE=$(basename ${OS}) if [[ ! -f $(basename ${OS} .xz) ]]; then wget ${OS} unxz ${IMAGE} fi IMAGE=$(basename ${IMAGE} .xz) START=$(fdisk -l ${IMAGE} | grep Linux | awk '{ print $2 }') START=$(( 512 * START )) mkdir -p ${SYSROOT} mkdir -p mnt sudo mount -t ext4 -o loop,offset=${START} ${IMAGE} mnt rsync -avz mnt/* ${SYSROOT} || true #rsync -avz mnt/lib ${SYSROOT} #rsync -avz mnt/usr/include ${SYSROOT}/usr #rsync -avz mnt/usr/lib ${SYSROOT}/usr sudo umount mnt python3 ./sysroot-relativelinks.py ${SYSROOT} if [[ "${BITS}" == "64" ]]; then cp -f $(which qemu-aarch64-static) ${SYSROOT}/usr/bin/. else cp -f $(which qemu-arm-static) ${SYSROOT}/usr/bin/. fi popd } function install_x86_64_linux() { # Required tools for Linux x86_64. These should always be installed. sudo apt-get install -y \ autoconf \ binutils \ bison \ build-essential \ clang \ cmake \ cmake-curses-gui \ curl \ flex \ git \ git-lfs \ liblzma-dev \ libtool \ nasm \ texinfo \ unzip \ zlib1g-dev } function install_x86_linux() { # x86 Linux support. sudo dpkg --add-architecture i386 sudo apt-get install -y \ gcc-i686-linux-gnu \ g++-i686-linux-gnu } function install_x86_64_windows() { # x86 and x86_64 Windows. sudo apt-get install -y mingw-w64 } function install_x86_windows() { # x86 Windows. install_x86_64_windows } function install_aarch64_pi() { # Raspberry Pi, aarch64. # wget -O- ${TC_G_PIURL}aarch64-rpi3-linux-gnu.tar.xz | tar xJ build_pi_sysroot 64 } function install_armv6_pi() { # Raspberry Pi, armv6. wget -O- ${TC_G_PIURL}armv6-rpi-linux-gnueabihf.tar.xz | tar xJ build_pi_sysroot 32 } function install_armv8_pi() { # Raspberry Pi, armv8. wget -O- ${TC_G_PIURL}armv8-rpi3-linux-gnueabihf.tar.xz | tar xJ build_pi_sysroot 32 } function install_x86_64_macos() { # MacOS x86_64. #***TODO*** https://stackoverflow.com/questions/67712376/after-updating-gcc-clang-cant-find-libstdc-anymore buildMacOSXToolchain MacOSX10.13.sdk.tar.xz Xcode_9.4.1.xip x86_64-macos-apple } function install_x86_macos() { # MacOS x86. install_x86_64_macos } function install_aarch64_macos() { # MacOS aarch64. #***TODO*** https://stackoverflow.com/questions/67712376/after-updating-gcc-clang-cant-find-libstdc-anymore buildMacOSXToolchain MacOSX13.3.sdk.tar.xz Xcode_14.3.1.xip aarch64-macos-apple } function install_x86_dos() { # DJGPP for DOS. export DJGPP_PREFIX=$(pwd)/x-tools/djgpp mkdir -p work if [[ ! -d work/build-djgpp ]]; then git clone https://github.com/andrewwutw/build-djgpp.git work/build-djgpp fi if [[ ! -f x-tools/djgpp/setenv ]]; then pushd work/build-djgpp ./build-djgpp.sh 12.2.0 popd fi } function use_toolchain() { local ARCH=$1 local PLAT=$2 case "${PLAT}" in dos) case "${ARCH}" in x86) TRIPLE="i586-pc-msdosdjgpp" ;; esac echo "source ${TC_G_SCRIPT_DIR}/x-tools/djgpp/setenv" #echo "export PATH=\"${TC_G_SCRIPT_DIR}/x-tools/djgpp/i586-pc-msdosdjgpp/bin:${TC_G_SCRIPT_DIR}/x-tools/djgpp/bin:${TC_G_SCRIPT_DIR}/x-tools/djgpp/libexec/gcc/i586-pc-msdosdjgpp/12.2.0:${PATH}\"" #echo "export GCC_EXE_PREFIX=\"${TC_G_SCRIPT_DIR}/x-tools/djgpp/lib/gcc\"" #echo "export DJDIR=\"${TC_G_SCRIPT_DIR}/x-tools/djgpp/i586-pc-msdosdjgpp\"" CROSS_OS="dos" CC="gcc" CXX="g++" RANLIB="ranlib" SUFFIX=".exe" ;; linux) case "${ARCH}" in x86) TRIPLE="i686-linux-gnu" ;; x86_64) TRIPLE="x86_64-linux-gnu" ;; esac CROSS_OS="linux" CC="${TRIPLE}-gcc" CXX="${TRIPLE}-g++" RANLIB="${TRIPLE}-ranlib" ;; macos) case "${ARCH}" in aarch64) TRIPLE="aarch64-apple-darwin22.4" OSXCROSS_LOCATION=${TC_G_SCRIPT_DIR}/x-tools/aarch64-macos-apple ;; x86) TRIPLE="i386-apple-darwin17" OSXCROSS_LOCATION=${TC_G_SCRIPT_DIR}/x-tools/x86_64-macos-apple ;; x86_64) TRIPLE="x86_64-apple-darwin17" OSXCROSS_LOCATION=${TC_G_SCRIPT_DIR}/x-tools/x86_64-macos-apple ;; esac CROSS_OS="darwin" CC="${OSXCROSS_LOCATION}/bin/${TRIPLE}-clang" CXX="${OSXCROSS_LOCATION}/bin/${TRIPLE}-clang++" RANLIB="${OSXCROSS_LOCATION}/bin/${TRIPLE}-ranlib" AR="${OSXCROSS_LOCATION}/bin/${TRIPLE}-ar" "${OSXCROSS_LOCATION}/bin/osxcross-conf" 2>/dev/null echo "export AR=\"${AR}\"" echo "export OSXCROSS_LOCATION=\"${OSXCROSS_LOCATION}\"" echo "export LDFLAGS=\"-fuse-ld=${OSXCROSS_LOCATION}/bin/${TRIPLE}-ld\"" echo "export PATH=\"${OSXCROSS_LOCATION}/bin:${PATH}\"" echo "export OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1" ;; pi) case "${ARCH}" in aarch64) TRIPLE="aarch64-rpi3-linux-gnu" echo "export SYSROOT=${TC_G_SCRIPT_DIR}/x-tools/sysroot-pi64" ;; armv6) TRIPLE="armv6-rpi-linux-gnueabihf" echo "export SYSROOT=${TC_G_SCRIPT_DIR}/x-tools/sysroot-pi64" ;; armv8) TRIPLE="armv8-rpi3-linux-gnueabihf" echo "export SYSROOT=${TC_G_SCRIPT_DIR}/x-tools/sysroot-pi64" ;; esac CROSS_OS="linux" CC="${TRIPLE}-gcc" CXX="${TRIPLE}-g++" RANLIB="${TRIPLE}-ranlib" ;; windows) case "${ARCH}" in x86) TRIPLE="i686-w64-mingw32" ;; x86_64) TRIPLE="x86_64-w64-mingw32" ;; esac CC="${TRIPLE}-gcc-posix" CXX="${TRIPLE}-g++-posix" RANLIB="${TRIPLE}-ranlib" SUFFIX=".exe" CROSS_OS="mingw32" ;; esac echo "export TOOLCHAIN_FILE=\"${TC_G_SCRIPT_DIR}/cmake/${TRIPLE}.cmake\"" echo "export CC=\"${CC}\"" echo "export CXX=\"${CXX}\"" echo "export RANLIB=\"${RANLIB}\"" echo "export SUFFIX=\"${SUFFIX}\"" echo "export CROSS_OS=\"${CROSS_OS}\"" echo "export TRIPLE=\"${TRIPLE}\"" } MODE=$1 ARCH=$2 PLAT=$3 HELP=1 COLS=2 ROWS=11 row=0 declare -A PLATFORMS=() # List of ARCHs List of PLATs PLATFORMS[0]="x86_64"; PLATFORMS[1]="linux" PLATFORMS[2]="x86"; PLATFORMS[3]="linux" PLATFORMS[4]="x86_64"; PLATFORMS[5]="windows" PLATFORMS[6]="x86"; PLATFORMS[7]="windows" PLATFORMS[8]="aarch64"; PLATFORMS[9]="pi" PLATFORMS[10]="armv6"; PLATFORMS[11]="pi" PLATFORMS[12]="armv8"; PLATFORMS[13]="pi" PLATFORMS[14]="x86_64"; PLATFORMS[15]="macos" PLATFORMS[16]="x86"; PLATFORMS[17]="macos" PLATFORMS[18]="aarch64"; PLATFORMS[19]="macos" PLATFORMS[20]="x86"; PLATFORMS[21]="dos" if [[ "${MODE}" == "install" ]]; then # We need some more packages for Pi work. if [[ "${PLAT}" == "pi" ]]; then sudo apt-get -y install qemu-user-static fi # Install all toolchains. if [[ "${ARCH}" == "all" && "${PLAT}" == "all" ]]; then HELP=0 for (( row=0; row