Outils pour utilisateurs

Outils du site


tuto:linux:tuto_compilation

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.c
#include <stdio.h>
 
void boo(void)
{
    puts("Hello, I'm a shared library : boo");
}
boo.h
#ifndef boo_h__
#define boo_h__
 
extern void boo(void);
 
#endif  // boo_h__
  • Librairie foo.c :
foo.c
#include <stdio.h>
 
void foo(void)
{
    puts("Hello, I'm a shared library : foo");
}
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 :

tuto/linux/tuto_compilation.txt · Dernière modification : 2013/06/08 17:19 de root