Reword and syntax coorrections

Thanks Eclipse, Duponin Heuzef and my wife
This commit is contained in:
Yorick Barbanneau 2023-09-04 22:01:33 +02:00
parent 46b5c7989b
commit 1f151ee32e

View file

@ -5,11 +5,10 @@ Date: 2023-08-30 12:10
cover: assets/backgrounds/machine_zorba.jpg cover: assets/backgrounds/machine_zorba.jpg
status: draft status: draft
Dans mon précédent [article]({filename}../fonctionnement_makefile/index.md), Dans mon [précédent article]({filename}../fonctionnement_makefile/index.md),
nous avons vu comment fonctionne *make* et son langague utilisé dans les nous avons parlé du fonctionnement de *make* et des `Makefile`. Comme promis,
`Makefile`. Comme promis, voici le premier example d'utilisation : la voici le premier exemple d'utilisation : la construction de documents *PDF* à
construction de document *PDF* à partir de fichiers sources LaTeX, de fichiers partir de fichiers sources LaTeX, de fichiers *SVG* et d'images matricielles.
*SVG* et d'images matricielles.
Nous allons avancer progressivement tout au long de cet article, ainsi nous Nous allons avancer progressivement tout au long de cet article, ainsi nous
commencerons avec un `Makefile` des plus basique pour l'améliorer au fur et à commencerons avec un `Makefile` des plus basique pour l'améliorer au fur et à
@ -22,7 +21,7 @@ archive]({attach}./files/examples.tar.xz). Les corrections sont disponibles dans
le répertoire `Makefile/`. le répertoire `Makefile/`.
Faites attention aux copiés/collés : les tabulations sont transformées en Faites attention aux copiés/collés : les tabulations sont transformées en
espace dans les blocs de code de cet article. Or *make* se sert des tabulations espaces dans les blocs de code de cet article. Or *make* se sert des tabulations
pour déterminer les actions relatives aux cibles. Lors de l'exécution de *make*, pour déterminer les actions relatives aux cibles. Lors de l'exécution de *make*,
vous aurez l'erreur `Makefile:23: *** missing separator. Stop.`, il suffira de vous aurez l'erreur `Makefile:23: *** missing separator. Stop.`, il suffira de
revoir votre indentation. revoir votre indentation.
@ -46,18 +45,32 @@ clean:
@rm document.aux document.log documents.pdf @rm document.aux document.log documents.pdf
``` ```
Nous utilisons ce qui se fait déjà pour la compilation de programme en `C`, à Nous utilisons ce qui se fait déjà pour la compilation de programme en `C`, à
savoir placer le compitateur et ses paramètres dans des variables. Nous avons savoir placer le compilateur et ses paramètres dans des variables. Nous avons
donc `$(LC)` pour *LaTeX Compiler* -- j'utilise LuaLatex -- et `$(LCFLAGS)` donc `$(LC)` pour *LaTeX Compiler* -- j'utilise LuaLatex -- et `$(LCFLAGS)`
pour les paramètres. pour les paramètres.
La cible `default` sera lancée automatiquement si aucune autre est spécifiée
dans la ligne de commande. Ainsi la compilation se lance avec un simple `make`.
## un répertoire pour les compiler tous ## un répertoire pour les compiler tous
À la premièrer compilation, on s'aperçoit vite que plusieurs fichiers À la premièrer compilation, on s'aperçoit vite que plusieurs fichiers
apparaissent dans notre répertoire (fichiers `aux`, `log`, `toc` etc.) Il apparaissent dans notre répertoire (fichiers `aux`, `log`, `toc` etc.) comme
devient alors un peu confus, nous allons faire en sorte de placer tous ces ceci:
fichiers (ainsi que le fichier PDF généré) dans un répertoire séparé.
```shell
$ ls -l
-rw-r--r-- 1 user group 186 Aug 31 13:14 document.aux
-rw-r--r-- 1 user group 19650 Aug 31 13:14 document.log
-rw-r--r-- 1 user group 41023 Aug 31 13:14 document.pdf
-rw-r--r-- 1 user group 1203 Aug 29 23:27 document.tex
-rw-r--r-- 1 user group 191 Aug 29 23:27 Makefile
```
Notre répertoire devient alors un peu confus, nous allons faire en sorte de
placer tous ces fichiers (ainsi que le fichier PDF généré) dans un
sous-répertoire.
```make ```make
LC = lualatex LC = lualatex
@ -73,18 +86,31 @@ $(OUTPUT)/document.pdf: document.tex
clean: clean:
@rm -rf $(OUTPUT) @rm -rf $(OUTPUT)
``` ```
Nous définissons la variables `OUTPUT` qui contient le répertoire dans lequel Nous définissons la variable `OUTPUT` qui contient le répertoire dans lequel
placer tous les fichiers générés par `lualatex`. L'options qui va bien est placer tous les fichiers générés par `lualatex`. L'option qui va bien est
ajoutée à `LCFLAGS`. `OUTPUT` est aussi utilisée pour la cible `clean`, notre ajoutée à `LCFLAGS`. `OUTPUT` est aussi utilisée pour la cible `clean`, notre
nettoyage n'en est que plus simple!. nettoyage n'en est que plus simple!
Tout ces fichiers sont maintenant dans le répertoire `build/`. Tous ces fichiers sont maintenant dans le répertoire `build/`:
## Tous ne s'appellent pas document ```shell
$ tree
.
├── build
│   ├── document.aux
│   ├── document.log
│   └── document.pdf
├── document.tex
└── Makefile
Tous nos documents de s'appellent pas *document*, leurs noms dépendent souvent 2 directories, 5 files
```
## Mais où est document?
Tous nos documents ne s'appellent pas *document*, leurs noms dépendent souvent
du contexte. Rendons donc ce `Makefile` plus générique grâce aux variables et du contexte. Rendons donc ce `Makefile` plus générique grâce aux variables et
macros macros.
```make ```make
LC = lualatex LC = lualatex
@ -102,35 +128,35 @@ $(OUTPUT)/%.pdf: %.tex
clean: clean:
@rm -rf $(OUTPUT) @rm -rf $(OUTPUT)
``` ```
notre macro `DOCUMENTS` est un imbrication de 3 fonction :
1. `wildcard <motif>` pour récupérer une liste de fichier dans le répersoire Notre macro `DOCUMENTS` est une imbrication de 3 fonctions :
1. `wildcard <motif>` pour récupérer une liste de fichiers dans le répertoire
courant en fonction d'un motif; courant en fonction d'un motif;
2. `patsubst <motif>,<remplacement>,<chaine>` pour substituer une partie de la 2. `patsubst <motif>,<remplacement>,<chaine>` pour substituer une partie de la
chaine dans un chemin, `%` fait ici office de caractère joker; chaîne dans un chemin, `%` fait ici office de caractère joker;
3. `addprefix <prefix>, <chaine>` pour ajouter un préfixe à chacun des éléments 3. `addprefix <prefix>, <chaine>` pour ajouter un préfixe à chacun des éléments
d'une chaine de caracères. Pour *make*, les éléments d'une chaine de d'une chaîne de caractères. N'oubliez pas, pour *make*, les éléments d'une
caractère sond délimités par des espaces. chaîne de caractères sont délimités par des espaces.
Elle permet d'obtenir le nom d'une cible en fonction des fichiers `tex` contenu Elle permet d'obtenir le nom d'une cible en fonction des fichiers `tex` contenus
dans notre répertoire : `document.tex` deviendra alors `build/document.pdf`. dans notre répertoire : `document.tex` deviendra alors `build/document.pdf`.
`$(DOCUMENTS)` est maintenant une dépendance de notre cible `default`. Et chacun `$(DOCUMENTS)` est maintenant une dépendance de notre cible `default`. Et chacun
de ses élémets appelle la cible `$(OUTPUT)/%.pdf: %.tex` qui dépend de `%.tex` : de ses élémets appelleront la cible `$(OUTPUT)/%.pdf: %.tex` qui se charge de
la source LaTeX, `%` étant remplacé par le nom donné dans la cible : contruite un fichier PDF en fonction de sa source LaTeX.
`build/document.pdf` donnerait `document.tex` comme dépendance.
Cette solution nous permet maintenant d'appeler notre source LaTeX comme bon Cette solution nous permet d'appeler notre source LaTeX comme bon nous semble.
nous semble. Mieux encore nous nouvons **avoir plusieurs fichiers** à la racine Mieux encore nous pouvons **avoir plusieurs fichiers** à la racine de notre
de notre répertoire, il seront tous compilés indépendament. C'est très pratique répertoire, ils seront tous compilés indépendamment. C'est très pratique lorsque
lorsque vous avez un rapport et la présentation dans un même dépôt par exemple. vous avez un rapport et la présentation dans un même dépôt par exemple.
## Les images matricielles ## Les images matricielles
Il n'est pas rare qu'un document contienne des **images au format matriciel** : Il n'est pas rare qu'un document contienne des **images matricielles** : des
des photos au format JPEG ou des captures d'écran au format PNG par exemple. Il photos JPEG ou des captures d'écran PNG par exemple. Il est alors nécessaire de
est alors nécessaire de prendre en compte la modification de ces images pour la prendre en compte la modification de ces images pour la compilation de nos
compilation de nos documents. documents.
```make ```make
LC = lualatex LC = lualatex
@ -155,26 +181,43 @@ clean:
Nous avons maintenant une variable `IMAGES_DIR` qui nous permet de spécifier le Nous avons maintenant une variable `IMAGES_DIR` qui nous permet de spécifier le
répertoire dans lequel sont stockées les images -- nous verrons plus tard que répertoire dans lequel sont stockées les images -- nous verrons plus tard que
d'autres sous-dossiers d'*images* apparaîtront. La liste des images est d'autres sous-dossiers d'*images* apparaîtront. La liste des images est
récupérée grace à la macro `IMAGES` qui utilise la fonction `wildcard` pour récupérée grâce à la macro `IMAGES` qui utilise la fonction `wildcard` pour
récupérer **tous les fichiers de ce répertoire**. récupérer **tous les fichiers de ce répertoire**.
Le résultat de cette macro est donné en dépendance de notre cible de Le résultat de cette macro est donné en dépendance de notre cible permettant la
contruction des documents `$(OUTPUT)/%.pdf: %.tex`. **Ainsi si une image est construction des documents : `$(OUTPUT)/%.pdf: %.tex`. **Ainsi si une image est
modifiée ou ajoutée, alors la compilation du fichier PDF sera relancée**. modifiée ou ajoutée, alors la compilation du fichier PDF sera relancée**.
Notre technique a cependant deux défauts. D'abord si une image est ajoutée mais Notre technique a cependant deux défauts.
n'est pas utilisée le document sera quand même compilé alors que ce n'est pas
nécessaire.
Enfin si une image utilisée **seulement** dans le document *B* est modifiée, *A* D'abord, si nous ajoutons une image sans l'utiliser dans notre document et
et *C* **seraient aussi compilés**. Ce dernier problème pourrait être résolu, nous relançons la compilation alors notre document sera tout de même
mais au prix d'une complexification de notre processus de compilation. recompilé sans que se soit nécessaire. *make* ne fait pas d'analyse sytaxique,
il n'est pas **capable d'analyser le fichier source pour determiner s'il doit
être compilé ou non**.
Ensuite prenons l'exemple d'un dossier contenant trois fichiers LaTeX *A*, *B*,
et *C*. Si une image utilisée **seulement** dans le document *B* est modifiée,
*A* et *C* **seront tout de même recompilés**.
Dans l'exemple de code fourni (dans le répertoire `4_images`), vous trouverex un
script (`change_image.sh`) qui se charge de changer l'image du document
`presentation.tex`. Vous pouvez tester la compilation avant et après la
modification du `Makefile` et observer les actions effectuées.
Ce scrits se lance sans paramètres :
```shell
$ ./change_image.sh
Flip images ...
Done!
```
## Les images SVG ## Les images SVG
Personnellement j'utilise beaucoup *Inkscape* pour produire diverses images. J'utilise beaucoup *Inkscape* pour produire diverses images. Mais le format SVG
Mais le format SVG n'est pas utilisable tel quel en LaTeX[^n_svgtex]. Il est n'est pas utilisable tel quel en LaTeX[^n_svgtex]. Il est nécesssaire de passer
nécesssaire de passer par une étape intermédiaire pour le transformer en PDF. par une étape intermédiaire et le transformer en PDF.
```make ```make
LC = lualatex LC = lualatex
@ -207,31 +250,30 @@ clean:
@rm -rf $(OUTPUT @rm -rf $(OUTPUT
``` ```
Le principe est ici simple : nous allons utiliser *Inkscape* pour exporter les Le principe est simple : nous utilisons *Inkscape* pour exporter les fichiers au
fichiers au format PDF. Pourquoi exporter en PDF? C'est un format bien supporté format PDF. Pourquoi exporter en PDF? C'est un format bien supporté par les
par les moteurs *LaTeX*. Il permet aussi de conserver au maximum le format moteurs *LaTeX*. Il permet aussi de conserver au maximum le format
vectoriel[^n_svgpdf]. vectoriel[^n_svgpdf].
Quatres variables font leur apparition : Quatres variables font leur apparition :
* `SC` pour *SVG compiler*, nous utilisons *Inkscape*; * `SC` pour *SVG compiler*, nous utilisons *Inkscape*;
* `SCFLAGS` qui contient les paramètres de la commande `Inkcape`; * `SCFLAGS` qui contient les paramètres de la commande `Inkscape`;
* `SVG_DIR` qui contient le chemin vers les fichiers SVG; * `SVG_DIR` qui contient le chemin vers les fichiers SVG;
* `SVG_EXPORTED_DIR` qui contient le chemin vers les fichiers PDF exportés * `SVG_EXPORTED_DIR` qui contient le chemin vers les fichiers PDF exportés
depuis *Inkscape*. depuis *Inkscape*.
Nous avons aussi deux macros Et deux deux macros :
* `SVG` liste les fichiers SVG, cette macro utilise la fonction `wildcard` * `SVG` liste les fichiers SVG via la fonction `wildcard`;
interne à *make* qui permet de récupérer une liste de fichiers en fonction * `SVG_EXPORTED` transforme la liste contenu dans`SVG` en liste de fichiers
d'un motif; PDF. Deux fonctions imbriquées sont nécessaires :`subst` qui permet de
* `SVG_EXPORTED` transforme la liste de fichiers SVG en liste de fichiers PDF. remplacer un motif dans des chaînes et `patsubst` que nous avons vu
Deux fonctions imbriquées sont nécessaires :`subst` qui permet de remplacer précédemment. Cette macro est donnée en dépendance de la cible de compilation
un motif dans des chaines et `patsubst` que nous avons vu précédemment. Cette des documents.
macro est donnée en dépendance de la cible de compilation des documents.
Ensuite la cible qui nous permet de convertir les fichiers : Ensuite la cible qui nous permet de convertir les fichiers :
`$(SVG_EXPORTED_DIR)/%.pdf: $(SVG_DIR)/%.svg` et la commande associée. `$(SVG_EXPORTED_DIR)/%.pdf: $(SVG_DIR)/%.svg`.
[^n_svgtex]: Ce n'est pas tout à fait vrai, il est possible d'utiliser le [^n_svgtex]: Ce n'est pas tout à fait vrai, il est possible d'utiliser le
package LaTeX *svg* et sa commande `\includesvg` mais les contraintes sont package LaTeX *svg* et sa commande `\includesvg` mais les contraintes sont
@ -243,15 +285,15 @@ Ensuite la cible qui nous permet de convertir les fichiers :
## Les cibles accessoires ## Les cibles accessoires
Nous avons vu jusqu'ici les cibles principales, nous allons maintenant ajouter Nous avons vu jusqu'ici les cibles principales, ajoutons maintenant deux cibles
deux cibles qui pourront nous faciliter la vie. qui pourront nous faciliter la vie.
### Afficher des informations ### Afficher des informations
Notre `Makefile` est maintenant conséquent, il contient quelques **macros qu'il Notre `Makefile` est maintenant conséquent, il contient quelques **macros qu'il
est parfois utiles d'afficher**. Cette affichage nous permettra par exemple de est parfois utile d'afficher**. Cet affichage nous permettra par exemple de
vérifier les images matricielles prises en compte ou encore les fichiers SVG qui vérifier les images matricielles prises en compte ou encore les fichiers SVG qui
seront exportées. seront exportés.
```make ```make
LC = lualatex LC = lualatex
@ -291,14 +333,25 @@ info:
@echo "exported SVG images..'$(SVG_EXPORTED)'" @echo "exported SVG images..'$(SVG_EXPORTED)'"
``` ```
Nous n'utilisons pas la commande relatives au messages (`info`, `warning` et Nous n'utilisons pas les commandes relatives aux messages (`info`, `warning` et
`error`) que nous avons vu dans le précédent article, sinon un message `make: `error`) que nous avons vu dans le précédent article, sinon un message `make:
Nothing to be done for 'info'.` apparaît après les informations. Nothing to be done for 'info'.` apparaît après les informations.
Voici le résultat de cette cible:
```shell
$ make info
document.............'build/presentation.pdf'
bitmap images........'images/bitmap/ferret.jpg'
SVG images...........'images/svg/souris.svg'
exported SVG images..'images/generated/souris.pdf'
```
### Lancer l'application de visualisation des PDF ### Lancer l'application de visualisation des PDF
Lancer la compilation d'un document et l'afficher ensuite dans notre visionneur Lancer la compilation d'un document et l'afficher ensuite dans notre visionneur
de document permet souvent de gagner du temps. de documents permet souvent de gagner du temps. Partons du principe que nous
utilisons [Zathura][l_zathura] comme visionneur de documents.
```make ```make
LC = lualatex LC = lualatex
@ -347,41 +400,44 @@ view: default
Deux nouvelles variables font leur apparition : Deux nouvelles variables font leur apparition :
* `VIEWER` qui contient le nom du programme utilisé comme visionneur, * `VIEWER` qui contient le nom du programme utilisé comme visionneur
[zathura][l_zathura] dans l'exemple.
* `VIEWER_FLAGS` qui contient les options de notre visionneur * `VIEWER_FLAGS` qui contient les options de notre visionneur
Nous avons aussi une nouvelle cible `view`, comme elle ne réalise aucune Nous avons aussi une nouvelle cible `view`, comme elle ne réalise aucune
création de fichier nous ladéclarons comme cible `.PHONY`. La seule dépendance création de fichiers nous la déclarons comme cible `.PHONY`. La seule dépendance
ce cette cible est `default`. Ainsi lors de l'appel de `view`, **notre document de cette cible est `default` : ainsi lors de l'appel de `view`, notre document
sera recompilé si nécessaire**. sera recompilé **si nécessaire**.
[l_zathura]:https://pwmt.org/projects/zathura/ [l_zathura]:https://pwmt.org/projects/zathura/
## En conclusion ## En conclusion
Partant d'un `Makefile` standard, nous l'avons amélioré au fur et à mesure en Partant d'un `Makefile` standard, nous l'avons amélioré au fur et à mesure en
utilisant les fonctionnalités proposé par *make*. Bien entendu cet exemple est utilisant les fonctionnalités proposées par *make*. Bien entendu cet exemple est
valable pour les documents simple, il sera alors nécessaire de l'adapter pour valable pour les documents simples, il sera alors nécessaire de l'adapter pour
prendre en compte les **compilations multi-passes** pour la gestion des prendre en compte les **compilations multi-passes** pour la gestion des
bibiographies par exemple. bibliographies par exemple.
De mon côté j'ai profité de l'écriture de cet article pour améliorer mon De mon côté, j'utilise énormément LaTeX pour les courriers officiels, les rendu
processus de compilation de mes documents LaTeX. Au final, chaque dépôt de code des différents TD pour l'Université, mes présentations. J'ai profité de
contenant des documents prend la forme suivante : l'écriture de cet article pour améliorer mon processus de compilation de tous
mes documents. Au final, chaque dépôt de code contenant des documents prend la
forme suivante :
``` ```
├── images ├── images/
│   ├── bitmap │   ├── bitmap/
│ │ └── ... │ │ └── ...
│   ├── generated │   ├── generated/
│   └── svg │   └── svg
│ └── ... │ └── ...
├── Makefile ├── Makefile
├── build ├── build/
├── README.md ├── README.md
└── document.tex └── document.tex
``` ```
*[PDF]: Portable Document Format *[PDF]: Portable Document Format
*[SVG]: Scalable Vector Graphics *[SVG]: Scalable Vector Graphics
*[JPEG]:Join Photographic Experts Group
*[PNG]: Portable Network Graphic