Cross-compiling tools package guidelines
Contents
Important note
This page describes new way of doing things, inspired by follwing packages in [community]
:
- mingw32-gcc and other packages from
mingw32-*
series - arm-elf-gcc-base and other packages from
arm-elf-*
series - arm-wince-cegcc-gcc and other packages from
arm-wince-cegcc-*
series
Version compatibility
Following strategies allows to select compatible vesions of gcc, binutils, kernel and C library:
- General rules:
- there is correlation between gcc and binutils releases, use simultaneously released versions
- it is better to use latest kernel headers to compile libc but use
--enable-kernel
switch (specific to glibc, other C libraries may use different conventions) to enforce work on older kernels;
- Official repositories: you may have to apply additional fixes and hacks but versions used by Arch Linux / Arch Linux ARM most probably can be made to work together
- Other distributions: they too do cross-compilation
- Gentoo crossdev Working Architecture Matrix|lists some working combinations
Building a Cross Compiler
The general approach to building a cross compiler is:
- binutils: Build a cross-binutils, which links and processes for the target architecture
- headers: Install a set of C library and kernel headers for the target architecture
- gcc-stage-1: Build a basic (stage 1) gcc cross-compiler. This will be used to compile the C library. It will be unable to build anything almost else (because it can't link against the C library it doesn't have).
- libc: Build the cross-compiled C library (using the stage 1 cross compiler).
- gcc-stage-2: Build a full (stage 2) C cross-compiler. Can be built
The source of the headers and libc will vary across platforms.
File Placement
To prevent file conflicts, place everything into /usr/lib/cross-<target>. The only exception to this rule are executables, that shall be placed directly into /usr/bin/ (however, to prevent conflicts here, prefix all of them with architecture name).
Typically, ./configure
would have at least following parameters:
_target=<your-target> # e.g. i686-pc-mingw32 _sysroot=/usr/lib/${_target} ... ./configure \ --prefix=${_sysroot} --sysroot=${_sysroot} \ --bindir=/usr/bin
Example
This is PKGBUILD for binutils for MinGW. Things worth noticing are:
- specifying root directory of the cross-environment
- usage of
${_pkgname}
,${_target}
and${_sysroot}
variables to make the code more readable - removal of the duplicated/conflicting files
# Maintainer: Allan McRae <allan@archlinux.org> # cross toolchain build order: binutils, headers, gcc (pass 1), w32api, mingwrt, gcc (pass 2) _target=i686-pc-mingw32 _sysroot=/usr/lib/cross-${_target} pkgname=cross-${_target}-binutils _pkgname=binutils pkgver=2.19.1 pkgrel=1 pkgdesc="MinGW Windows binutils" arch=('i686' 'x86_64') url="http://www.gnu.org/software/binutils/" license=('GPL') depends=('glibc>=2.10.1' 'zlib') options=('!libtool' '!distcc' '!ccache') source=(http://ftp.gnu.org/gnu/${_pkgname}/${_pkgname}-${pkgver}.tar.bz2) md5sums=('09a8c5821a2dfdbb20665bc0bd680791') build() { cd ${srcdir}/${_pkgname}-${pkgver} mkdir build && cd build ../configure --prefix=${_sysroot} --bindir=/usr/bin \ --with-sysroot=${_sysroot} \ --build=$CHOST --host=$CHOST --target=${_target} \ --with-gcc --with-gnu-as --with-gnu-ld \ --enable-shared --without-included-gettext \ --disable-nls --disable-debug --disable-win32-registry make || return 1 make DESTDIR=${pkgdir}/ install || return 1 # clean-up cross compiler root rm -r ${pkgdir}/${_sysroot}/{info,man} }
Hows and whys
Why not installing into /opt? There would be no need for fooling around with non-standard executable naming etc.?
- Two reasons:
- First, according to File Hierarchy Standard, these files just belong somewhere to /usr. Period.
- Second, installing into /opt is a last measure when there is no other option.
What is that out-of-path executables thing?
- This weird thing allows easier cross-compiling. Sometimes, project Makefiles do not use CC & co. variables and instead use gcc directly. If you just want to try to cross-compile such project, editing the Makefile could be a very lengthy operation. However, changing the
$PATH
to use "our" executables first is a very quick solution. - You would then run
PATH=/usr/bin/cross/arch/:$PATH make
instead ofmake
.