---
title: Plus de Makefiles
date: 2021-03-03
---

# `make` avancé

## Rappel: utilité

- Automatiser le processus de conversion d'un type de fichier à un autre, en *gérant les dépendances*.
- Effectue la conversion des fichiers qui ont changé uniquement.
- Utilisé pour la compilation:
  - Création du code objet à partir des sources.
  - Création de l'exécutable à partir du code objet.
- Tout "gros" projet utilise `make` (pas uniquement en `C`).

# Utilisation de `make`

## `Makefile` simple

::::::::::::::  {.columns}
::: {.column width="60%"}

```bash
# Les commentaires commencent 
# par #

# exemple est la cible, example.o
# la dépendance
example: example.o
# ligne exécuté à l'appel de 
# `make` (`make example`)
    gcc -o example example.o 

# exemple.o est la cible, example.c 
# et example.h les dépendances
exmaple.o: exmaple.c example.h  
# ligne exécuté à l'appel de 
# `make example.o`
    gcc -c example.c 
```

:::
::: {.column width="40%"}

## Terminal

```bash
$ make
gcc -c example.c
gcc -o example example.o
```
:::
::::::::::::::

# `Makefile` plus complexe (1/3)

```makefile
# Un Makefile typique

# Le compilateur
CC = gcc

# La variable CFLAGS contient les flags de compilation:
#  -g                 compile avec les infos de debug
#  -Wall              Plein de warning
#  -Wextra            Encore plus de warnings
#  -pedantic          Warning lvl archimage
#  -O0                Option d'optimisation (0,1,2,3)
#  -std=c11           Utilisation du standard c11
#  -fsanitize=address Utilisation du standard c11
CFLAGS = -g -Wall -O0 -std=c11
```

# `Makefile` plus complexe (2/3)

```makefile
# La variable LDFLAGS contient les flags pour l'éditeur
# de liens: -lm dit d'éditer les liens avec la lib math
LDFLAGS = -lm

# Définition des sources
SOURCES = galaxy.c stars.c vec.c
# OBJECTS contient SOURCES avec .c -> .o
OBJECTS = $(SOURCES:.c=.o)
# galaxy sera l'exécutable (galaxy.c contient le main)
TARGET = galaxy
# Jusqu'ici on a aucune cible.
```

# `Makefile` plus complexe (3/3)

```makefile
# TARGET est la première cible et sera donc exécuté à l'invocation de `make`
# Elle dépend de OBJECTS
$(TARGET) : $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
# $@ : la cible, $ˆ : la liste des dépendances

# PHONY signifie qu'on ne crée rien avec les cibles mentionnées
# Ici clean est la cible utilisée pour enlever tous les fichier .o
# et l'exécutable

.PHONY: clean

clean: # aucune dépendance
    rm -f $(TARGET) $(OBJECTS)
```

# Gestion implicites (1/2)

## Question

Comment cela se fait-il qu'on ait pas besoin de générer les `OBJECTS`
dans le `Makefile` précédent?

## Réponse

`make` possède une série de règles implicites (voir [ce lien](https://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html#SEC95) pour une liste).

## Fonctionnement

Quand `make` rencontre une dépendance sans règle, il va voir dans sa liste de règles implicites pour la générer.
Ainsi

```makefile
foo: foo.o bar.o
    gcc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
# implicitement pour foo.c et bar.c
    $(CC) -c $(CPPFLAGS) $(CFLAGS)
```

# Gestion implicites (2/2)

## Question

Et pour les dépendances des cibles implicites ça se passe comment?

## Réponse

On peut définir individuellement les 

## Fonctionnement

Quand `make` rencontre une dépendance sans règle, il va voir dans sa liste de règles implicites pour la générer.
Ainsi

```makefile
foo: foo.o bar.o
    gcc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
# implicitement pour foo.c et bar.c
    $(CC) -c $(CPPFLAGS) $(CFLAGS)
```



# Macros

## Les macros

- Assignation
 
    ```make
    CC = gcc
    CFLAGS = -g -Wall -Wextra -pedantic -O0 -std=c11
    LDFLAGS = -lm
    ```
- Utilisation
 
    ```bash
    $(CC) 
    ```
- Déclaration à la ligne de commande

    ```bash
    make CFLAGS="-O3 -Wall"
    ```

## Variables internes

- `$@` : la cible
- `$^` : la liste des dépendances
- `$<` : la première dépendance
- `$*` : le nom de la cible sans extension