Last active
April 4, 2024 10:20
-
-
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!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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