#!/bin/sh BUILD_GCC=true BUILD_BINUTILS=true BUILD_GDB=true START_SHELL=false PROJECT_ROOT="$(pwd)" CROSS_ROOT="$PROJECT_ROOT/cross" PREFIX="$CROSS_ROOT" CROSS_BUILD_DIR="$PROJECT_ROOT/.cross_build" TARGET='' CPUS=1 # Get the target arch if [ -z "$ARCH" ]; then ARCH="$1" shift if [ -z "$ARCH" ]; then echo "Must define an arch" exit 1 fi fi case "$ARCH" in 'x86_64-elf'|'x86_64'|'x64'|'amd64') TARGET='x86_64-elf' CONFIG_EXTRA_GCC="$CONFIG_EXTRA_GCC --enable-multilib" ;; 'i686-elf'|'i386'|'x32'|'386') TARGET='i686-elf' CONFIG_EXTRA_GCC="$CONFIG_EXTRA_GCC --enable-multilib" ;; 'riscv-64-elf'|'rv64'|'riscv64') TARGET='riscv-64-elf' ;; *) echo "arch=$ARCH not implemented" exit 1 ;; esac # Get the build target while [ "${1:-}" != "" ]; do case "$1" in "--no-gcc") BUILD_GCC=false ;; "--no-binutils") BUILD_BINUTILS=false ;; "--no-gdb") BUILD_GDB=false ;; "--start-shell") START_SHELL=true BUILD_GCC=false BUILD_BINUTILS=false BUILD_GDB=false ;; esac shift done # TODO: add some more options to speed up the build / disable unnecessary features # https://gitlab.archlinux.org/archlinux/packaging/packages/riscv64-linux-gnu-binutils/-/blob/main/PKGBUILD CONFIG_EXTRA_BINUTILS="\ --without-zstd \ --with-sysroot \ --enable-languages=c \ --disable-nls \ --disable-werror" # TODO: add some more options to speed up the build / disable unnecessary features # https://gitlab.archlinux.org/archlinux/packaging/packages/riscv64-linux-gnu-gcc/-/blob/main/PKGBUILD CONFIG_EXTRA_GCC="\ --without-zstd \ --disable-nls \ --enable-languages=c \ --without-headers" CONFIG_EXTRA_GDB="\ --with-sysroot \ --disable-nls \ --disable-werror \ --without-headers \ --enable-languages=c \ --enable-tui=yes \ --with-expat" #CONFIG_HOST="$(gcc -dumpmachine)" FTP_MIRROR="https://ftpmirror.gnu.org" gdb_version='13.1' gcc_version='12.2.0' binutils_version='2.37' gcc_url="$FTP_MIRROR/gcc/gcc-$gcc_version" binutils_url="$FTP_MIRROR/binutils" gdb_url="$FTP_MIRROR/gdb" gdb_build_log=gdb-log-"$(date +%F_%H-%M)".log gcc_build_log=gcc-log-"$(date +%F_%H-%M)".log binutils_build_log=binutils-log-"$(date +%F_%H-%M)".log # check if the user wants a particular version if [ -n "$GDB_VERSION" ]; then gdb_version="$GDB_VERSION" fi # sanity check if [ -z "$TARGET" ]; then echo "Target not specified, how'd you get this far?" exit 1 fi # get the right number of cpus # and some extra fixes case $(uname) in 'OpenBSD') CPUS="$(sysctl -n hw.ncpu)" CPUS=$((CPUS + 1)) CONFIG_EXTRA_GCC="$CONFIG_EXTRA_GCC --with-gmp=/usr/local" # use GNU make alias make=gmake ;; 'Linux') CPUS="$(nproc)" CPUS=$((CPUS + 1)) ;; *) ;; esac gpg_verify() { keyring="$1" pkg="$2" sig="$3" gpg --verify --keyring "$keyring" "$sig" "$pkg" return $? } download_sources() { pkg="$1" sig="$2" url="$3" wget -nv -O "$pkg" "$url/$pkg" || return $? wget -nv -O "$sig" "$url/$sig" || return $? } download_and_build() { pkg_name="$1" pkg_version="$2" pkg_config="$3" pkg_url="$4" pkg_ark="$pkg_name-$pkg_version.tar.xz" pkg_sig="$pkg_name-$pkg_version.tar.xz.sig" # Get the archives and signature if they are not already present if ! [ -e "$pkg_ark" ] || ! [ -e "$pkg_sig" ]; then download_sources "$pkg_ark" "$pkg_sig" "$pkg_url" || return 1 fi # Verify the archive if ! gpg_verify ./gnu-keyring.gpg "$pkg_ark" "$pkg_sig"; then echo "Package signature was incorrect, please remove the donwloaded sources and try again" return 1 fi # Extract the archive xz -k -d "$pkg_ark" tar -xf "$pkg_name-$pkg_version.tar" && rm -f "$pkg_name-$pkg_version.tar" # FIXME: this forces a comlete rebuild #if [ -d "build-$pkg_name-$TARGET" ]; then # rm -rf "build-$pkg_name-$TARGET" #fi mkdir -p "build-$pkg_name-$TARGET" cd "build-$pkg_name-$TARGET" || exit 1 oldpath="$PATH" export PATH="$PREFIX/bin:$PATH" # shellcheck disable=SC2086 ../"$pkg_name-$pkg_version"/configure \ --target="$TARGET" \ $pkg_config \ --prefix="$PREFIX" || return 1 case "$pkg_name" in 'gcc') make all-gcc || return 1 make all-target-libgcc || return 1 make install-gcc || return 1 make install-target-libgcc || return 1 ;; 'binutils') make -j$CPUS || return 1 make install || return 1 ;; 'gdb') make all-gdb || return 1 make install-gdb || return 1 ;; esac export PATH="$oldpath" cd .. return 0 } #set -x mkdir -p "$PREFIX" mkdir -p "$CROSS_BUILD_DIR/$TARGET" cd "$CROSS_BUILD_DIR/$TARGET" || exit 1 # get the gnu keyring, used to verify the archives if [ $BUILD_GCC = true ] || [ $BUILD_BINUTILS = true ] || [ $BUILD_GDB = true ]; then if ! [ -e gnu-keyring.gpg ]; then wget -O gnu-keyring.gpg https://ftp.gnu.org/gnu/gnu-keyring.gpg fi fi if [ $BUILD_BINUTILS = true ]; then echo "### BUILDING BINUTILS ###" download_and_build binutils "$binutils_version" "$CONFIG_EXTRA_BINUTILS" \ "$binutils_url" > ../"$binutils_build_log" 2>&1 res=$? if ! [ $res -eq 0 ]; then echo "Error building binutils, check $CROSS_BUILD_DIR/$binutils_build_log for more details" exit 1 fi fi if [ $BUILD_GCC = true ]; then echo "### BUILDING GCC ###" download_and_build gcc "$gcc_version" "$CONFIG_EXTRA_GCC" \ "$gcc_url" > ../"$gcc_build_log" 2>&1 res=$? if ! [ $res -eq 0 ]; then echo "Error building gcc, check $CROSS_BUILD_DIR/$gcc_build_log for more details" exit 1 fi fi if [ $BUILD_GDB = true ]; then echo "### BUILDING GDB ###" download_and_build gdb "$gdb_version" "$CONFIG_EXTRA_GDB" \ "$gdb_url" > ../"$gdb_build_log" 2>&1 res=$? if ! [ $res -eq 0 ]; then echo "Error building gdb, check $CROSS_BUILD_DIR/$gdb_build_log for more details" exit 1 fi fi cd "$PROJECT_ROOT" || exit 1 if [ $START_SHELL = true ]; then PATH="$CROSS_ROOT/bin:$PATH" export PATH TARGET ARCH echo "### Starting $SHELL with correct PATH and TARGET ###" exec "$SHELL" || exit 1 fi # TODO: validate that all things are where they should