Compilation croisée avec GCC 4 sous Windows pour Linux

Thibaut Cuvelier

Un guide de la compilation croisée avec GCC depuis Windows vers Linux.

N'hésitez pas à commenter cet article ! Commentez

- Titre : Compilation croisée avec GCC 4 sous Windows pour Linux

- Auteur : Thibaut Cuvelier

- Parution : 13 janvier 2009

- Mise à jour : 9 janvier 2011

- Licence : Copyright ® 2009 Thibaut Cuvelier. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- I-A. Remarque d'introduction

- I-B. Qu'est-ce qu'un compilateur ?

- I-C. Qu'est-ce qu'un compilateur croisé ?

- I-D. À propos du 64 bits

- I-E. Préparation de l'environnement

- I-F. La cible

- I-F-1. Qu'est-ce que la cible ?

- I-F-2. Trouver la cible

- I-G. Pourquoi y a-t-il si peu à compiler ?

- II. La compilation

- II-A. Les binutils

- II-B. GCC

- II-C. En cas d'énormes problèmes : la compilation de GCC 4.4.0 SVN

- II-D. Ça ne va toujours pas ?

- II-E. Bibliothèque standard

- II-E-1. GNU LibC

- II-E-2. Newlib

- II-E-3. µClibc

- II-E-4. µClibc++

- II-E-5. Apache StdCxx

- II-E-6. STLPort

- II-F. Devra-t-on recompiler toutes les bibliothèques ?

- III. Et les autres cibles ?

- IV. Divers

- IV-A. Remerciements

- IV-B. Voir aussi

I - Introduction

I-A - Remarque d'introduction

Cet article est la suite du guide de la compilation de GCC 4 sous Windows.
En effet, ne seront pas reprécisées ici toutes les options utilisées pour la configuration qui y ont déjà été présentées.

I-B - Qu'est-ce qu'un compilateur ?

Selon Wikipédia, un compilateur est un programme informatique qui traduit un langage, le langage source, en un autre, appelé le langage cible, en préservant la signification du texte source.

Je suppose qu'une version en français serait appréciée. En gros, un compilateur prend un fichier source dans un langage (disons, le C) et le convertit dans un autre langage (généralement, un langage assembleur, ou un langage machine) et le code produit fait la même chose que le code d'origine.

I-C - Qu'est-ce qu'un compilateur croisé ?

Selon Wikipédia toujours, un compilateur croisé est un programme capable de traduire un code source en code objet ayant un environnement d'exécution (architecture matérielle, système d'exploitation) différent de celui où la compilation est effectuée.

Dit autrement, le compilateur se lance sous un OS (Windows, dans le cas qui nous intéresse) et produit des exécutables qui se lancent sous un autre OS (Linux, ici).

I-D - À propos du 64 bits

