Difference between revisions of "Cross-compiling tools package guidelines"

From ArchWiki
Jump to: navigation, search
(Hows and whys)
m (clean up a bit)
(15 intermediate revisions by 8 users not shown)
Line 1: Line 1:
== Important ==
+
[[Category:Package development]]
This page describes a proposal, not an accepted approach!
+
{{Package Guidelines}}
  
== Package Naming ==
+
__TOC__
The package name shall be prefixed with the word '''cross-''', followed by architecture name and the package name itself shall come at the end.
+
  
Thus, cross GCC for MIPS shall be '''cross-mips-gcc'''.
+
{{Tip|As alternative for creation of cross-compiler packages you could use [http://crosstool-ng.org/  crosstool-ng] and create you own toolchain in fully automated way. crosstool-ng can be find on {{AUR|crosstool-ng}}}}.
  
 +
== Important note ==
 +
This page describes new way of doing things, inspired by follwing packages in {{Ic|[community]}}:
 +
*{{Pkg|mingw32-gcc}} and other packages from {{Ic|mingw32-*}} series
 +
*{{Pkg|arm-elf-gcc-base}} and other packages from {{Ic|arm-elf-*}} series
 +
*{{Pkg|arm-wince-cegcc-gcc}} and other packages from {{Ic|arm-wince-cegcc-*}} series
 +
 +
== Version compatibility ==
 +
{{Warning|Using incompatible version of packages for toolchain compilation leads to inevitable failures. By default consider '''all''' versions incompatible.}}
 +
 +
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 {{Ic|--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 it's architecture-specific forks) most probably can be made to work together;
 +
*Software documentation: all GNU software have {{Ic|README}} and {{Ic|NEWS}} files, documenting things like minimal required versions of dependencies;
 +
*Other distributions: they too do cross-compilation
 +
**Gentoo crossdev [http://en.gentoo-wiki.com/wiki/Crossdev#Known%20Workingn%20Architecturen%20Matrix lists] some working combinations.
 +
*http://cross-lfs.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 {{Pkg|linux-api-headers}} as reference and pass {{Ic|1=ARCH=''target-architecture''}} to '''make'''
 +
## create libc headers package (process for Glibc is described [http://sources.redhat.com/ml/crossgcc/2003-06/msg00170.html 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 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
 +
 +
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 "clone" of Arch Linux system with same versions of kernel and glibc, you can skip building headers and pass {{Ic|1=--with-build-sysroot=/}} to {{Ic|configure}}.}}
 +
 +
== Package naming ==
 +
The package name shall '''not''' be prefixed with the word {{Ic|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 [http://wiki.debian.org/Multiarch/Tuples GNU triplet] without vendor field or with "unknown" in vendor field; example: {{Ic|arm-linux-gneabihf-gcc}}. If shorter naming convention exists (e.g. {{Ic|mips-gcc}}), it may be used, but this is not recommended.
  
 
== File Placement ==
 
== File Placement ==
To prevent file conflicts, place everything into '''/usr/lib/cross-<arch>'''. 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).
+
Latest versions of gcc and binutils use non-conflicting paths for sysroot and libraries. Executables shall be placed into {{Ic|/usr/bin/}}, to prevent conflicts here, prefix all of them with architecture name.
 +
 
 +
Typically, {{Ic|./configure}} would have at least following parameters:
  
Typically, <code>./configure</code> would have at least following parameters:
+
{{Bc|1=
<pre>_target=<your-target> # e.g. i686-pc-mingw32
+
_target=<your-target> # e.g. i686-pc-mingw32
 
_sysroot=/usr/lib/${_target}
 
_sysroot=/usr/lib/${_target}
 
...
 
...
 
./configure \
 
./configure \
 
     --prefix=${_sysroot} --sysroot=${_sysroot} \
 
     --prefix=${_sysroot} --sysroot=${_sysroot} \
     --bindir=/usr/bin</pre>
+
     --bindir=/usr/bin
 +
}}
  
 
== Example ==
 
== Example ==
This is PKGBUILD for GCC for MIPS.
+
This is PKGBUILD for binutils for MinGW.
 
Things worth noticing are:
 
Things worth noticing are:
*manually specifying where to find the '''as''' and '''ld''' binaries
+
*specifying root directory of the cross-environment
*usage of <code>${_pkgname}</code> and <code>${_target}</code> variables to make the code more readable
+
*usage of {{Ic|${_pkgname}}}, {{Ic|${_target}}} and {{Ic|${_sysroot}}} variables to make the code more readable
 
*removal of the duplicated/conflicting files
 
*removal of the duplicated/conflicting files
<pre># Contributor: Your name <your@email.somewhere.net>
+
 
pkgname=cross-mips-gcc
+
{{bc|<nowiki>
_pkgname=gcc
+
# Maintainer: Allan McRae <allan@archlinux.org>
pkgver=4.3.2
+
 
pkgrel=2
+
# cross toolchain build order: binutils, headers, gcc (pass 1), w32api, mingwrt, gcc (pass 2)
pkgdesc="The GNU Compiler Collection for the MIPS architecture"
+
 
url="http://www.gnu.org/software/binutils/"
+
_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')
 
arch=('i686' 'x86_64')
 +
url="http://www.gnu.org/software/binutils/"
 
license=('GPL')
 
license=('GPL')
depends=('mpfr' 'sh' 'cross-mips-binutils')
+
depends=('glibc>=2.10.1' 'zlib')
options=('!ccache' '!distcc' '!emptydirs' '!libtool' '!strip')
+
options=('!libtool' '!distcc' '!ccache')
source=("ftp://ftp.gnu.org/gnu/gcc/gcc-${pkgver}/${_pkgname}-core-${pkgver}.tar.bz2")
+
source=(http://ftp.gnu.org/gnu/${_pkgname}/${_pkgname}-${pkgver}.tar.bz2)
md5sums=('dd8048b43d3d4e5595bcade47b9144c6')
+
md5sums=('09a8c5821a2dfdbb20665bc0bd680791')
_target="mipsel-linux-gnu"
+
  
 
build() {
 
build() {
cd ${srcdir}/${_pkgname}-${pkgver}
+
  cd ${srcdir}/${_pkgname}-${pkgver}
+
  mkdir binutils-build && cd binutils-build
./configure \
+
"--prefix=/usr" \
+
"--libexecdir=/usr/lib" \
+
"--program-prefix=${_target}-" \
+
"--target=${_target}" \
+
"--mandir=/usr/share/man" \
+
--without-headers \
+
--with-gnu-as --with-gnu-ld \
+
--with-as=/usr/bin/${_target}-as \
+
--with-ld=/usr/bin/${_target}-ld \
+
--disable-nls --disable-multilib --disable-shared \
+
--disable-libgcj --disable-threads --disable-tls \
+
--enable-languages=c || return 1
+
+
make all-gcc || return 1
+
+
make DESTDIR=${pkgdir} install-gcc || return 1
+
+
msg "Removing duplicit files..."
+
# remove these files as they are already in the system
+
# (with native gcc)
+
rm -Rf ${pkgdir}/usr/info
+
rm -f ${pkgdir}/usr/lib/libiberty.a
+
rm -Rf ${pkgdir}/usr/share/man
+
rm -Rf ${pkgdir}/usr/share/info
+
  
msg "Creating out-of-path executables..."
+
  ../configure --prefix=${_sysroot} --bindir=/usr/bin \
# symlink executables to single directory with no-arch-prefix name
+
    --with-sysroot=${_sysroot} \
mkdir -p ${pkgdir}/usr/bin/cross/${_target}/;
+
    --build=$CHOST --host=$CHOST --target=${_target} \
cd ${pkgdir}/usr/bin/cross/${_target}/;
+
    --with-gcc --with-gnu-as --with-gnu-ld \
for bin in ${pkgdir}/usr/bin/${_target}-*; do
+
    --enable-shared --without-included-gettext \
bbin=`basename "$bin"`;
+
    --disable-nls --disable-debug --disable-win32-registry
ln -s "/usr/bin/${bbin}" `echo "$bbin" | sed "s#^${_target}-##"`;
+
  make
done
+
  make DESTDIR=${pkgdir}/ install
}</pre>
+
 
 +
  # clean-up cross compiler root
 +
  rm -r ${pkgdir}/${_sysroot}/{info,man}
 +
}
 +
</nowiki>}}
  
 +
{{Note|During cross-toolchain building always execute {{Ic|configure}} and '''make''' commands from dedicated directory (so-called out-of-tree compilation) and remove whole {{Ic|src}} directory after slightest change in [[PKGBUILD]].}}
  
 
== Hows and whys ==
 
== Hows and whys ==
Why not installing into ''/opt''? There would be no need for fooling around with non-standard executable namings etc.?
+
{{FAQ|question=
: Two reasons:
+
Why not installing into {{Ic|/opt}}?
:: First, according to File Hierarchy Standard, these files just belong somwhere to ''/usr''. Period.
+
|answer=
:: Second, installing into ''/opt'' is a last meassure when there is no other option.
+
Two reasons:
 +
#First, according to File Hierarchy Standard, these files just belong somewhere to {{Ic|/usr}}. Period.
 +
#Second, installing into {{Ic|/opt}} is a last measure when there is no other option.
 +
}}
  
 +
{{FAQ|question=
 
What is that ''out-of-path executables'' thing?
 
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 <code>$PATH</code> to use "our" executables first is a very quick solution.
+
|answer=
: You would then run <code>PATH=/usr/bin/cross/<i>arch</i>/:$PATH make</code> instead of <code>make</code>.
+
This weird thing allows easier cross-compiling. Sometimes, project Makefiles do not use {{Ic|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 {{Ic|$PATH}} to use "our" executables first is a very quick solution. You would then run {{Ic|1=PATH=/usr/''arch''/bin/:$PATH make}} instead of {{Ic|make}}.
 +
}}
 +
 
 +
 
 +
== Troubleshooting ==
 +
{{FAQ|question=
 +
What to do if compilation fails without clear message?
 +
|answer=
 +
For error, occurred during running {{Ic|configure}}, read {{Ic|$srcdir/''pkgname''-build/config.log}}. For error, occurred during compilation, scroll console log up or search for word "error".
 +
}}
 +
 
 +
{{FAQ|question=
 +
What does this error [error message] means?
 +
|answer=
 +
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 {{Ic|1=export CFLAGS=""}} to your {{Ic|build()}} function (see [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25672 bug 25672] in GCC Bugzilla).
 +
* Some {{Ic|--prefix}}/{{Ic|--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.
 +
}}
 +
 
 +
{{FAQ|question=
 +
Why do files get installed in wrong places?
 +
|answer=
 +
Various methods of running generic {{Ic|make install}} line results in different results. For example, some make targets may not provide {{Ic|DESTDIR}} support and instead require {{Ic|install_root}} usage. The same for {{Ic|tooldir}}, {{Ic|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 ==
 +
http://wiki.osdev.org/GCC_Cross-Compiler

Revision as of 01:16, 1 September 2012

Template:Package Guidelines

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 find on crosstool-ngAUR
.

Important note

This page describes new way of doing things, inspired by follwing packages in [community]:

Version compatibility

Warning: Using incompatible version of packages for toolchain compilation leads to inevitable failures. By default consider all versions incompatible.

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 (or it's 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
    • Gentoo crossdev lists some working combinations.
  • http://cross-lfs.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:

  1. binutils: Build a cross-binutils, which links and processes for the target architecture
  2. headers: Install a set of C library and kernel headers for the target architecture
    1. use linux-api-headers as reference and pass ARCH=target-architecture to make
    2. create libc headers package (process for Glibc is described here)
  3. 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).
  4. libc: Build the cross-compiled C library (using the stage 1 cross compiler).
  5. 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 "clone" of Arch Linux system with 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-gneabihf-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> # 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 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

Template:FAQ

Template:FAQ


Troubleshooting

Template:FAQ

Template:FAQ

Template:FAQ

See also

http://wiki.osdev.org/GCC_Cross-Compiler