#! /bin/bash ############################################################################## # Building gcc-12.2.0 aarch64 cross-compiler for Raspberry Pi5 # based on Slackware script for gcc-12.2.0 aarch64 cross-compiler for Raspberry Pi ############################################################################## # Installation directory - edit INSTALL_PATH as required INSTALL_PATH=${HOME}/cross-gcc-rpi5 # Required build packages-versions [* newer versions may exist] BINUTILS_VERSION=binutils-2.40 CLOOG_VERSION=cloog-0.18.1 GCC_VERSION=gcc-12.2.0 GLIBC_VERSION=glibc-2.36 GMP_VERSION=gmp-6.2.1 ISL_VERSION=isl-0.24 MPFR_VERSION=mpfr-4.2.0 MPC_VERSION=mpc-1.3.1 ARCH=armv8-a+fp+simd # RPi GitHub Linux source - working branch [e.g. rpi-4.19.y | rpi-5.15.y | rpi-5.19.y ] DEV_BRANCH=rpi-6.6.y # Halt build process on error [with output] set -euo pipefail IFS=$'\n\t' # Uncomment for additional error output when testing/debugging #trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG #trap 'echo "exit $? due to $previous_command"' EXIT # Build variables PRGNAM=cross-compiler-aarch64 ARCH_TARGET=aarch64-linux LINUX_ARCH=arm64 QUADLET=aarch64-unknown-linux-gnu # aarch64-arm-none-eabi LINUX_FLAVOUR=linux-rpi RPI_GITURL_LINUX=https://github.com/raspberrypi BUILD_LANGUAGES="--enable-languages=c,c++" # --enable-languages=all,ada,c,c++,fortran,go,jit,lto,objc,obj-c++ ALT_CONFIG_OPTIONS="--disable-multilib" # --disable-threads --disable-shared --disable-multiarch TEST_CONFIG_OPTIONS="--with-arch=armv8-a --with-tune=cortex-a72 --with-fpu=vfpv3-d16 --with-float=hard" # RPI4_CONFIG_OPTIONS="--prefix=$INSTALL_PATH --target=arm-linux-gnueabihf --enable-languages=c,c++ --with-arch=${ARCH} --with-fpu=vfp --with-float=hard --disable-multilib" # PARALLEL_JOBS=-j4 # https://www.gnu.org/software/make/manual/html_node/Parallel.html BUILDDIR=($PWD) CWD="$BUILDDIR"/build-cc # Define CONFIG_OPTIONS for build CONFIG_OPTIONS=$ALT_CONFIG_OPTIONS # Uncomment to log EVERYTHING during build process [** WARNING! HUGE log filesize! **] #LOGFLE=${PRGNAM}_build_$(date +"%F").log #exec 1> >(logger -s -t $(basename $0)) 2>&1 > $LOGFLE # Output aesthetics echo echo " ############################################" echo " ## $PRGNAM " echo " ## Build: $GCC_VERSION Kernel ${DEV_BRANCH} " echo " ## Timestamp: $(date '+%F %T') " echo " ############################################" echo echo "Starting $PRGNAM build ..." mkdir -p "$CWD" cd "$CWD" || { echo "Cannot create ${CWD}"; exit 1; } # INSTALL_PATH needs to be at the front of $PATH # Command: export PATH=/tmp/.gcc-cross/bin:$PATH echo "Checking $ARCH_TARGET $INSTALL_PATH/bin \$PATH ..." if [[ ! "$PATH" =~ $INSTALL_PATH ]]; then export PATH=/"${INSTALL_PATH}"/bin:$PATH # echo -e $INSTALL_PATH/bin:$(cat $PATH) > $PATH || exit 1 else echo "Found $INSTALL_PATH\/bin in \$PATH : OK! ... " fi # Prerequisite packages BISON_REQ=$(which bison) FLEX_REQ=$(which flex) GAWK_REQ=$(which gawk) GIT_REQ=$(which git) # Check prerequisites are installed, or exit if [ ! -e "$BISON_REQ" ]; then echo "ERROR: bison not found!" echo "Install bison before you run this script!" exit 1 elif [ ! -e "$FLEX_REQ" ]; then echo "ERROR: flex not found!" echo "Install flex before you run this script!" exit 1 elif [ ! -e "$GAWK_REQ" ]; then echo "ERROR: gawk not found!" echo "Install gawk before you run this script!" exit 1 elif [ ! -e "$GIT_REQ" ]; then echo "ERROR: git not found!" echo "Install git before you run this script!" exit 1 else echo "Prerequisite packages are installed ..." fi # Download RPi kernel source ** this may take a while ** cd "$CWD" echo "Checking kernel $DEV_BRANCH source ..." if [ ! -e $LINUX_FLAVOUR/Makefile ]; then echo "Downloading kernel $DEV_BRANCH source ..." git clone --depth=1 $RPI_GITURL_LINUX/linux.git --branch $DEV_BRANCH $LINUX_FLAVOUR fi cd $LINUX_FLAVOUR echo "Checking kernel $DEV_BRANCH branch for updates ..." git checkout -f $DEV_BRANCH cd "$CWD" # Download gcc and related packages to build cross-compiler echo "Downloading packages ..." if [ ! -d "$CWD"/$BINUTILS_VERSION ]; then wget -nc --progress=bar https://ftp.gnu.org/gnu/binutils/$BINUTILS_VERSION.tar.gz tar -xvf $BINUTILS_VERSION.tar.gz fi if [ ! -d "$CWD"/$GCC_VERSION ]; then wget -nc --progress=bar https://ftp.gnu.org/gnu/gcc/$GCC_VERSION/$GCC_VERSION.tar.gz tar -xvf $GCC_VERSION.tar.gz fi if [ ! -d "$CWD"/$GLIBC_VERSION ]; then wget -nc --progress=bar https://ftp.gnu.org/gnu/glibc/$GLIBC_VERSION.tar.xz tar -xvf $GLIBC_VERSION.tar.xz fi if [ ! -d "$CWD"/$GMP_VERSION ]; then wget -nc --progress=bar https://ftp.gnu.org/gnu/gmp/$GMP_VERSION.tar.xz tar -xvf $GMP_VERSION.tar.xz fi if [ ! -d "$CWD"/$MPFR_VERSION ]; then wget -nc --progress=bar https://ftp.gnu.org/gnu/mpfr/$MPFR_VERSION.tar.xz tar -xvf $MPFR_VERSION.tar.xz fi if [ ! -d "$CWD"/$MPC_VERSION ]; then wget -nc --progress=bar https://ftp.gnu.org/gnu/mpc/$MPC_VERSION.tar.gz tar -xvf $MPC_VERSION.tar.gz fi if [ ! -d "$CWD"/$ISL_VERSION ]; then wget -nc --progress=bar ftp://gcc.gnu.org/pub/gcc/infrastructure/$ISL_VERSION.tar.bz2 tar -xvf $ISL_VERSION.tar.bz2 fi if [ ! -d "$CWD"/$CLOOG_VERSION ]; then wget -nc --progress=bar ftp://gcc.gnu.org/pub/gcc/infrastructure/$CLOOG_VERSION.tar.gz tar -xvf $CLOOG_VERSION.tar.gz fi # Create symbolic links so gcc builds these dependencies automatically echo "Creating symbolic links in gcc ..." cd "$CWD"/$GCC_VERSION ln -sf ../$MPFR_VERSION mpfr ln -sf ../$GMP_VERSION gmp ln -sf ../$MPC_VERSION mpc ln -sf ../$ISL_VERSION isl ln -sf ../$CLOOG_VERSION cloog # Create aarch64 cross-compiler install directory echo "Creating $INSTALL_PATH directory ..." rm -rf $INSTALL_PATH mkdir -p $INSTALL_PATH chown "$(whoami)" $INSTALL_PATH cd "$CWD" # Build binutils echo "Building binutils ..." rm -rf build-binutils mkdir build-binutils cd build-binutils ../$BINUTILS_VERSION/configure --prefix=$INSTALL_PATH --target=$ARCH_TARGET $CONFIG_OPTIONS make $PARALLEL_JOBS echo "Installing binutils ..." make install # Install Linux kernel headers echo "Installing kernel headers ..." cd "$CWD"/$LINUX_FLAVOUR make ARCH=$LINUX_ARCH INSTALL_HDR_PATH=$INSTALL_PATH/$ARCH_TARGET headers_install cd "$CWD" # Build gcc C and C++ cross-compilers echo "Building gcc $ARCH_TARGET C,C++ cross-compiler ..." mkdir -p build-gcc cd build-gcc ../$GCC_VERSION/configure --prefix=$INSTALL_PATH --target=$ARCH_TARGET $BUILD_LANGUAGES $CONFIG_OPTIONS make $PARALLEL_JOBS all-gcc echo "Installing gcc $ARCH_TARGET cross-compiler to $INSTALL_PATH ..." make $PARALLEL_JOBS install-gcc # create gcc-12.2.0 libsanitizer asan_linux-cpp.patch file cd "$CWD" touch asan_linux-cpp.patch cat << EOF > asan_linux-cpp.patch --- gcc-12.2.0/libsanitizer/asan/asan_linux.cpp 2022-09-17 08:36:38.000000000 +0100 +++ asan_linux.cpp 2022-09-17 08:37:30.000000000 +0100 @@ -77,6 +77,10 @@ asan_rt_version_t __asan_rt_version; } +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + namespace __asan { void InitializePlatformInterceptors() {} EOF # Patch gcc-12.2.x/libsanitizerasan/asan_linux.cpp [or the build will fail] ASANLINUXCC=$CWD/$GCC_VERSION/libsanitizer/asan/asan_linux.cpp if [ ! -f "$ASANLINUXCC".orig ]; then echo "Patching $ASANLINUXCC ..." patch -b "$ASANLINUXCC" asan_linux-cpp.patch || exit 1 # sarpiSP64 echo "$ASANLINUXCC has been PATCHED! ..." echo "Backup of original: $ASANLINUXCC.orig ..." sleep 10 fi # Build and install glibc's standard C library headers and startup files echo "Building glibc library headers ..." mkdir -p build-glibc cd build-glibc ../$GLIBC_VERSION/configure --prefix=$INSTALL_PATH/$ARCH_TARGET --build="$MACHTYPE" --host=$ARCH_TARGET --target=$ARCH_TARGET --with-headers=$INSTALL_PATH/$ARCH_TARGET/include $CONFIG_OPTIONS libc_cv_forced_unwind=yes make $PARALLEL_JOBS install-bootstrap-headers=yes install-headers make $PARALLEL_JOBS csu/subdir_lib echo "Installing glibc library headers ..." install csu/crt1.o csu/crti.o csu/crtn.o $INSTALL_PATH/$ARCH_TARGET/lib $ARCH_TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $INSTALL_PATH/$ARCH_TARGET/lib/libc.so touch $INSTALL_PATH/$ARCH_TARGET/include/gnu/stubs.h # Build glibc support library echo "Building glibc support library ..." cd "$CWD"/build-gcc make $PARALLEL_JOBS all-target-libgcc echo "Installing glibc support library ..." make install-target-libgcc # Finish building glibc's standard C library and install it echo "Completing glibc C library ..." cd "$CWD"/build-glibc make $PARALLEL_JOBS echo "Installing glibc C library ..." make install # Finish building gcc's C++ library and install it echo "Completing glibc C++ library ..." cd "$CWD"/build-gcc make $PARALLEL_JOBS echo "Installing glibc C++ library ..." make install cd "$CWD" # Check status of aarch64-linux-gcc cross-compiler echo "Checking status of $ARCH_TARGET-gcc cross-compiler ..." ARCH_TARGET_STATUS=$(which $ARCH_TARGET-gcc) $ARCH_TARGET-gcc -v if [ ! -e "$ARCH_TARGET_STATUS" ]; then # ERROR! echo "ERROR: $ARCH_TARGET-gcc not responding!" echo "$(date +"%F %T") : $PRGNAM FAILED! ..." exit 1 else # Done! echo "Verifying $ARCH_TARGET-gcc \$PATH ..." echo "PATH: $PATH" echo "Status: $ARCH_TARGET-gcc : READY!" echo "$(date +"%F %T") : $PRGNAM build complete ..." fi exit 0