Cross-compiling tools package guidelines

Arch package guidelines
32-bit
–
CLR
–
CMake
–
Cross
–
DKMS
–
Eclipse
–
Electron
–
Font
–
Free Pascal
–
GNOME
–
Go
–
Haskell
–
Java
–
KDE
–
Kernel modules
–
Lisp
–
Meson
–
MinGW
–
Node.js
–
Nonfree
–
OCaml
–
Perl
–
PHP
–
Python
–
R
–
Ruby
–
Rust
-
Security
–
Shell
–
VCS
–
Web
–
Wine
This page describes how to create packages for
cross-compiler
toolchains.  Another method to cross-compile makes use of distcc on mixed architectures. See
Distcc#Cross compiling with distcc
.
Tip
As alternative for creation of cross-compiler packages you could use
crosstool-ng
and create you own toolchain in fully automated way. crosstool-ng can be found on
crosstool-ng
.
Important note
This page describes the new way of doing things, inspired by the following packages:
mingw-w64-gcc
and other packages from
mingw-w64-*
series
arm-none-eabi-gcc
and other packages from
arm-none-eabi-*
series
Other packages from
arm-wince-cegcc-*
series
Version compatibility
Warning
Using incompatible versions of packages for toolchain compilation leads to inevitable failures. By default consider
all
versions incompatible.
The following strategies allows you to select compatible versions of gcc, binutils, kernel and C library:
General rules:
there is a 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 (or its architecture-specific forks) most probably can be made to work together;
Software documentation: all GNU software have
README
and
NEWS
files, documenting things like minimal required versions of dependencies;
Other distributions: they too do cross-compilation
https://trac.clfs.org
covers steps, necessary for building cross-compiler and mentions somewhat up-to-date versions of dependencies.
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
use
linux-api-headers
as reference and pass
ARCH=
target-architecture
to
make
create libc headers package (process for Glibc is described
here
)
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 almost anything else (because it cannot link against the C library it does not 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
The source of the headers and libc will vary across platforms.
Tip
Exact procedure varies greatly, depending on your needs. For example, if you want to create a "clone" of an Arch Linux system with the same versions of kernel and glibc, you can skip building headers and pass
--with-build-sysroot=/
to
configure
.
Package naming
The package name shall
not
be prefixed with the word
cross-
(it was previously proposed, but was not adopted in official packages, probably due to additional length of names), and shall consist of the package name, prefixed by
GNU triplet
without vendor field or with "unknown" in vendor field; example:
arm-linux-gnueabihf-gcc
. If shorter naming convention exists (e.g.
mips-gcc
), it may be used, but this is not recommended.
File placement
Latest versions of gcc and binutils use non-conflicting paths for sysroot and libraries. Executables shall be placed into
/usr/bin/
, to prevent conflicts here, prefix all of them with architecture name.
Typically,
./configure
would have at least following parameters:
_target=
your_target
_sysroot=/usr/lib/${_target}
...
./configure \
    --prefix=${_sysroot} \
    --sysroot=${_sysroot} \
    --bindir=/usr/bin
where
your_target
can be, e.g., "i686-pc-mingw32".
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/${_target}

pkgname=${_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 ${_pkgname}-${pkgver}
  mkdir binutils-build && cd binutils-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
  make DESTDIR=${pkgdir}/ install

  # clean-up cross compiler root
  rm -r ${pkgdir}/${_sysroot}/{info,man}
}
Note
During cross-toolchain building always execute
configure
and
make
commands from dedicated directory (so-called out-of-tree compilation) and remove whole
src
directory after slightest change in
PKGBUILD
.
Hows and whys
Why not installing into /opt
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/
arch
/bin/:$PATH make
instead of
make
.
Troubleshooting
What to do if compilation fails without clear message?
For error, occurred during running
configure
, read
$srcdir/
pkgname
-build/config.log
. For error, occurred during compilation, scroll console log up or search for word "error".
What does this error [error message] means?
Most probably you made some of non-obvious errors:
Too many or too few configuration flags. Try to use already proven set of flags.
Dependencies are corrupted. For example misplaced or missing binutils files may result in cryptic error during gcc configuration.
You did not add
export CFLAGS=""
to your
build()
function (see
bug 25672
in GCC Bugzilla).
Some
--prefix
/
--with-sysroot
combination may require directories to be writable (non-obvious from clfs guides).
sysroot does nor yet has kernel/libc headers.
If google-fu does not help, immediately abandon current configuration and try more stable/proven one.
Why do files get installed in wrong places?
Various methods of running generic
make install
line results in different results. For example, some make targets may not provide
DESTDIR
support and instead require
install_root
usage. The same for
tooldir
,
prefix
and other similar arguments. Sometimes providing parameters as arguments instead of environment variables, e.g
./configure CC=arm-elf-gcc
instead of
CC=arm-elf-gcc ./configure
and vice versa may result in different outcomes (often caused by recursive self-invocation of configure/make).
See also
https://wiki.osdev.org/GCC_Cross-Compiler