Table des matières
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<dir> : Dossier des fichiers “include”
- -L<dir> : Dossier des librairies
- -l<lib> : 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=<DIR> : 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<thread> : spécifie le nombre de compilation simultanées. Conseillé de mettre nombre total de thread+1
- -l<load> : 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 :
- boo.h
#ifndef boo_h__ #define boo_h__ extern void boo(void); #endif // boo_h__
- Librairie foo.c :
- boo.h
#ifndef foo_h__ #define foo_h__ extern void foo(void); #endif // foo_h__
- Programme principal avec appel au 2 librairies :
- main.c
#include <stdio.h> #include "foo.h" #include "boo.h" int main(void) { puts("This is a shared library test..."); foo(); boo(); return 0; }
- Compilation en shared :
- compile1.sh
#!/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) :
- compile2.sh
#!/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 :
- compile3.sh
#!/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 !
- compile4.sh
#!/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 :
- compile5.sh
#!/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 :
- compile6.sh
#!/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 :
- ELF Statifier : mini tuto.