Depuis quelque temps, un groupe s'est chargé de l'adaptation de MinGW pour un environnement 64 bits. À l'heure actuelle, seul l'AMD64 (aussi connu sous le nom de x86_64) est supporté (tous les processeurs 64 bits, à l'exception des Intel Itanium et Itanium 2).

Cependant, il n'est pas du tout supporté, ni par MinGW, ni par GCC, mais de nombreux programmes l'utilisent déjà sans problème majeur.

Pour ceux qui sont intéressés par ces possibilités, ou ceux qui en ont besoin, sachez que la première partie vous a appris à compiler GCC pour Win32, et que ce compilateur est obligatoire pour pouvoir compiler sereinement GCC pour Win64. Il serait possible de s'en passer, cependant, mais les warnings vont pleuvoir.

Un nouveau projet est né pour porter MinGW sous Windows 64 bits. Il s'agit de MinGW64. Ce projet est mis à jour beaucoup plus fréquemment que MinGW et propose même des binaires déjà prêts pour compiler depuis Win32, Win64, Cygwin et Lin64.

I-E - Préparation de l'environnement

Vous aurez besoin du compilateur GCC, de préférence, la même version que celle que vous allez compiler.
En effet, la partie compilation croisée des sources est plus dure à maintenir, et donc, moins facile à compiler. Facilitons donc la tâche et choisissons un compilateur qui accepte de compiler avec des sources qui acceptent d'être compilées.

Changez le fstab pour que /work/build soit un nouveau répertoire vide (par exemple, renommez l'ancien en /work/build-native, et créez un nouveau /work/build) et que /cross pointe vers un dossier vide.

Vérifiez que toutes les sources sont toujours accessibles via /work/src, et que le nouveau GCC est dans le path (/gcc), ainsi que MSYS (/mingw/msys ou /gcc/msys).

Vous pouvez vérifier que GCC est dans le path en tapant ces commandes :

gcc --version
g++ --version

Elles doivent retourner un message semblable à ceci :

gcc.exe (GCC) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ou :

g++.exe (GCC) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Faites bien attention à la version de GCC affichée : 4.3.2, vous êtes dans le bon ; 3.4.5, vérifiez que vous avez bien installé GCC dans sa version 4, pas la version stable disponible sur le site de MinGW !

I-F - La cible

I-F-1 - Qu'est-ce que la cible ?

La notion de cible n'est jamais utilisée seule. On lui adjoint aussi l'hôte (host) et le build.

Le build est la plateforme sur laquelle vous compilez (utilisez, de préférence, la valeur par défaut, sauf si le programme se trompe).

L'hôte est la plateforme sur laquelle l'exécutable que vous produisez à l'instant s'exécutera.

La cible est la plateforme sur laquelle s'exécuteront les exécutables produits par le programme que vous configurez.

I-F-2 - Trouver la cible

Dans le répertoire des sources des binutils, de GCC, de GMP ou de MPFR et utilisez la commande ci-dessous pour votre plateforme :

config.guess

Le code retourné est votre target, c'est-à-dire votre cible.

Pour canonicaliser un nom (rendre standard), utilisez une commande semblable :

config.sub i586-linux

Où i586 est votre architecture et linux votre OS.

I-G - Pourquoi y a-t-il si peu à compiler ?

En fait, quelques paquets sont tout à fait inutiles sous Linux : la Win32API et le runtime MinGW.
La première est la version MinGW de l'API Win32, qui n'existe pas sous Linux.
Le deuxième est la bibliothèque de base pour Windows uniquement, et une version Linux (minimaliste) est compilée en même temps que GCC, vu que cela rentre dans ses cordes (Windows n'étant pas prévu pour le support au début). Mais, vu que cette version est très minimaliste, nous devrons compiler une version exhaustive.

Ensuite, GMP et MPFR ne seront pas recompilés, vu que le compilateur en dispose déjà.

II - La compilation

II-A - Les binutils

Rendez-vous dans le dossier /work/build et créez-y un dossier binutils, entrez-y :

../../src/binutils/configure \
--prefix=/cross --target=i586-pc-linux-gnu \
--program-prefix="" \
--with-lib-path=/gcc/mingw32/lib:/gcc/lib:/usr/local/lib:/lib:/usr/lib \
--with-gcc --with-gnu-as --with-gnu-ld --disable-nls --disable-shared \
--disable-boostrap

Vous pouvez activer le support de GOLD, mais je ne l'ai pas testé.

N'oubliez surtout pas la dernière option, qui va empêcher GCC de se recompiler de lui-même, vu que Windows ne peut exécuter des exécutables Linux (ELF, a.out…).

La configuration peut sembler se bloquer pendant deux ou trois minutes au niveau de checking how to compare bootstrapped objects... cmp --ignore-initial=16 $$f1 $$f2.

Ceci n'est pas parfaitement normal dans le cas d'un compilateur natif, mais bien dans le cas d'un compilateur croisé. Attendez et ça ira…

make all
make install

II-B - GCC

Rendez-vous dans le dossier /work/build et créez-y un dossier gcc, entrez-y :

../../src/gcc/configure \
--prefix=/cross --target=i586-pc-linux-gnu \
--program-prefix="" \
--with-gcc --with-gnu-ld --with-gnu-as \
--disable-threads --disable-nls  \
--enable-languages=c,c++,ada,objc,treelang \
--disable-win32-registry --disable-shared --without-x \
--enable-interpreter --enable-libstdcxx-debug \
--with-gmp=/gcc --with-mpfr=/gcc --with-gomp \
--disable-boostrap

Le Fortran n'est pas supporté dans un compilateur croisé et sa compilation ne fonctionnera pas (sauf par GCC 4.4.0).

Les fils d'exécution ne sont plus activés : en compilation croisée, GCC requiert les POSIX Threads, qui ne sont, ni fournis, ni compilables sous Windows, à cause d'une implémentation POSIX très lacunaire (sauf par des compilateurs croisés stables, comme ceux que vous obtiendrez en fin d'article).

make all
make install

II-C - En cas d'énormes problèmes : la compilation de GCC 4.4.0 SVN

Si votre problème n'apparaît pas ici en bas, ou bien si aucune solution n'est disponible, essayez de passer à GCC 4.4.0.

N'oubliez pas ceci :

Quand un compilateur accepte un programme sans erreur du premier coup, le programme ne fournira pas le résultat attendu !
There's always one more bug. (Il y a toujours un problème supplémentaire.)
Des tests lents et méthodiques vous feront parvenir à un point où vous pourrez localiser le problème ou devenir fou. Peut-être les deux.
(extraits des lois de Murphy).

Vous devrez passer par le protocole SVN. Les informations nécessaires sont disponibles sur le site de GCC. Choisissez la branche trunk. Avant de configurer, resynchronisez. Avant de compiler, resynchronisez. À chaque erreur, resynchronisez (le guide pour GCC 4.3 peut être utile).

Chaque resynchronisation peut amener à une reconfiguration, partielle ou complète, ou à la suppression d'un patch (seulement si le fichier est modifié en amont).

Au niveau des aménagements du configure, ne pourrez compiler que le C et le C++, les autres nécessitant bien beaucoup d'aménagements, impossibles à réaliser, selon les différentes communautés.

../../src/gcc/configure \
--prefix=/cross --target=i586-pc-linux-gnu \
--program-prefix="" \
--with-gcc --with-gnu-ld --with-gnu-as \
--disable-threads --disable-nls  \
--enable-languages=c,c++ \
--disable-win32-registry --disable-shared --without-x \
--enable-interpreter --enable-libstdcxx-debug \
--with-gmp=/gcc --with-mpfr=/gcc --with-gomp \
--disable-boostrap

Puis :

make all
make install

II-D - Ça ne va toujours pas ?

Après avoir patiemment essayé GCC 4.3.2 puis 4.4.0 SVN, vous n'avez toujours rien ? Changez de crèmerie ! Essayez GCC 3.4.6 (ou 3.4.5) !

Cependant, il est probable que le programme gen-modes.exe soit extrêmement lent à lancer, il produira un fichier de 2,5 Go (plus ou moins, on n'est plus à dix mébioctets près…).

Vous devriez aussi essayer cette version si vous avez un absolu besoin de stabilité pour votre compilateur. En effet, la branche 3 a été commencée en 2001 : en la choisissant, vous vous ouvrez à huit années de débogage ! Tandis que la branche 4 est encore plus récente : 2005, encore plus de bugs (en théorie).

Si tout ceci ne fonctionne toujours pas (oui, c'est possible et pas forcément improbable), essayez MinGW 4.3.0 (GCC, mais porté sur Win32). Les commandes restent (comme toujours) inchangées, mais vous devez désactiver le support de l'OpenMP.

../../src/gcc/configure \
--prefix=/cross --target=i586-pc-linux-gnu \
--program-prefix="" \
--with-gcc --with-gnu-ld --with-gnu-as \
--disable-threads --disable-nls  \
--enable-languages=c,c++ \
--disable-win32-registry --disable-shared --without-x \
--enable-interpreter \
--with-gmp=/gcc --with-mpfr=/gcc \
--disable-boostrap --disable-libssp

Suivi de :

make all
make install

II-E - Bibliothèque standard

Que contient une bibliothèque standard ? Simplement, toutes les fonctions standard du C. Le C++ est désormais intégré à G++ via libstdc++-v3.

Commencez par créer un nouveau répertoire libc dans votre répertoire /work/build et extrayez dans son homologue source la dernière version de la GNU LibC.

Si vous effectuez une compilation croisée vers une plateforme embarquée, préférez une des bibliothèques standard suivantes, plus légères et plus optimisées pour ces plateformes : dietlibc, µcLibC, Contiki, NewLib, KLibC [ftp://ftp.kernel.org/pub/linux/libs/klibc/].

Préférez KLibC pour une utilisation dans un initramfs et µLibC pour les autres cas. Les autres bibliothèques, non présentées, sont nettement moins utilisées.

Au lieu d'extraire l'archive précisée en haut, utilisez celle de la bibliothèque que vous voulez utiliser. Sauf exception, toutes les bibliothèques se compilent avec les mêmes commandes, seule la configuration peut changer.

II-E-1 - GNU LibC

Pour configurer, utilisez cette commande du nouveau /work/build/libc.

/work/src/libc/configure \
--prefix=/cross \
--with-binutils=/cross \
--host=i586-pc-linux-gnu \
--enable-versioning

Puis compilez et installez d'un simple

make all && make install

II-E-2 - Newlib

/work/src/libc/configure --prefix=/cross --host=i586-pc-linux-gnu

La configuration peut prendre autant de temps que la compilation de GCC !

II-E-3 - µClibc

Extrayez directement dans le répertoire de compilation : la bibliothèque ne supporte pas autre chose.

Pour configurer :

make menuconfig || make config || make oldconfig

Ici, sélectionnez toutes les options (pour une utilisation pour un système non embarqué), et précisez l'hôte : i586-pc-linux-gnu. Pour l'embarqué, sélectionnez les options nécessaires et uniquement celles-là.

II-E-4 - µClibc++

make menuconfig
make
make install

Choisissez les options par défaut, elles conviennent presque toujours.

II-E-5 - Apache StdCxx

cd /work/src/stdcxx
make \
BUILDDIR=/work/build/stccxx \
BUILDTYPE=12d \
CONFIG=gcc.config
make install \
PREFIX=/cross

II-E-6 - STLPort

configure --prefix=/cross \
--target=i586-pc-linux-gnu

II-F - Devra-t-on recompiler toutes les bibliothèques ?

Vous pourrez directement réutiliser toutes les bibliothèques construites pour Linux, tant que le compilateur qui s'en est occupé utilise le format ELF et est en 32 bits (ou bien, correspond aux choix réalisés sur la cible).

Il est même recommandé d'utiliser ces bibliothèques compilées avec un compilateur natif, car celui-ci produit donc des binaires de meilleure qualité que le second, mais il n'est pas toujours utilisable (sur une console de jeu portable, par exemple, il est très dur de lancer un shell pour compiler quoi que ce soit…).

III - Et les autres cibles ?

Il suffit de changer le --target (voir ci-dessous). Si vous disposez d'un OS 64 bits, vous pouvez même réactiver les bootstraps (enlever le commutateur --disable-bootstrap) pour la compilation du compilateur croisé vers 64 bits.

Changer le paramètre de --target en…

- i386-pc-mingw32 pour Windows 32 bits

- x86_64-mingw32 pour Windows x64 (hors Intel Xeon et Xeon 2)

- i686-pc-mingw32 pour une console XboX

- arm-unknown-wince pour un PDA sous Windows CE

- i586-pc-linux-gnu pour Linux 32 bits (format ELF, le plus répandu)

- i586-pc-elf pour tout OS supportant le ELF (dont GNU Hurd)

- i586-linux-coff pour Linux 32 bits (format COFF)

- i586-pc-coff pour tout OS supportant le COFF

- i586-linux-aout pour Linux 32 bits (format A.OUT)

- i586-pc-aout pour tout OS supportant le A.OUT

- x86_64-pc-linux-gnu pour Linux x64 (format ELF, le plus répandu)

- x86_64-pc-elf pour tout OS 64 bits supportant le ELF (dont GNU Hurd)

- x86_64-linux-coff pour Linux 64 bits (format COFF)

- x86_64-pc-coff pour tout OS 64 bits supportant le COFF

- x86_64-linux-aout pour Linux 64 bits (format A.OUT)

- x86_64-pc-aout pour tout OS 64 bits supportant le A.OUT

- arm-unknown-linux-gnu pour tout Linux pour PDA

- powerpc-apple-macos pour MacOS X 32 bits sur processeur PowerPC

- i686-apple-macos pour MacOS X 32 bits sur processeur Intel

- x86_64-pc-macos pour MacOS X 64 bits

- i586-pc-bsd pour tout dérivé BSD 32 bits

- x86_64-pc-bsd pour tout dérivé BSD 64 bits

- i586-pc-netbsd pour un NetBSD 32 bits

- x86_64-pc-netbsd pour un NetBSD 64 bits

- i586-pc-openbsd pour un OpenBSD 32 bits

- x86_64-pc-openbsd pour un OpenBSD 64 bits

- i586-pc-freebsd pour un FreeBSD 32 bits

- x86_64-pc-free-bsd pour un FreeBSD 32 bits

- i586-pc-dragonflybsd pour un DragonflyBSD 32 bits

- x86_64-pc-dragonflybsd pour un DragonflyBSD 64 bits

- i586-pc-solaris2 pour un Solaris ou OpenSolaris 31 bits sur processeur x86

- x86_64-pc-solaris2 pour un Solaris ou OpenSolaris 64 bits sur processeur x86_64

Évidemment, il existe des myriades d'autres possibilités. Pour les connaître, utilisez le script config.sub, en lui passant comme paramètre unique quelque chose de la forme processeur-OS-version, la version étant peu utilisée.

IV - Divers

IV-A - Remerciements

Un très grand merci à RideKick pour sa relecture attentive !

IV-B - Voir aussi

L'article Wikipedia sur le sujet (et la version hypra-allégée, mais en français)

Le bootstrapping sur Wikipedia.