-
-
Save preshing/41d5c7248dea16238b60 to your computer and use it in GitHub Desktop.
#! /bin/bash | |
set -e | |
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG | |
trap 'echo FAILED COMMAND: $previous_command' EXIT | |
#------------------------------------------------------------------------------------------- | |
# This script will download packages for, configure, build and install a GCC cross-compiler. | |
# Customize the variables (INSTALL_PATH, TARGET, etc.) to your liking before running. | |
# If you get an error and need to resume the script from some point in the middle, | |
# just delete/comment the preceding lines before running it again. | |
# | |
# See: http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler | |
#------------------------------------------------------------------------------------------- | |
INSTALL_PATH=/opt/cross | |
TARGET=aarch64-linux | |
USE_NEWLIB=0 | |
LINUX_ARCH=arm64 | |
CONFIGURATION_OPTIONS="--disable-multilib" # --disable-threads --disable-shared | |
PARALLEL_MAKE=-j4 | |
BINUTILS_VERSION=binutils-2.24 | |
GCC_VERSION=gcc-4.9.2 | |
LINUX_KERNEL_VERSION=linux-3.17.2 | |
GLIBC_VERSION=glibc-2.20 | |
MPFR_VERSION=mpfr-3.1.2 | |
GMP_VERSION=gmp-6.0.0a | |
MPC_VERSION=mpc-1.0.2 | |
ISL_VERSION=isl-0.12.2 | |
CLOOG_VERSION=cloog-0.18.1 | |
export PATH=$INSTALL_PATH/bin:$PATH | |
# Download packages | |
export http_proxy=$HTTP_PROXY https_proxy=$HTTP_PROXY ftp_proxy=$HTTP_PROXY | |
wget -nc https://ftp.gnu.org/gnu/binutils/$BINUTILS_VERSION.tar.gz | |
wget -nc https://ftp.gnu.org/gnu/gcc/$GCC_VERSION/$GCC_VERSION.tar.gz | |
if [ $USE_NEWLIB -ne 0 ]; then | |
wget -nc -O newlib-master.zip https://github.com/bminor/newlib/archive/master.zip || true | |
unzip -qo newlib-master.zip | |
else | |
wget -nc https://www.kernel.org/pub/linux/kernel/v3.x/$LINUX_KERNEL_VERSION.tar.xz | |
wget -nc https://ftp.gnu.org/gnu/glibc/$GLIBC_VERSION.tar.xz | |
fi | |
wget -nc https://ftp.gnu.org/gnu/mpfr/$MPFR_VERSION.tar.xz | |
wget -nc https://ftp.gnu.org/gnu/gmp/$GMP_VERSION.tar.xz | |
wget -nc https://ftp.gnu.org/gnu/mpc/$MPC_VERSION.tar.gz | |
wget -nc ftp://gcc.gnu.org/pub/gcc/infrastructure/$ISL_VERSION.tar.bz2 | |
wget -nc ftp://gcc.gnu.org/pub/gcc/infrastructure/$CLOOG_VERSION.tar.gz | |
# Extract everything | |
for f in *.tar*; do tar xfk $f; done | |
# Make symbolic links | |
cd $GCC_VERSION | |
ln -sf `ls -1d ../mpfr-*/` mpfr | |
ln -sf `ls -1d ../gmp-*/` gmp | |
ln -sf `ls -1d ../mpc-*/` mpc | |
ln -sf `ls -1d ../isl-*/` isl | |
ln -sf `ls -1d ../cloog-*/` cloog | |
cd .. | |
# Step 1. Binutils | |
mkdir -p build-binutils | |
cd build-binutils | |
../$BINUTILS_VERSION/configure --prefix=$INSTALL_PATH --target=$TARGET $CONFIGURATION_OPTIONS | |
make $PARALLEL_MAKE | |
make install | |
cd .. | |
# Step 2. Linux Kernel Headers | |
if [ $USE_NEWLIB -eq 0 ]; then | |
cd $LINUX_KERNEL_VERSION | |
make ARCH=$LINUX_ARCH INSTALL_HDR_PATH=$INSTALL_PATH/$TARGET headers_install | |
cd .. | |
fi | |
# Step 3. C/C++ Compilers | |
mkdir -p build-gcc | |
cd build-gcc | |
if [ $USE_NEWLIB -ne 0 ]; then | |
NEWLIB_OPTION=--with-newlib | |
fi | |
../$GCC_VERSION/configure --prefix=$INSTALL_PATH --target=$TARGET --enable-languages=c,c++ $CONFIGURATION_OPTIONS $NEWLIB_OPTION | |
make $PARALLEL_MAKE all-gcc | |
make install-gcc | |
cd .. | |
if [ $USE_NEWLIB -ne 0 ]; then | |
# Steps 4-6: Newlib | |
mkdir -p build-newlib | |
cd build-newlib | |
../newlib-master/configure --prefix=$INSTALL_PATH --target=$TARGET $CONFIGURATION_OPTIONS | |
make $PARALLEL_MAKE | |
make install | |
cd .. | |
else | |
# Step 4. Standard C Library Headers and Startup Files | |
mkdir -p build-glibc | |
cd build-glibc | |
../$GLIBC_VERSION/configure --prefix=$INSTALL_PATH/$TARGET --build=$MACHTYPE --host=$TARGET --target=$TARGET --with-headers=$INSTALL_PATH/$TARGET/include $CONFIGURATION_OPTIONS libc_cv_forced_unwind=yes | |
make install-bootstrap-headers=yes install-headers | |
make $PARALLEL_MAKE csu/subdir_lib | |
install csu/crt1.o csu/crti.o csu/crtn.o $INSTALL_PATH/$TARGET/lib | |
$TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $INSTALL_PATH/$TARGET/lib/libc.so | |
touch $INSTALL_PATH/$TARGET/include/gnu/stubs.h | |
cd .. | |
# Step 5. Compiler Support Library | |
cd build-gcc | |
make $PARALLEL_MAKE all-target-libgcc | |
make install-target-libgcc | |
cd .. | |
# Step 6. Standard C Library & the rest of Glibc | |
cd build-glibc | |
make $PARALLEL_MAKE | |
make install | |
cd .. | |
fi | |
# Step 7. Standard C++ Library & the rest of GCC | |
cd build-gcc | |
make $PARALLEL_MAKE all | |
make install | |
cd .. | |
trap - EXIT | |
echo 'Success!' |
Incidentally I'm here looking at the script, because in following the steps on your blog, I got an error on Step 4.
I'm on Mac OS X Sierra 10.12.4. No errors (modulo having to unpack linux-4.4.38 to a case-sensitive filesystem in order for it to install properly) following Steps 1-3.
At Step 4, though, I got the following:
$ ../glibc-2.19/configure --prefix=/usr/local/bin/gcc-7.1.0-armv7-linux-gnueabihf/armv7-linux-gnueabihf --build=$MACHTYPE --host=armv7-linux-gnueabihf --target=armv7-linux-gnueabihf --with-headers=/usr/local/bin/gcc-7.1.0-armv7-linux-gnueabihf/include --disable-multilib libc_cv_forced_unwind=yes
checking build system type... x86_64-apple-darwin16
checking host system type... armv7-unknown-linux-gnueabihf
checking for armv7-linux-gnueabihf-gcc... /usr/local/bin/gcc-7.1.0-armv7-linux-gnueabihf/bin/armv7-linux-gnueabihf-gcc
...
checking whether to put _rtld_local into .sdata section... no
checking for .preinit_array/.init_array/.fini_array support... no
configure: error: Need linker with .init_array/.fini_array support.
I've tried several Google searches and a number of variations of the above configure
command, but no luck.
Any ideas on how to fix this?
--
Some background, in case it helps:
- Followed steps 1-4 exactly, changing only the target (armv7-unknown-gnueabihf for 32-bit ARM) and the install path (/usr/local/bin/gcc-7.1.0-armv7-unknown-gnueabihf).
- Compiled using gcc v7.1.0 using the following versions of the gcc components to best match the kernel version used for the Raspberry Pi 3's Raspbian Linux or otherwise used the latest version:
- binutils v2.28
- glibc v2.19
- gmp v6.1.2
- isl v0.16.1
- linux 4.4.38
- mpc v1.0.3
- mpfr v3.1.5
Disable libsanitizer by passing --disable-libsanitizer
to GCC while configuring. That is, if you're using uClibc-ng.
If you want to compile on macOS do a Canadian Cross Compile with a macOS to Linux ABI handover. I'm not sure how to explain.
Amazing script. I was able to create a cross compiler for ARM, and then create a Kernel and BusyBox to boot up in QEMU. I have converted the script to a makefile under kanj/MAKE_CROSS_LINUX for reference.
Very interesting script. On this basis, i create conan package https://github.com/BetterCallBene/conan-cgcc.
Is it possible to build multi lib gcc i.e. with aarch64 and arm?
This doesn't work for me trying to build gcc-4.8.5. It fails on configuring glibc (2.12.2) as it is using the newly built cross-compiled-gcc which cannot find stdio.h. I can resolve this by not exporting the PATH to the new binaries but then the csu binaries built will be for the host architecture. Not really sure how to resolve it.
Anyone trying to use something other than Linux as the build/host platform may be helped by looking at my fork of this script.
My Fork
I used MSys2 64 bit (a Cygwin fork) under Win7 64 bit; I yet to test the cross compiler produced; did it as a learning exercise.
I have no need to use it; but, likely will in a few months.
Edit2: Once, I deleted the installed files my version of the script stopped building with gcc/glibc errors.
Tim S.
I'm building for a RaspberryPi3 running Raspbian, so I want to build my cross-compiler for a 32-bit Linux target. (I'm on Mac OS X Sierra 10.12.4, if that matters.) Should I use
arm-linux
?armv7-unknown-gnueabihf
? Something else?Fairly new to this, so in addition to knowing the proper 32-bit target identifier for the RPi3, I'd like to know how/where to find the list of valid targets.
Thank you for this and the blog article!