Crosscompiler
Crosstool-NG
Prerequisites
Linux
sudo apt-get install autoconf automake bison curl cvs flex g++ gawk gcc git gperf help2man libgmp-dev libncurses-dev libstdc++-dev libtool libtool-bin make mercurial patch subversion texinfo wget
sudo yum install autoconf automake bison curl cvs flex gawk gcc gcc-c++ git glibc-static gmp-devel gperf libstdc++-devel libstdc++-static libtool make mercurial ncurses-devel patch subversion texinfo wget
sudo zypper install autoconf automake bison curl cvs flex gawk gcc gcc-c++ git glibc-devel-static gmp-devel gperf libstdc++-devel libtool make mercurial ncurses-devel patch subversion texinfo wget
MacOS X
For MacOS it gets more complicated[1][2], we need the following[3]:
gcc (>= 4.3)
installed orclang
for MacOS X 10.x- Some GNU utilities:
lzmautils, libtool, binutils, gsed, gawk
- A case sensitive file system for
ct-ng
's build and target directories
Install the prerequisites:
sudo port install git gsed coreutils libtool gawk wget autoconf automake
There's no suitable[4] binutils
package for MacPorts, so let's build it ourselves:
wget http://ftp.gnu.org/gnu/binutils/binutils-2.25.tar.bz2{,.sig} gpg --keyserver hkp://keys.gnupg.net --recv-keys 4AE55E93 gpg --verify binutils*.tar.bz2.sig tar -xjf binutils*.tar.bz2 && cd binutils* ./configure --prefix=/opt/binutils && make && sudo make install
Make the new binutils available in PATH
:
export PATH=/opt/binutils/bin:${PATH}
While we e should be able to install crosstool-ng
anywhere on the system disk, we still need a case sensitive file system to build our tool chain.
$ mkfile -n -v 4g /var/tmp/ct-disk.img # -n creates an sparse file $ hdiutil attach -nomount /var/tmp/ct-disk.img /dev/disk4
Note: hdiutil(1) expects the image filename to end in .img
, otherwise it may fail with:
hdiutil: attach failed - image not recognized
Now we can create a case sensitive file system[5] on this virtual disk:
$ diskutil eraseDisk jhfsx ct-disk disk4
Started erase on disk4
Unmounting disk
Creating the partition map
Waiting for the disks to reappear
Formatting disk4s1 as Mac OS Extended (Case-sensitive, Journaled) with name ct-disk
Initialized /dev/rdisk4s1 as a 1024 MB case-sensitive HFS Plus volume with a 8192k journal
Mounting disk
Finished erase on disk4
The disk should now be mounted on /Volumes/ct-disk
, let's prepare it for the toolchain build later on:
mkdir -p /Volumes/ct-disk/{ctng,tools} ln -s /Volumes/ct-disk/ctng /var/tmp/ctng
Installation
Download Crosstool-NG:
wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.20.0.tar.xz{,.sig} gpg --keyserver hkp://keys.gnupg.net --recv-keys A156D05D gpg --verify crosstool-ng*tar.xz.sig xz -dc crosstool-ng*tar.xz | tar -xf - cd crosstool-ng-*
git clone https://github.com/crosstool-ng/crosstool-ng.git crosstool-ng-git cd crosstool-ng-git git checkout -b local crosstool-ng-1.22.0 # We will use a stable version this time
Note: crosstool-ng v1.20
still has a bug in scripts/crosstool-NG.sh
[7] on BSD like systems that we need to address first:
diff --git a/scripts/crosstool-NG.sh.in b/scripts/crosstool-NG.sh.in index cd65d5b..53ac552 100644 --- a/scripts/crosstool-NG.sh.in +++ b/scripts/crosstool-NG.sh.in @@ -125,7 +125,7 @@ CT_DoLog INFO "Build started ${CT_STAR_DATE_HUMAN}" # We really need to extract from ,config and not .config.2, as we # do want the kconfig's values, not our mangled config with arrays. CT_DoStep DEBUG "Dumping user-supplied crosstool-NG configuration" -CT_DoExecLog DEBUG ${grep} -E '^(# |)CT_' .config +CT_DoExecLog DEBUG ${grep} -E '^(# )?CT_' .config CT_EndStep CT_DoLog DEBUG "Unsetting and unexporting MAKEFLAGS"
Now we can install Crosstool-NG:
export PREF=/opt/ctng ./bootstrap ./configure --prefix=${PREF}
When building on MacOS X, we need our GNU tools in PATH
:
PATH=/opt/local/bin:{$PATH} ./configure --prefix=${PREF} --with-libtool=glibtool --with-libtoolize=glibtoolize
Build with:
make sudo make install ln -s /Volumes/ct-disk/tools /opt/ctng/tools # On MacOS X, the toolchain directory needs to be case sensitive sudo install -v -m0644 -o root -g root ct-ng.comp /etc/bash_completion.d/ # For bash-completion echo "export PATH=\$PATH:$PREF/bin" | sudo tee /etc/profile.d/ctng.sh
On our NFS-mounted share this failed (root was not allowed to read /home
where the build took place) and we did make install
like this:
sudo mkdir -p ${PREF} && sudo chown ${USER} ${PREF} make install sudo chown -R root:root ${PREF}
Building a toolchain
$ mkdir -p /var/tmp/ctng/build /usr/local/src/pkg $ cd /var/tmp/ctng $ ct-ng help $ ct-ng menuconfig $ grep -E 'CT_((WORK|PREFIX|LOCAL_TARBALLS)_DIR|SAVE_TARBALLS|ARCH|PARALLEL_JOBS|LIBC)=' .config CT_LOCAL_TARBALLS_DIR="/usr/local/src/pkg" # Paths and misc options → Local tarballs directory CT_SAVE_TARBALLS=y # Paths and misc options → Save new tarballs CT_WORK_DIR="/var/tmp/ctng/build" # Paths and misc options → Working directory CT_PREFIX_DIR="/opt/ctng/tools/${CT_TARGET}" # Paths and misc options → Prefix directory CT_PARALLEL_JOBS=4 # Paths and misc options → Number of parallel jobs CT_ARCH="powerpc" # Target options → Target Architecture CT_LIBC="glibc" # C-library → C library[8]
MacOS
# gcc other options CT_CC_STATIC_LIBSTDCXX=n # General toolchain options CT_WANTS_STATIC_LINK=n CT_STATIC_TOOLCHAIN=n
Examples
We selected powerpc here for our target architecture. Since we know the machine running the code will be a PowerBook G4, we can set -mcpu
and -mtune
for gcc:[11]
CT_ARCH_CPU="G4" # Target options → Emit assembly for CPU CT_ARCH_TUNE="G4" # Target options → Tune for CPU
If we know the operating system our target will be running on, we can select it instead of "bare-metal"
:
CT_KERNEL="linux" # Operating System → Target OS
After saving the configuration, we can print the tuple[12] of the configured (but yet to be built) toolchain:
$ ct-ng show-tuple
powerpc-unknown-linux-gnu # Note: it will print "powerpc-unknown-elf" if we selected
# "bare-metal" for CT_KERNEL
For ARMv8[13] (e.g. Raspberry_Pi):
CT_ARCH_32=y # Tuple: arm-unknown-linux-gnueabihf CT_ARCH_ARCH="armv7-a" CT_ARCH_FPU="neon-vfpv4" CT_ARCH_FLOAT_HW=y CT_ARCH_FLOAT="hard"
For aarch64
, only set:
CT_ARCH_64=y # Tuple: aarch64-unknown-linux-gnueabi CT_ARCH_ARCH="armv8-a"
Be sure to have plenty of diskspace available, building toolchains sometimes uses a lot:
CT_LOCAL_TARBALLS_DIR
may use ~500 MBCT_WORK_DIR
may use ~5 GB per architecture (2 GB for the extraced sources, 3 GB for building them)CT_PREFIX_DIR
may use ~100 MB per architecture
Now we're ready to actually build (and install) our toolchain.
sudo mkdir -p /opt/ctng/tools sudo chown -R ${USER} /opt/ctng/tools
Build our tool chain:
export PATH=/opt/local/libexec/gnubin:${PATH} # For MacOS X onlyct-ng build
This might take a while: on my Intel Core 2 Duo processor, it takes about 6 hours to build for one architecture; on a 4-core Intel i7-3632QM this took about 30 minutes.
Note: the build might fail if DEB_BUILD_HARDENING=1
enabled and -Werror=format-security
is set.[14]
After the build is done, setting the ownership of the toolchain to root
is advised:
sudo chown -R root:root /opt/ctng/tools
NOTE: We cannot set CT_WORK_DIR
or CT_PREFIX_DIR
to reside underneath our crosstool installation (/opt/ctng
), otherwise it might fail early on.[15]
Usage
Hello World
Standard hello.c
:
#include<stdio.h> int main(void) { printf("Hello World\n"); return 0; }
$ powerpc-unknown-linux-gnu-gcc hello.c -o hello.exe $ file hello.exe hello.exe: ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.15.4, not stripped $ scp hello.exe alice: $ ssh alice "uname -rm; ./hello.exe" 3.19.0-rc5 ppc Hello World
Linux Kernel
To build a Linux kernel, use:
export PATH=${PATH}:/opt/ctng/tools/powerpc-unknown-linux-gnu/bin export DIR=/var/tmp/lnx make -j2 O=${DIR} ARCH=powerpc CROSS_COMPILE=powerpc-unknown-linux-gnu- tarxz-pkg
Note the trailing "-" after the toolchain tuple (powerpc-unknown-linux-gnu). It's important, so that the build system can find its compilers in ${PATH}
.
When combined with ccache, it looks like this:
make -j4 O=${DIR} ARCH=powerpc CROSS_COMPILE="ccache powerpc-unknown-linux-gnu-" tarxz-pkg
And with distcc:
make -j4 O=${DIR} ARCH=powerpc CROSS_COMPILE="ccache powerpc-unknown-linux-gnu-" CCACHE_PREFIX=distcc tarxz-pkg
Building for multipe architectures
KERNEL=/usr/local/src/linux-2.6-git RESULT=${HOME}/results TOOLS=/opt/ctng/tools # Find out which archs we can build for ARCHS="$(find "${TOOLS}" -maxdepth 1 -type l | sed 's/.*\///' | xargs echo)" cd ${KERNEL_SOURCE} for arch in ${ARCHS}; do # powerpc-750-linux-gnu vs. powerpc-unknown-linux-gnu CROSS_COMPILE="$(ls -d "${CROSS}"/gcc*/"${arch}"* | sed 's/.*\///')-" PATH="${TOOLS}/${arch}/bin:/bin:/usr/bin" echo "ARCH=${arch}" PATH="${PATH}" CROSS_COMPILE="${CROSS_COMPILE}" ${DEBUG} mkdir -p "${RESULT}/${arch}" ${DEBUG} make -ki O="${RESULT}/${arch}" mrproper # Build kernel, modules ${DEBUG} make -ki O="${RESULT}/${arch}" targz-pkg # # Fetch, archive results # cleanup # ${DEBUG} make -ki O="${RESULT}/${arch}" mrproper echo "" done
Crosstool
Crosstool hasn't been updated for some years now, so the following is more for historic reference.
Installation
You may want to tune the scripts to your needs to build as many archs as possible with as less hassle as possible:
wget http://www.kegel.com/crosstool/crosstool-0.43.tar.gz -O - | tar -xzf - # Last Update: 2006-12-07 wget http://crosstool.googlecode.com/svn/trunk/src/patches/glibc-2.3.6/glibc-2.3.6-csu-Makefile.patch mv glibc-2.3.6-csu-Makefile.patch crosstool-0.43/patches/glibc-2.3.6/ cd crosstool-0.43/
Or, when checking out via Subversion:
svn co https://crosstool.googlecode.com/svn/trunk/src/ crosstool-svn # Last update: 2008-10-15 cd crosstool-svn
Adjust TARBALLS_DIR
and RESULT_TOP
:
sed -i 's/^TARBALLS_DIR=.*/TARBALLS_DIR=\/var\/tmp\/pkgs/' demo-*sh # Tarballs into /var/tmp/pkgs sudo mkdir -p /opt/crosstool /var/tmp/pkgs # Create directories sudo chown -R ${USER} /opt/crosstool /var/tmp/pkgs
Some prerequisites to be installed:
sudo apt-get install gettext gcc g++ binutils bison flex autoconf automake
Available architectures:
$ ls demo-*.sh | sed 's/demo-//;s/\.sh//' | xargs echo alpha arm9tdmi armeb arm-iwmmxt arm arm-softfloat armv5b-softfloat arm-xscale canadian cluster cygwin \ i686 ia64 m68k mipsel mips powerpc-405 powerpc-603 powerpc-750 powerpc-860 powerpc-970 pr17209 runtest \ s390 sh3 sh4 sparc64 sparc x86_64
Which architectures to build:
archs="alpha arm i686 mips powerpc-750 sparc x86_64"
Find out what would happen
for a in ${archs}; do echo "ARCH: ${a}" grep -Ev '^\#|^$' "demo-${a}.sh" echo done
Find out what will happen :)
for a in ${archs}; do echo "ARCH: ${a}" sh "demo-${a}.sh" 2>&1 | tee "demo-${a}.log" done
Create symlinks for each arch (wow, I wonder when this will break...):
cd `awk -F= '/^RESULT_TOP/ {print $2}' demo-s390.sh` for i in */*/*gnu; do (ln -vs "$i" "`echo $i | sed 's/.*\///;s/-.*//'`"); done for i in */*gnu; do (ln -vs "$i" "`echo $i | sed 's/.*\///;s/-.*//'`"); done
Sources
Tool | URL | Last update |
---|---|---|
binutils | https://ftp.gnu.org/gnu/binutils/ | |
gcc | https://ftp.gnu.org/gnu/gcc/ | |
glibc | https://ftp.gnu.org/gnu/glibc/ | |
gdb | https://ftp.gnu.org/gnu/gdb/ | |
linux | https://www.kernel.org/pub/linux/kernel/v3.x/ | |
linux-libc-headers | http://ep09.pld-linux.org/~mmazur/linux-libc-headers/ resp. https://github.com/pld-linux/linux-libc-headers | 2005-07-06 |
glibc-linuxthreads | https://ftp.gnu.org/gnu/glibc/ | 2006-10-02 |
TODO
- make use of ccache, distcc (PARALLELMFLAGS="-j2")
- (more) sophisticated tracking of build results
Links
- Applications
- WANTS_STATIC_LINK
- Building and Testing gcc/glibc cross toolchains
- Al Viro: massive cross-builds without too much PITA
- crosstool-ng
- How to make a cross compiler (gcc) for freebsd under linux. A small tutorial.
- A tool to generate a freebsd cross compiler (gcc) in linux
- make.cross (Usage:
make.cross ARCH=sh
)
References
- ↑ crosstool-ng.org: MacOS X
- ↑ docs/README.macos.txt (crosstool-NG 1.8)
- ↑ docs/C - Misc. tutorials.txt (crosstool-NG 1.20)
- ↑ dports/devel/binutils/Portfile
- ↑ diskutil(8) (see Format under partitionDisk)
- ↑ Announcement: Moving to github (2014-12-05)
- ↑ scripts/crosstool-NG.sh.in: patch regex to work with BSD grep
- ↑ Compilation issue in NIS (EGLIBC is no longer developed and such goals are now being addressed directly in GLIBC.)
- ↑ Cross Compile from OS X
- ↑ Re: Static linking impossible on the host system
- ↑ Safe CFLAGS: G4 (PPC 74xx)
- ↑ GNU configuration names
- ↑ Safe CFLAGS: ARMv8-A/BCM2837
- ↑ gcc does not build (error: format not a string literal and no format arguments)
- ↑ How to build cross toolchains for ARM crosstool-NG