Josue Kouka

Josue Kouka

Code, Linux, and open source — one post at a time.

05 Feb 2013

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.

  1. 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 sors
    
  2. Ai-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 erreur
    
  3. Je 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.

Categories