Skip to content
Snippets Groups Projects
Verified Commit 5a2e4b56 authored by orestis.malaspin's avatar orestis.malaspin
Browse files

maj slides, et makefile exemple

parent 62dad8c3
No related branches found
No related tags found
No related merge requests found
Pipeline #13024 passed
# galaxy: galaxy.o stars.o vec.o
# gcc -o galaxy galaxy.o stars.o vec.o
# galaxy.o: galaxy.c stars.h
# gcc -c galaxy.c
# stars.o: stars.c stars.h vec.h
# gcc -c stars.c
# vec.o: vec.c vec.h
# gcc -c vec.c
# clean:
# rm -f *.o galaxy
CC = gcc CC = gcc
CFLAGS = -g -Wall -O0 -std=c11 CFLAGS = -g -Wall -Wextra -pedantic -O0 -std=c11
LDFLAGS = -lm LDFLAGS = -lm
# SOURCES = main.c foo.c bar.c x = foo
y = $(x) bar
x = later
######### advanced v1 ############
SOURCES = galaxy.c stars.c vec.c
##################################
######### advanced v2 ############
# SOURCES = $(wildcard *.c)
# means *.c # means *.c
SOURCES = $(wildcard *.c) ##################################
# OK pour v1 et v2
# OBJECTS contient SOURCES avec .c -> .o # OBJECTS contient SOURCES avec .c -> .o
OBJECTS = $(SOURCES:.c=.o) OBJECTS = $(SOURCES:.c=.o)
######### advanced v3 ############
# OBJECTS := $(patsubst %.c,%.o,$(wildcard *.c)) # OBJECTS := $(patsubst %.c,%.o,$(wildcard *.c))
##################################
# galaxy sera l'exécutable (galaxy.c contient le main) # galaxy sera l'exécutable (galaxy.c contient le main)
TARGET = main TARGET = galaxy
$(TARGET) : $(OBJECTS) $(TARGET) : $(OBJECTS)
@echo $(x) $(y)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
# main: main.o foo.o bar.o # galaxy.o: stars.h vec.h
# cc -o $@ $^ $(CFLAGS) $(LDFLAGS) # stars.o: *.h
# # vec.o: vec.h
# foo.o: foo.h
# bar.o: bar.h
# main.o: foo.h
.PHONY: clean .PHONY: clean
......
...@@ -13,28 +13,28 @@ date: 2021-03-03 ...@@ -13,28 +13,28 @@ date: 2021-03-03
- Création du code objet à partir des sources. - Création du code objet à partir des sources.
- Création de l'exécutable à partir du code objet. - Création de l'exécutable à partir du code objet.
- Tout "gros" projet utilise `make` (pas uniquement en `C`). - Tout "gros" projet utilise `make` (pas uniquement en `C`).
- Un `Makefile` bien écrit ne recompile que ce qui est **nécessaire**![^1]
- Il existe d'autres outils pour le `C` et d'autres langages (`cmake`, `meson`, `maven`, `cargo`, ...). - Il existe d'autres outils pour le `C` et d'autres langages (`cmake`, `meson`, `maven`, `cargo`, ...).
# Utilisation de `make` [^1]: Par pitié arrêtez de faire un `rebuild` ou un `clean` à chaque compilation.
## `Makefile` simple # Utilisation de `make`
:::::::::::::: {.columns} :::::::::::::: {.columns}
::: {.column width="60%"} ::: {.column width="60%"}
## `Makefile` simple
```bash ```bash
galaxy: galaxy.o stars.o vec.o galaxy: galaxy.o stars.o vec.o
gcc -o galaxy galaxy.o stars.o vec.o gcc -o galaxy galaxy.o stars.o \
vec.o
galaxy.o: galaxy.c galaxy.o: galaxy.c stars.h
gcc -c galaxy.c gcc -c galaxy.c
stars.o: stars.c stars.h vec.h stars.o: stars.c stars.h vec.h
gcc -c galaxy.c gcc -c galaxy.c
vec.o: vec.c vec.h vec.o: vec.c vec.h
gcc -c vec.c gcc -c vec.c
clean: clean:
rm -f *.o galaxy rm -f *.o galaxy
``` ```
...@@ -42,8 +42,6 @@ clean: ...@@ -42,8 +42,6 @@ clean:
::: :::
::: {.column width="40%"} ::: {.column width="40%"}
**Dessinez le diagramme de dépendances de ce `Makefile`**.
## Terminal ## Terminal
```bash ```bash
...@@ -51,13 +49,16 @@ $ make ...@@ -51,13 +49,16 @@ $ make
gcc -c galaxy.c gcc -c galaxy.c
gcc -c stars.c gcc -c stars.c
gcc -c vec.c gcc -c vec.c
gcc -o galaxy galaxy.o stars.o vec.o gcc -o galaxy galaxy.o
stars.o vec.o
$ make clean $ make clean
rm -f *.o galaxy rm -f *.o galaxy
``` ```
::: :::
:::::::::::::: ::::::::::::::
**Dessinez le diagramme de dépendances de ce `Makefile`**.
# Diagramme de dépendances # Diagramme de dépendances
~~~{.mermaid format=png} ~~~{.mermaid format=png}
...@@ -101,7 +102,7 @@ LDFLAGS = -lm ...@@ -101,7 +102,7 @@ LDFLAGS = -lm
# Définition des sources # Définition des sources
SOURCES = galaxy.c stars.c vec.c SOURCES = galaxy.c stars.c vec.c
# OBJECTS contient SOURCES avec .c -> .o # OBJECTS contient SOURCES avec .c qui devient .o
OBJECTS = $(SOURCES:.c=.o) OBJECTS = $(SOURCES:.c=.o)
# galaxy sera l'exécutable (galaxy.c contient le main) # galaxy sera l'exécutable (galaxy.c contient le main)
TARGET = galaxy TARGET = galaxy
...@@ -111,15 +112,15 @@ TARGET = galaxy ...@@ -111,15 +112,15 @@ TARGET = galaxy
# `Makefile` plus complexe (3/3) # `Makefile` plus complexe (3/3)
```makefile ```makefile
# TARGET est la première cible et sera donc exécuté à l'invocation de `make` # TARGET est la première cible et sera donc exécuté à
# Elle dépend de OBJECTS # l'invocation de `make`. Elle dépend de OBJECTS
$(TARGET) : $(OBJECTS) $(TARGET) : $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
# $@ : la cible, $ˆ : la liste des dépendances # $@ : la cible, $ˆ : la liste des dépendances
# PHONY signifie qu'on ne crée rien avec les cibles mentionnées # PHONY signifie qu'on ne crée rien avec les cibles
# Ici clean est la cible utilisée pour enlever tous les fichier .o # mentionnées. Ici clean est la cible utilisée pour
# et l'exécutable # enlever tous les fichier .o et l'exécutable
.PHONY: clean .PHONY: clean
...@@ -127,12 +128,11 @@ clean: # aucune dépendance ...@@ -127,12 +128,11 @@ clean: # aucune dépendance
rm -f $(TARGET) $(OBJECTS) rm -f $(TARGET) $(OBJECTS)
``` ```
# Gestion implicites (1/2) # Gestion implicite (1/2)
## Question ## Question
Comment cela se fait-il qu'on ait pas besoin de générer les `OBJECTS` Pourquoi n'a-t-on pas besoin de générer les `OBJECTS`?
dans le `Makefile` précédent?
## Réponse ## Réponse
...@@ -140,17 +140,17 @@ dans le `Makefile` précédent? ...@@ -140,17 +140,17 @@ dans le `Makefile` précédent?
## Fonctionnement ## 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. Si `make` rencontre une dépendance sans règle, il va voir dans sa liste de règles implicites pour la générer.
Ainsi Ainsi
```makefile ```makefile
foo: foo.o bar.o galaxy: galaxy.o stars.o vec.o
gcc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS) gcc -o galaxy galaxy.o stars.o vec.o $(CFLAGS) $(LDFLAGS)
# implicitement pour foo.c et bar.c # implicitement pour galaxy.c, stars.c et vec.c
$(CC) -c $(CFLAGS) $(CC) -c $< $(CFLAGS) -o $@
``` ```
# Gestion implicites (2/2) # Gestion implicite (2/2)
## Question ## Question
...@@ -166,7 +166,91 @@ Quand `make` rencontre une dépendance sans règle, il va voir dans sa liste de ...@@ -166,7 +166,91 @@ Quand `make` rencontre une dépendance sans règle, il va voir dans sa liste de
Ainsi Ainsi
```makefile ```makefile
foo.o: foo.h # pas besoin des .c qui sont implicites
bar.o: foo.h bar.h galaxy.o: stars.h vec.h
stars.o: *.h
vec.o: vec.h
``` ```
# On peut faire mieux
Il est possible de prendre **tous** les fichiers `.c`
```makefile
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
```
Ou encore mieux
```makefile
OBJECTS := $(patsubst %.c,%.o,$(wildcard *.c))
```
# That escalated quickly: `*`, `%`, `:=`, ...
Let's take one step at a time:
* Les `*`,
* Les `%`, et leurs différences.
* Les fonctions, ici `wildcard` et `patsubst`.
* Le symbole `:=` vs `=`.
# Le symbole `*`
## `make` peut "développer" (expand) des `wildcards` (`*`)
* dans les recettes le `*` est géré par le shell
```makefile
clean:
rm -f *.o galaxy
```
* dans les dépendances
```makefile
galaxy.o: *.h
```
mais des fichiers `.h` doivent exister sinon il interprète `*.h` le nom du fichier.
## Par contre ile ne peut pas
```makefile
OBJECTS = *.o
# il faut utiliser
OBJECTS := $(wildcard *.o) # retourne tous les fichier .o
```
# Le symbole `:=` vs `=` (1/2)
Deux façon (flavors) d'assigner des variables (voir [ce lien](https://www.gnu.org/software/make/manual/html_node/Flavors.html#Flavors)):
## Le symbole `=`
* Façon **récursive**:
```makefile
foo = $(bar)
bar = $(ugh)
ugh = Huh?
```
ici `foo` vaut `Huh?`.
* Valeurs remplacées "récursivement".
* Variables remplacées à chaque appel (lent + impredictible!).
# Le symbole `:=` vs `=` (2/2)
Deux façon (flavors) d'assigner des variables (voir [ce lien](https://www.gnu.org/software/make/manual/html_node/Flavors.html#Flavors)):
## Le symbole `:=`
* Façon **simplement développée** (`Simply expanded variable`):
```makefile
x := foo
y := $(x) bar
x := later
```
ici `y` vaut `foo bar` et `x` vaut `later` (avec des `=`, `y` vaudrait `later bar`).
* Les variables se comportent comme en `C`.
* En particulier dans les *longs* `Makefile` le comportement est plus prédictible.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment