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
# 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
CFLAGS = -g -Wall -O0 -std=c11
CFLAGS = -g -Wall -Wextra -pedantic -O0 -std=c11
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
SOURCES = $(wildcard *.c)
##################################
# OK pour v1 et v2
# OBJECTS contient SOURCES avec .c -> .o
OBJECTS = $(SOURCES:.c=.o)
######### advanced v3 ############
# OBJECTS := $(patsubst %.c,%.o,$(wildcard *.c))
##################################
# galaxy sera l'exécutable (galaxy.c contient le main)
TARGET = main
TARGET = galaxy
$(TARGET) : $(OBJECTS)
@echo $(x) $(y)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
# main: main.o foo.o bar.o
# cc -o $@ $^ $(CFLAGS) $(LDFLAGS)
#
# foo.o: foo.h
# bar.o: bar.h
# main.o: foo.h
# galaxy.o: stars.h vec.h
# stars.o: *.h
# vec.o: vec.h
.PHONY: clean
......
......@@ -13,28 +13,28 @@ date: 2021-03-03
- 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`).
- 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`, ...).
# Utilisation de `make`
[^1]: Par pitié arrêtez de faire un `rebuild` ou un `clean` à chaque compilation.
## `Makefile` simple
# Utilisation de `make`
:::::::::::::: {.columns}
::: {.column width="60%"}
## `Makefile` simple
```bash
galaxy: galaxy.o stars.o vec.o
gcc -o galaxy galaxy.o stars.o vec.o
galaxy.o: galaxy.c
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 galaxy.c
vec.o: vec.c vec.h
gcc -c vec.c
clean:
rm -f *.o galaxy
```
......@@ -42,8 +42,6 @@ clean:
:::
::: {.column width="40%"}
**Dessinez le diagramme de dépendances de ce `Makefile`**.
## Terminal
```bash
......@@ -51,13 +49,16 @@ $ make
gcc -c galaxy.c
gcc -c stars.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
rm -f *.o galaxy
```
:::
::::::::::::::
**Dessinez le diagramme de dépendances de ce `Makefile`**.
# Diagramme de dépendances
~~~{.mermaid format=png}
......@@ -101,7 +102,7 @@ LDFLAGS = -lm
# Définition des sources
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)
# galaxy sera l'exécutable (galaxy.c contient le main)
TARGET = galaxy
......@@ -111,15 +112,15 @@ TARGET = galaxy
# `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 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 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
......@@ -127,12 +128,11 @@ clean: # aucune dépendance
rm -f $(TARGET) $(OBJECTS)
```
# Gestion implicites (1/2)
# Gestion implicite (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?
Pourquoi n'a-t-on pas besoin de générer les `OBJECTS`?
## Réponse
......@@ -140,17 +140,17 @@ dans le `Makefile` précédent?
## 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
```makefile
foo: foo.o bar.o
gcc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
# implicitement pour foo.c et bar.c
$(CC) -c $(CFLAGS)
galaxy: galaxy.o stars.o vec.o
gcc -o galaxy galaxy.o stars.o vec.o $(CFLAGS) $(LDFLAGS)
# implicitement pour galaxy.c, stars.c et vec.c
$(CC) -c $< $(CFLAGS) -o $@
```
# Gestion implicites (2/2)
# Gestion implicite (2/2)
## Question
......@@ -166,7 +166,91 @@ Quand `make` rencontre une dépendance sans règle, il va voir dans sa liste de
Ainsi
```makefile
foo.o: foo.h
bar.o: foo.h bar.h
# pas besoin des .c qui sont implicites
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.
Finish editing this message first!
Please register or to comment