diff --git a/slides/Makefile b/slides/Makefile index 7895e41092f7d37916969c676ebc0f3d5e28f15c..edad008238d8f5880d358afd00ed31ca97edcee3 100644 --- a/slides/Makefile +++ b/slides/Makefile @@ -8,6 +8,7 @@ PDFOPTIONS = -t beamer PDFOPTIONS += --pdf-engine=xelatex +PDFOPTIONS += -F mermaid-filter PDFOPTIONS += --default-image-extension=pdf PDFOPTIONS += -V theme:metropolis PDFOPTIONS += -V themeoptions:numbering=none -V themeoptions:progressbar=foot diff --git a/slides/make_avance.md b/slides/make_avance.md new file mode 100644 index 0000000000000000000000000000000000000000..f4f756425060f9f381ece509da3ded7686c2f589 --- /dev/null +++ b/slides/make_avance.md @@ -0,0 +1,292 @@ +--- +title: "Plus de Makefiles" +date: "2023-02-24" +--- + +# `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`). +- Un `Makefile` bien écrit ne recompile que ce qui est **nécessaire**! +- Il existe d'autres outils pour le `C` et d'autres langages (`cmake`, `meson`, `maven`, `cargo`, ...). + +# 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 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 +``` + +::: +::: {.column width="40%"} + +## Terminal + +```bash +$ make +gcc -c galaxy.c +gcc -c stars.c +gcc -c vec.c +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} +graph TD; + galaxy.o --> galaxy + stars.o --> galaxy + vec.o --> galaxy + galaxy.c --> galaxy.o + stars.c --> stars.o + stars.h --> stars.o + stars.h --> galaxy.o + vec.h --> stars.o + vec.h --> vec.o + vec.c --> vec.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 des sanitizers +CFLAGS = -g -Wall -Wextra -pedantic -O0 -std=c11 -fsanitize=address +``` + +# `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 +# -lSDL2 dit d'éditer les liens avec la lib SDL2 +LDFLAGS = -lm -lSDL2 + +# Définition des sources +SOURCES = galaxy.c stars.c vec.c +# OBJECTS contient SOURCES avec .c qui devient .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 +# exécute toujours clean, même si un ficher `clean` existe + +.PHONY: clean + +clean: # aucune dépendance + rm -f $(TARGET) $(OBJECTS) +``` + +# Gestion implicite (1/2) + +## Question + +Pourquoi n'a-t-on pas besoin de générer les `OBJECTS`? + +## 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 + +Si `make` rencontre une dépendance sans règle, il va voir dans sa liste de règles implicites pour la générer. + +```makefile +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 implicite (2/2) + +## Question + +Et pour les dépendances des cibles implicites ça se passe comment? + +## Réponse + +On peut définir individuellement les dites dépendances! + +## 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. + +```makefile +# 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: `*`, `%`, `:=`, ... + +```makefile +# version "longue" +SOURCES = $(wildcard *.c) +OBJECTS = $(SOURCES:.c=.o) +# version "courte" +OBJECTS := $(patsubst %.c,%.o,$(wildcard *.c)) +``` + +Let's take one step at a time: + +* Les `*`{.makefile}, +* Les `%`{.makefile}, et leurs différences. +* Les fonctions, ici `wildcard`{.makefile} et `patsubst`{.makefile} (voir respectivement [ce lien](https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html) et [ce lien](https://www.gnu.org/software/make/manual/html_node/Text-Functions.html)). +* Le symbole `:=`{.makefile} vs `=`{.makefile}. + +# 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 +``` + +# La différence entre `*` et `%` + +* Le symbole `*`{.makefile} sert à générer une *liste* d'objets. +* Le symbole `%`{.makefile} sert comme *emplacement* (placeholder). + +## Exemple + +```makefile +%.o: %.c # % est la partie avant .c + $(CC) -o $@ -c $< $(CFLAGS) # la règle pour chaque `%.c` +# équivalent à +galaxy.o: galaxy.c +stars.o: stars.c +vec.o: vec.c + +``` + +## Application + +```makefile +$(patsubst # Substitution de texte pour chaque + %.c,\ # Le pattern "avant" le .c + %.o,\ # Le pattern "avant" le .o + $(wildcard *.c)\ # Tous les fichiers .c + ) +``` + + +# Le symbole `:=`{.makefile} vs `=`{.makefile} (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 + imprédictible!). + +# 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. diff --git a/slides/pointeurs_avances.md b/slides/pointeurs_avances.md new file mode 100644 index 0000000000000000000000000000000000000000..9c3cdadd21ed98a17704150914faf88e6e2caa06 --- /dev/null +++ b/slides/pointeurs_avances.md @@ -0,0 +1,68 @@ +--- +title: "Pointeurs avancés" +date: "2023-02-28" +--- + +# Pointeurs et `const` + +\footnotesize + +- Le mot-clé `const` permet de déclarer des valeurs **constantes** qui ne changeront plus en cours d'exécution du programme. + + ```C + const int a = 1; + a = 2; // interdit, erreur de compilation! + ``` + +## Deux niveaux de constance + +- Mais qu'est-ce que cela veut dire pour les pointeurs? +* Constance de la valeur de l'adresse? de la valeur pointée? des deux? + + ```C + int n = 12; + const int *p = &n; // la valeur *p est const, p non + int const *p = &n; // la valeur *p est const, p non + int *const p = &n; // la valeur p est const, *p non + const int *const p = &n; // la valeur p et *p sont const + ``` + +# Pointeurs et `const` + +## Exemples + +```C +int n = 12; int m = 13; +const int *p = &n; // la valeur *p est const, p non +*p = m; // erreur de compilation. +p = &m; // OK +int const *p = &n; // la valeur *p est const, p non +*p = m; // erreur de compilation. +p = &m; // OK +int *const p = &n; // la valeur p est const, *p non +*p = m; // OK +p = &m; // erreur de compilation. +const int *const p = &n; // la valeur p et *p sont const +*p = m; // erreur de compilation. +p = &m; // erreur de compilation. +``` + +# Pointeurs et `const` + +## Fonctions + +```C +void foo(int *a); +void foo(const int *a); // on pourra pas changer *a +void foo(int *const a); // inutile on peut pas changer a +void foo(const int *const a); // identique à ci-dessus +``` + +## Mais..... + +```C +const int a = 0; +int *b = (int *)&a; +*b = 7; +printf("a = %d\n", a); // affiche quoi? +```