Skip to content

Instantly share code, notes, and snippets.

@olegslavkin
Forked from kukrimate/bootstrap.sh
Last active April 4, 2024 10:20
Show Gist options
  • Save olegslavkin/c13c1cc7a7131f19df96b80369d2cc7d to your computer and use it in GitHub Desktop.
Save olegslavkin/c13c1cc7a7131f19df96b80369d2cc7d to your computer and use it in GitHub Desktop.
Create a cross gcc toolchain for any target! And it only builds everything once!
#!/bin/bash
# This script builds a (hopefully) working gcc based cross compiler
# Update to latest stable release
BINUTILS_VERSION=2.28
GMP_VERSION=6.1.2
MPFR_VERSION=3.1.5
MPC_VERSION=1.0.3
ISL_VERSION=0.16.1
GCC_VERSION=6.3.0
GLIBC_VERSION=2.25
# Update to latest Linux LTS
LINUX_MAJOR_REVISION=v4.x
LINUX_VERSION=4.4.48
if [ "$#" -ne 2 ]; then
printf "Usage: boostrap.sh <target> <path>\n"
exit 1
fi
# Store the arguments
TARGET=$1
PREFIX=$(readlink -f $2)
# Download sources
mkdir -p src && cd src
SRCDIR=$(readlink -f .)
curl -O http://mirror.yandex.ru/mirrors/gnu/binutils/binutils-$BINUTILS_VERSION.tar.gz || { echo 'Failed to download binutils!'; exit 1; }
curl -O http://mirror.yandex.ru/mirrors/gnu/gmp/gmp-$GMP_VERSION.tar.xz || { echo 'Failed to download gmp!'; exit 1; }
curl -O http://mirror.yandex.ru/mirrors/gnu/mpfr/mpfr-$MPFR_VERSION.tar.gz || { echo 'Failed to download mpfr!'; exit 1; }
curl -O http://mirror.yandex.ru/mirrors/mpc/mpc-$MPC_VERSION.tar.gz || { echo 'Failed to download mpc!'; exit 1; }
curl -O ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-$ISL_VERSION.tar.bz2 || { echo 'Failed to download isl!'; exit 1; }
curl -O https://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.gz || { echo 'Failed to download gcc!'; exit 1; }
curl -O https://ftp.gnu.org/gnu/glibc/glibc-$GLIBC_VERSION.tar.gz || { echo 'Failed to download glibc!'; exit 1; }
curl -O http://mirror.yandex.ru/pub/linux/kernel/$LINUX_MAJOR_REVISION/linux-$LINUX_VERSION.tar.xz || { echo 'Failed to download linux!'; exit 1; }
# Setup path
PATH=$PREFIX/bin:$PATH
# Setup makeflags
MAKEFLAGS=-j$(($(nproc || { echo 'Command `nproc` not found!'; exit 1; }) + 1))
# On amd64 create the lib64 symlink
case $(uname -m) in
x86_64) mkdir -p $PREFIX/$TARGET/lib && ln -sf lib $PREFIX/$TARGET/lib64 ;;
esac
# Dirty hack to fix sysroot support
ln -sf . $PREFIX/$TARGET/usr
mkdir -p $PREFIX/$TARGET/include
# Build binutils
tar -xf binutils-$BINUTILS_VERSION.tar.gz || { echo 'Failed to extract binutils!'; exit 1; } && cd binutils-$BINUTILS_VERSION
mkdir -p build && cd build
../configure --prefix=$PREFIX --target=$TARGET --disable-multilib --with-sysroot=$PREFIX/$TARGET --disable-nls || { echo 'Binutils configure failed!'; exit 1; }
make $MAKEFLAGS || { echo 'Binutils compile failed!'; exit 1; }
make install || { echo 'Binutils install failed!'; exit 1; }
# Build gcc
cd $SRCDIR
tar -xf gcc-$GCC_VERSION.tar.gz || { echo 'Extracting gcc failed!'; exit 1; } && cd gcc-$GCC_VERSION
tar -xf ../gmp-$GMP_VERSION.tar.xz || { echo 'Extracting gmp failed!'; exit 1; } && mv gmp-$GMP_VERSION gmp
tar -xf ../mpfr-$MPFR_VERSION.tar.gz || { echo 'Extracting mpfr failed!'; exit 1; } && mv mpfr-$MPFR_VERSION mpfr
tar -xf ../mpc-$MPC_VERSION.tar.gz || { echo 'Extracting mpc failed!'; exit 1; } && mv mpc-$MPC_VERSION mpc
tar -xf ../isl-$ISL_VERSION.tar.bz2 || { echo 'Extracting isl failed!'; exit 1; } && mv isl-$ISL_VERSION isl
mkdir -p build && cd build
../configure --prefix=$PREFIX --target=$TARGET --enable-languages=c,c++ --with-glibc-version=$GLIBC_VERSION --disable-multilib --with-sysroot=$PREFIX/$TARGET \
--disable-nls --disable-decimal-float --disable-libatomic --disable-libgomp --disable-libmpx --disable-libquadmath --disable-libssp --disable-libvtv \
|| { echo 'Gcc configure failed!'; exit 1; }
# Build just the compiler for now
make $MAKEFLAGS all-gcc || { echo 'Building the compiler part of gcc failed!'; exit 1; }
make install-gcc || { echo 'Failed to install gcc!'; exit 1; }
# Install the kernel headers
cd $SRCDIR
LINUX_ARCH=$(echo $TARGET | cut -d'-' -f 1)
tar -xf linux-$LINUX_VERSION.tar.xz || { echo 'Error extracting the kernel sources!'; exit 1; } && cd linux-$LINUX_VERSION
make mrproper || { echo 'Failed to prepare Linux sources!'; exit 1; }
make ARCH=$LINUX_ARCH INSTALL_HDR_PATH=dest headers_install || { echo 'Failed to install Linux headers!'; exit 1; }
# Remove install files
find dest -name .install -delete -or -name ..install.cmd -delete
cp -R dest/include $PREFIX/$TARGET/ || { echo 'Error copying Linux headers to the prefix!'; exit 1; }
# Build glibc
cd $SRCDIR
tar -xf glibc-$GLIBC_VERSION.tar.gz || { echo 'Error extracting glibc!'; exit 1; } && cd glibc-$GLIBC_VERSION
mkdir -p build && cd build
../configure --prefix=$PREFIX/$TARGET --host=$TARGET --enable-kernel=2.6.32 --with-headers=$PREFIX/$TARGET/include \
libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes --disable-executables || { echo 'Failed to configure glibc!'; exit 1; }
# Install C runtime
make $MAKEFLAGS csu/subdir_lib || { echo 'Failed to build the C runtime!'; exit 1; }
install csu/crt1.o csu/crti.o csu/crtn.o $PREFIX/$TARGET/lib || { echo 'Failed to install the C runtime!'; exit 1; }
# Install headers
make install-headers || { echo 'Failed to install system headers!'; exit 1; }
# Install fake temporary C library
$TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $PREFIX/$TARGET/lib/libc.so || { echo 'Failed to install fake C library!'; exit 1; }
# Create fake 'stubs.h' headers
touch $PREFIX/$TARGET/include/gnu/stubs.h || { echo 'Failed to create fake stubs.h header!'; exit 1; }
# Build libgcc
cd $SRCDIR/gcc-$GCC_VERSION/build
make $MAKEFLAGS all-target-libgcc || { echo 'Failed to build libgcc!'; exit 1; }
make install-target-libgcc || { echo 'Failed to install libgcc!'; exit 1; }
# Build and install the rest of glibc
cd $SRCDIR/glibc-$GLIBC_VERSION/build
make $MAKEFLAGS || { echo 'Failed to build glibc!'; exit 1; }
make install || { echo 'Failed to install glibc!'; exit 1; }
# Finally build the rest of gcc
cd $SRCDIR/gcc-$GCC_VERSION/build
make $MAKEFLAGS || { echo 'Failed to build gcc!'; exit 1; }
make install || { echo 'Failed to install gcc'; exit 1; }
# Fix incomplete limits.h
cd $SRCDIR/gcc-$GCC_VERSION
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > `dirname $($TARGET-gcc -print-libgcc-file-name)`/include-fixed/limits.h \
|| { echo 'Failed to create final limits.h!'; exit 1; }
echo 'Done building! Everything succeeded!'
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment