Introduction aux Makefiles
Makefile
Un makefile est tout simplement un fichier de configuration (script) contenant des instructions qui sont lus et executées par un programme de type make (gmake,…).
A quoi sert il ?
Il permet de construire automatiquement des executable (tres souvent) , des libraries, des architectures de dossier ou des actions diverses . En gros , enormement de choses .
Guillaume> Pourquoi ne pas juste ecrire un script shell, python pour le faire ?
La principale difference entre une makefile et un script normal est que les instructions d’un makefile ne sont executées que si necessaires, c.a.d qu’une action (règle) qui a deja été accomplie, ne sera plus reexecutée.
Comment fonctionne t-il ?
Il fonctionne tout simplement par verification de statisfactions de dépendances. Je m’explique par l’algorithme qui suit : Pour faire mon tea (avec l’accent british s’il vous plait!!) j’ai généralement besoin d’une cup , de l’eau et un tea bag (twisted mind, get away!!!). On supposera qu’on a déja notre tasse.
Ai-je de l’eau chaude ?
O : on passe a l’étape 2
N : Sais-je comment me procurer de l’eau ?
O : Satisfait -> étape 2 N : impossible de creer de l'eau, je renvoie une erreur et je sorsAi-je du thé ?
O : alors étape 3
N : Sais-je comment me procurer du thé ?
O : je me procure du thé puis je vais à l'étape suivante N : jre renvoie une erreurJe fais mon thé grace à mon eau et mon sac de thé
A la prochaine execution, on n’aura plus besoin de se procurer de l’eau par exemple, dans le cas ou la dependance est toujours satisfaite .
Comment ecrire un Makefile ?
Context :
Jimmy Mcmillan veut écrire 2 fonctions d’affichage pour son party. Etant le super programmeur de son party, il se lance :
un fichier my_putchar.h
#ifndef __my_putchar__
#define __my_putchar__
void my_putchar(char c);
#endif
un fichier my_putchar.c
#include <my_putchar.h>
void my_putchar(char c){
write(1,&c,1);
}
un fichier my_putstr.h
#ifndef __my_putstr__
#define __my_putstr__
void my_putstr(char *s);
#endif
un fichier my_putstr.c
#include <my_putchar.h>
#include <my_putstr.h>
void my_putstr(char *s){
while(*s){
my_putchar(*s);
*s++ ;
}
}
un fichier main.c
#include<my_putchar.h>
#include <my_putstr.h>
int main(int argc, char **argv){
my_putchar('O');
my_putchar('m');
my_putchar('g');
my_putchar('!');
my_putchar('\n');
my_putstr("The Rent Is Damn Too High !!!\n");
return 0 ;
}
# ifndef __my_putchar__
jimmy@mcmillan:~$cc -Wall -c main.c my_putchar.c my_putstr.c
jimmy@mcmillan:~$ls *.o # pour lister les .o generes
jimmy@mcmillan:~$cc main.o my_putchar.o my_putstr.o -o my_exe #generation de l'executable
jimmy@mcmillan:~$./test
Omg!
The Rent Is Damn Too High !!!
jimmy@mcmillan:~$
Faut avouer que si son projet a plus de 10 fichiers sources, ça devient tres vite fastidieux de tout taper a la main. Alors pour palier à cela, il decide d’ecrire un makefile bien commenté.
notre makefile
CC = cc # le compliteur (e.g: g++, gcc, gccsense,...)
#Les sources ou fichiers cibles
SRC = my_putchar.c\
my_putstr.c\
main.c
CFLAGS = -Wall -W -I./
OBJ = $(SRC:.c=.o) # infference, les .o sont generés à partir des .c de manière implicite
EXE = my_exe
#Les differentes regles
#La 1ere regles est la premiere appelee, donc il est vivement conseille de definir **all** comme etant la premiere
all:$(EXE)
#On peut definir une regle avec le nom d'une variable
$(EXE):$($OBJ) #la regle $(EXE) depend de ($OBJ)
$(CC) $(OBJ) -o $(EXE) $(CFLAGS)
clean:
rm -rf *.o *~
fclean:clean
rm -rf $(EXE)
re:fclean all
NB: Respecter l’indentation, sinon make renverra une erreur.
jimmy@mcmillan:~$make
Appelle la regle all et genere tous les fichiers de dependances
jimmy@mcmillan:~$make my_exe
make: `my_exe' is up to date.
Appelle la regle my_exe qui dans notre makefile correspond a
$(EXE):$($OBJ) #la regle $(EXE) depend de ($OBJ)
$(CC) $(OBJ) -o $(EXE) $(CFLAGS)
Et oui !! Une regle peut avoir nom du contenu d’une variable. Vous avez surement remarque le message qui indique que la regle est deja satisfaite (^_~) .
Pour resumer, mcmillan a les dependances suivantes dans son makefile :
- all depend de exe
- exe depend de obj
- fclean depend de clean
- re depend de fclean puis all
Je vous conseille de lire ceci pour vous documenter sur les regles d’inference .
Voila, j’espere que ca vous aura permet d’ecrire des makefiles simplistes mais utiles.
