====== Compilation ====== ===== Environnement ===== Varibles d'environnement : * **CC** : Compilateur C (gcc, icc...) * **CXX** : Idem que CC mais pour le C++ (export CXX=$CC) * **CFLAGS** : Ce paramétrage a en général pour but d'optimiser ou déboguer le code C (CFLAGS=" -march=native -mtune=native -O3 -pipe") * **CXXFLAGS** : Idem pour le C++ (export CXXFLAGS=$CFLAGS) * **LDFLAGS** : Permet de préciser les répertoires où se trouvent les librairies (*.so) et include(*.h) (LDFLAGS=" -I/home/include -L/home/lib -lX11") ./configure CC=gcc CFLAGS=-O3 LDFLAGS=-lposix ==== Options de compilation de gcc/g++ ==== Il existe énormément d'options de compilation, nous allons en détailler quelques unes. * **-O0 à -O3** : optimisation * **-march=native / -mtune=native** : produit du code optimisé pour notre processeur. Attention le code ne sera pas lisible sur tous les ordinateurs. * **-pipe** : N'agit pas sur le code mais améliore la vitesse de compilation en passant par un pipe * **-I** : Dossier des fichiers "include" * **-L** : Dossier des librairies * **-l** : Link une librairie au binaire générée. Attention une librarie doit commencer par "lib" et nous ne précisons que ce qui suit. Par exemple je veux linker la librairie libgigix.so : "-lgigix" * **-Wl,-rpath=** : permet de spécifier en dur dans le binaire (ou moment du linkage) où il doit chercher sa librairie. Cela permet notemment de se passer de lavariable "LD_LIBRARY_PATH". * **-static** : compile un binaire static sans plus aucune dépendance avec des librairies du système * **-shared** : compile une librairie de type ".so" ==== Options de make ==== * **-j** : spécifie le nombre de compilation simultanées. Conseillé de mettre nombre total de thread+1 * **-l** : spécifie le load à ne pas dépasser lors de la compilation. Conseillé de mettre le nombre total de thread. * **make clean** : Si implémenté dans le Makefile, fait le ménage dans la compilation (effacement des objets .o, fichiers temporaires...) * **make distclean** : Si implémenté dans le Makefile, fait le ménage comme dans le make clean mais efface également les fichiers Makefile. Donc obligé de relancé un ./configure pour regénérer les Makefile ==== Mode de compilation ==== Il existe 2 modes de compilation : * statique en faisant appel a une librairie d'extension //.a// * dynamique ne faisant appel a une librairie d'extension //.so// A noter qu'il est possible d'obtenir à partir d'une librairie dynamique une librairie statique comme nous le verrons dans les exemples en bas de page. ==== Exemples ==== Prenons une exemple tout bête, fichier qui affiche tu texte via 2 fonctions incluses dans 2 librairies différentes. * Librairie //boo.c// : #include void boo(void) { puts("Hello, I'm a shared library : boo"); } #ifndef boo_h__ #define boo_h__ extern void boo(void); #endif // boo_h__ * Librairie //foo.c// : #include void foo(void) { puts("Hello, I'm a shared library : foo"); } #ifndef foo_h__ #define foo_h__ extern void foo(void); #endif // foo_h__ * Programme principal avec appel au 2 librairies : #include #include "foo.h" #include "boo.h" int main(void) { puts("This is a shared library test..."); foo(); boo(); return 0; } * Compilation en shared : #!/bin/bash gcc -c -Wall -Werror -fpic foo.c gcc -shared -o libfoo.so foo.o gcc -c -Wall -Werror -fpic boo.c gcc -shared -o libboo.so boo.o gcc -L. -Wall -o test main.c -lfoo -lboo export LD_LIBRARY_PATH=. ./test ldd test Résultat : root@ks305337:~/compile# ./compile1.sh This is a shared library test... Hello, I'm a shared library : foo Hello, I'm a shared library : boo linux-vdso.so.1 => (0x00007fffd5dfe000) libfoo.so => /root/compile/libfoo.so (0x00007f4521e50000) libboo.so => /root/compile/libboo.so (0x00007f4521c4f000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f45218ba000) /lib64/ld-linux-x86-64.so.2 (0x00007f4522053000) * Compilation en shared avec la librairie boo directement inclue en statique dans le binaire (noter l'utilisation du binaire ar pour obtenir un fichier archive .a à partir d'une librairie.so) : #!/bin/bash gcc -c -Wall -Werror -fpic foo.c gcc -shared -o libfoo.so foo.o gcc -c -Wall -Werror -fpic boo.c gcc -shared -o libboo.so boo.o ar rcs libboo.a boo.o gcc -L. -Wall -o test main.c -lfoo ./libboo.a export LD_LIBRARY_PATH=. ./test ldd test root@ks305337:~/compile# ./compile2.sh This is a shared library test... Hello, I'm a shared library : foo Hello, I'm a shared library : boo linux-vdso.so.1 => (0x00007fff757fe000) libfoo.so => ./libfoo.so (0x00007ffa5a8f6000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffa5a562000) /lib64/ld-linux-x86-64.so.2 (0x00007ffa5aaf9000) * Compilation en shared avec les 2 librairies en statique : #!/bin/bash gcc -c -Wall -Werror -fpic foo.c gcc -shared -o libfoo.so foo.o ar rcs libfoo.a foo.o gcc -c -Wall -Werror -fpic boo.c gcc -shared -o libboo.so boo.o ar rcs libboo.a boo.o gcc -L. -Wall -o test main.c ./libfoo.a ./libboo.a export LD_LIBRARY_PATH=. ./test ldd test root@ks305337:~/compile# ./compile3.sh This is a shared library test... Hello, I'm a shared library : foo Hello, I'm a shared library : boo linux-vdso.so.1 => (0x00007fff76e7d000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fabfe74f000) /lib64/ld-linux-x86-64.so.2 (0x00007fabfeae5000) * En dynamique, mais en forçant automatiquement le linker (sans LD_LIBRARY_PATH) à chercher les librairies dans un répertoire : Noter que j'ai enlever la variable LD_LIBRARY_PATH avant l’exécution du programme ! #!/bin/bash gcc -c -Wall -Werror -fpic foo.c gcc -shared -o libfoo.so foo.o gcc -c -Wall -Werror -fpic boo.c gcc -shared -o libboo.so boo.o gcc -Wl,-rpath=/root/compile -L. -Wall -o test main.c -lfoo -lboo ./test root@ks305337:~/compile# ./compile4.sh This is a shared library test... Hello, I'm a shared library : foo Hello, I'm a shared library : boo linux-vdso.so.1 => (0x00007fff13be7000) libfoo.so => /root/compile/libfoo.so (0x00007fca9e569000) libboo.so => /root/compile/libboo.so (0x00007fca9e368000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fca9dfd3000) /lib64/ld-linux-x86-64.so.2 (0x00007fca9e76c000) Dans l'exemple 1, les librairies n'étaient pas automatiquement trouvées, ce qui n'est plus le cas maintenant : root@ks305337:~/compile# ldd test linux-vdso.so.1 => (0x00007fff79eda000) libfoo.so => not found libboo.so => not found libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f67d24f9000) /lib64/ld-linux-x86-64.so.2 (0x00007f67d2890000) * En statique : #!/bin/bash gcc -c -Wall -Werror -fpic foo.c gcc -shared -o libfoo.so foo.o ar rcs libfoo.a foo.o gcc -c -Wall -Werror -fpic boo.c gcc -shared -o libboo.so boo.o ar rcs libboo.a boo.o gcc -static -L. -Wall -o test main.c ./libfoo.a ./libboo.a export LD_LIBRARY_PATH=. ./test ldd test root@ks305337:~/compile# ./compile5.sh This is a shared library test... Hello, I'm a shared library : foo Hello, I'm a shared library : boo n'est pas un exécutable dynamique * Include les 2 librairies dans une seule : #!/bin/bash gcc -c -Wall -Werror -fpic foo.c gcc -c -Wall -Werror -fpic boo.c gcc -shared -o libgigix.so boo.o foo.o gcc -L. -Wall -o test main.c -lgigix export LD_LIBRARY_PATH=/root/compile ./test ldd test root@ks305337:~/compile# ./6.sh This is a shared library test... Hello, I'm a shared library : foo Hello, I'm a shared library : boo linux-vdso.so.1 => (0x00007fff2e7fe000) libgigix.so => /root/compile/libgigix.so (0x00007fcd2fd37000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcd2f9a3000) /lib64/ld-linux-x86-64.so.2 (0x00007fcd2ff3a000) === Compilation statique === Pour compiler un programme en static (par exemple python) : ./configure LDFLAGS=" -static -Wl,-static" CFLAGS=" -static-libgcc -static -march=native -mtune=native -O3 -pipe -fPIC" CC=gcc-4.8 --enable-shared=no Pour transformer un binaire dynamique en statique, il existe des outils comme : * [[http://sourceforge.net/projects/statifier/files/|ELF Statifier]] : mini [[http://archive09.linux.com/feature/150677|tuto]]. * [[http://www.magicermine.com/trial.html|Ermine]] : mini [[http://nathanaaron.wordpress.com/2011/08/31/building-a-portable-executable-on-linux/|tuto]]