|
Construction d'un cross compilateur GNU
Benoît PAPILLAULT, 08/02/2005
Introduction
Un cross compilateur est comme un compilateur normal. Il prend en
entrée un code source et produit en sortie un binaire exécutable. La
seule différence est que le binaire résultant ne peut pas être exécuté
sur la même machine. Par exemple, sur une machine x86, vous pouvez
cross compiler des exécutables pour un processeur PowerPC®.
Ce document n'est pas un n-iéme document sur comment construire un
cross compilateur. Il y a déjà des documents sur ce sujet, allez voir
la section Références. Son but est d'expliquer quelles sont les étapes
requises and comment cela doit fonctionner dans un monde idéal. Nous
ne parlerons pas de patchs ici (ou juste pour référence). Bien sûr,
LES INTRUCTIONS FOURNIES ICI NE FONCTIONNENT PAS.
Versions utilisées
-
linux-libc-headers-2.6.8.1
-
binutils-2.15
-
glibc-2.3.4
-
glibc-linuxthreads-2.3.4
-
gcc-core-3.4.3
-
gcc-g++-3.4.3
-
tar-1.15.1
Etapes de construction
Dans ces explications, nous allons essayer de construire un cross
compilateur PowerPC® (powerpc-unknown-linux-gnu) sur une machine x86
(i686-pc-linux-gnu). Nous allons essayer de construire un chroot
PowerPC® dans un répertoire nommé $SYSROOT
(/opt/powerpc-unknown-linux-gnu-root ici) et un cross
compilateur PowerPC® dans un autre répertoire nommé
$PREFIX (/opt/powerpc-unknown-linux-gnu-gcc
ici).
-
$BUILD sera le système de compilation, i.e. le système
sur lequel nous allons compilé, ici i686-pc-linux-gnu
-
$HOST sera le système hôte, i.e. le système sur lequel
nous allons exécuter les exécutables produits, ici
powerpc-unknown-linux-gnu
- Installation des en-têtes du noyau Linux®
Les en-têtes du noyau Linux® sont nécessaires pour compiler la
glibc. Cependant, nous avons besoin des mêmes en-têtes que celles qui
seraient sur le système hôte. Par exemple, le lien symbolique
asm doit pointer vers le répertoire approprié. Une autre
façon de régler cette situation et qui est nécessaire sur un système
multi-arch est d'avoir des en-têtes du noyau Linux® multi-arch.
Comme nous utilisons déjà des en-têtes du noyau Linux® multi-arch,
cette étape est une simple copie de répertoire.
mkdir -p $SYSROOT/usr/include &&
cp -a /usr/include/asm* /usr/include/linux $SYSROOT/usr/include
- Installation de binutils
binutils fournis deux outils importants : l'assembleur GNU et
l'éditeur de liens GNU qui sont tout les deux utilisés comme
backend du compilateur C GNU. Nous avons ici besoin de cross
binutils, i.e. un assembleur GNU et un éditeur de liens GNU qui seront
exécutés sur le système de compilation et qui produiront des binaires
corrects pour le système hôte.
L'option --with-sysroot est assez importante. Elle sera
codée en dur dans l'exécutable résultant, i.e. $HOST-ld. Cette option
est utilisée au moment de l'exécution pour localiser les bibliothéques
lorsque le chemin de recherche des bibliothéques inclus un chemin
commençant par le signe =. C'est le cas pour les chemins de recherche
des bibliothéques par défaut, qui est :
=/usr/local/lib:=/lib:=/usr/lib. Ceci peut sembler assez
complexe de prime abord, mais cela permet aux bibliothéques d'être
trouvées par l'éditeur de liens comme si nous compilions sur le
système hôte lui-même.
tar jxf binutils-2.15.tar.bz2 &&
mkdir binutils-build &&
cd binutils-build &&
../binutils-2.15/configure --prefix=$PREFIX \
--target=$HOST \
--with-sysroot=$SYSROOT &&
make all &&
make install
- Installation des en-têtes glibc
Nous avons besoin des en-têtes glibc pour construire gcc. Nous avons
utilisé l'add-on linuxthreads au lieu de nptl car ce dernier ne
fonctionnait pas dans cette étape. Nous spécifions à la fois le
système de compilation et le système hôte sur la ligne de commande
configure pour forcer la cross compilation. La valeur de BUILD
peut-être déterminé en exécutant le script config.guess
dans les sources de binutils.
tar jxf glibc-2.3.4.tar.bz2 &&
(cd glibc-2.3.4 &&
tar jxf glibc-linuxthreads-2.3.4.tar.bz2) &&
mkdir glibc-build &&
cd glibc-build &&
../glibc-2.3.4/configure --prefix=/usr \
--build=$BUILD --host=$HOST \
--with-headers=$SYSROOT/usr/include \
--without-cvs --disable-profile --disable-debug --without-gd \
--enable-add-ons=linuxthreads --with-tls --without-__thread \
--enable-kernel=2.4 &&
make install-headers install_root=$SYSROOT
- Installation d'un premier gcc
Dans cet étape, nous pouvons compiler un premier cross compilateur. Il
ne sera pas capable de produire des bibliothéques dynamiques car les
bibliothéques dynamiques ont besoin des bibliothéques dynamiques de
glibc.
Comme pour binutils, l'option --with-sysroot est assez
importante aussi. Cette option sera utilisé au moment de l'exécution
pour gérer le chemin par défaut de recherche des en-têtes comme si
nous compilions sur le système hôte. Le chemin par défaut de recherche
des en-têtes est :
/usr/local/include:/usr/include. Quelques répertoires
internes à gcc peuvent également s'y ajouter
($PREFIX/lib/gcc/$HOST/3.4.3/include ici).
tar jxf gcc-core-3.4.3.tar.bz2 &&
mkdir gcc-build &&
cd gcc-build &&
../gcc-3.4.3/configure --prefix=$PREFIX \
--target=$HOST \
--with-sysroot=$SYSROOT --with-headers=$SYSROOT/usr/include \
--disable-threads --disable-shared --enable-language=c &&
make &&
make install
- Installation de glibc
Nous avons maintenant un premier cross compilateur/assembleur/éditeur
de liens. Nous allons l'utiliser pour construire une glibc hôte. Nous
avons besoin d'ajouter le répertoire correct à PATH afin que le script
configure trouve notre cross compilateur.
export PATH=$PREFIX/bin:$PATH &&
tar jxf glibc-2.3.4.tar.bz2 &&
(cd glibc-2.3.4 &&
tar jxf glibc-linuxthreads-2.3.4.tar.bz2) &&
../glibc-2.3.4/configure \
--prefix=/usr \
--build=$BUILD --host=$HOST \
--with-headers=$SYSROOT/usr/include \
--without-cvs --disable-profile --disable-debug --without-gd \
--enable-add-ons=linuxthreads --with-tls --without-__thread \
--enable-kernel=2.4 &&
make &&
make install install_root=$SYSROOT &&
- Installation de gcc
Maintenant que nous avons une glibc hôte, nous pouvons reconstruire
notre cross compilateur pour inclure le support du C++ (ceci requiert
la construction d'une bibliothéque dynamique et ne pouvait pas être
fait à une étape précédente).
tar jxf gcc-core-3.4.3.tar.bz2 &&
tar jxf gcc-g++-3.4.3.tar.bz2 &&
mkdir gcc-build &&
cd gcc-build &&
../gcc-3.4.3/configure --prefix=$PREFIX \
--target=$HOST \
--with-sysroot=$SYSROOT --with-headers=$SYSROOT/usr/include \
--enable-threads=posix --enable-languages=c,c++ &&
make &&
make install
Tests
- Un exemple simple: compilons Hello World!
Nous allons utilisé le programme C suivant pour tester si notre cross
compilateur fonctionne. C'est un programme trés simple.
int main()
{ printf("Hello World!\n"); return 0; }
Nous le compilons par:
$HOST-gcc -o main main.c
Nous pouvons maintenant le fichier main sur le système hôte et
l'exécuter!
- Un exemple plus complexe: compilons tar
Nous allons maintenant utiliser la syntaxe correcte de configure pour
activer la cross compilation. DESTDIR est l'argument correct à
utiliser pour make install avec tout les logiciels
utilisant automake, ce qui est le cas de tar.
tar zxvf tar-1.15.1.tar.gz &&
cd tar-1.15.1 &&
./configure --prefix=/usr --host=$HOST &&
make &&
make install DESTDIR=$SYSROOT
D'autres logiciels peuvent utiliser la même convention, même s'ils
n'utilisent pas automake. Si aucune convention n'a été
utilisé, nous pouvons utiliser make install
prefix=$SYSROOT/usr à la place, mais ceci ne fonctionnera pas
pour les chemins qui ont été passés sur la ligne de commande de
configure. Voici un exemple plus complexe que nous utiliserons dans ce
cas:
./configure --prefix=/usr \
--sysconfdir=/etc \
--localstatedir=/var \
--mandir="\${prefix}/share/man" \
--infodir="\${prefix}/share/info" &&
make &&
make install prefix="${SYSROOT}/usr" \
sysconfdir="${SYSROOT}/etc" \
localstatedir="${SYSROOT}/var"
Références
- Le site principal pour construire un cross compilateur GNU est http://kegel.com/crosstool/. Ce
site fournit un script sympa qui peut être utilisé pour produire un
cross compilateur qui marche. Ce script inclus aussi divers patchs qui
ont été collectés et qui s'appliquent automatiquement
-
Le manuel Autoconf 2.57 explique comme utiliser les options de
e
./configure pour activer correctement la cross
compilation. Les détails sont dans la
section 15.6.3.
-
Le manuel Autobook explique comment le cadre fournit par
autoconf/automake peut être utilisé pour simplifier la cross
compilation, surtout lorsque le logiciel a besoin de compiler des
outils qui s'exécuteront sur la machine de compilation. Les détails
sont dans la
section 26.4.6.2.
- Un script qui marche et qui implémente ce qui a été dit ici: mk-cross-gcc. It can also be used to build an
x86_64 bi-arch cross compiler (not described here).
- Un patch pour glibc-2.3.4 patch nécessaire au script précédent:
glibc-2.3.4-libeh-kludge.patch
Mentions légales
- Linux® est
une marque déposée de Linus Torvalds.
-
PowerPC® est une marque déposée d'International Business
Machines Corporation
|