Cher journal,
je t'écris pour te donner des nouvelles de BSD Make Pallàs Scripts[1], une famille de macros pour make
que j'écris et utilise pour:
- Préparer et publier des documents avec TeX et LaTeX.
- Développer des macros TeX et LaTeX avec NOWEB.
- Développer pour OCaml.
- Préparer un site web statique avec ONSGMLS.
- Maintenir les fichiers de configuration de systèmes FreeBSD.
Les macros sont publiées sous licence CeCILL-B, une licence de type BSD.
[1] https://bitbucket.org/michipili/bsdmakepscripts
Un atout des macros make
sur d'autres systèmes analogues sont d'une part l'universalité de make
qui ne vise pas de sous-système particulier, l'ubiquité de make
et sa simple extensibilité:
make
est universel car il propose simplement d'écrire des scripts shells dans une forme particulière, en imposant un flux de traitement adapté aux tâches de type traitement sur des fichiers, sans pour autant prescrire ce que peut-être traité.make
est partout. (Parceque.)une macro
make
est facilement extensible, puisque pour ajouter la commandeplop fizz
en épilogue à l'installation d'un programme il suffit d'ajouter
after-install:
plop fizz
Enfin, make
peut-être utilisé pour construire de gros projets, comme le système FreeBSD.
Fonctions avancées
Les fonctions avancées sympas sont, pour les documents TeX:
- Support de bibtex
- Support des figures générées avec (une version moderne de) METAPOST.
- Support de profils d'impression PostScript.
Cf: https://bitbucket.org/michipili/bsdmakepscripts/wiki/ProduceLaTeXDocuments
Pour les projets OCaml:
- Support de la compilation bytecode ou native.
- Génération de documentation avec OCamldoc.
- Compilation pour le déboguage.
- Compilation pour le profilage.
- Génération de lexers et de parsers.
- Compilation parallèle.
- Support de la séparation des sources et des objets.
- Prépraration des archives de distribution, signature avec GPG.
Cf: https://bitbucket.org/michipili/bsdmakepscripts/wiki/DevelopOCamlSoftware
Compatibilité
J'utilise ces macros dans les environnements suivants:
- FreeBSD 9.0 et le programme
make
du système. - Mac OS X 10.5 et le programme
bsdmake
du système. - Mac OS X 10.4 et le programme
bsdmake
du système. - Debian 7.0 et le package
bmake
.
La compatibilité avec ces systèmes est un but du projet. Probablement, les macros peuvent être utilisées sur d'autres systèmes comme NetBSD, OpenBSD et peut-être même INTERIX avec bmake
.
Bon développement!
# omake
Posté par barmic . Évalué à 2.
Est-ce que tu t'es penché sur omake avant de choisir make pour tes macro ?
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: omake
Posté par Michaël (site web personnel) . Évalué à 5.
Ma première réponse est simplement que j'ai commencé à écrire ces macros en 2000, époque à laquelle
omake
n'existait probablement pas.J'ai commencé à travailler avec GNU Make, je peux donc par contre détailler les raisons qui m'ont motivé à changer.
La documentation de GNU Make est essentiellement réduite à son manuel de référence. Ce manuel est très complet (à l'époque il faisait plus de 200 pages) mais c'est un manuel de référence: le but de ce document est de décrire très précisément tous les aspects du logiciel, mais pas du tout d'expliquer comment on résout des problèmes avec le logiciel.
Ces dernières explications sont habituellement contenues dans des introductions, des tutoriels, ou des fiches de recette, comme on peut les appeler. À l'époque je n'avais pas trouvé de tutoriel satisfaisant.
Finalement, la troisième source d'information sont les exemples. J'avais trouvé très difficile de trouver des exemples intéressants, le gros des
Makefile
étant généré parautomake
et pas du tout typique de ce qu'on peut écrire à la main.Du côté de BSD Make, que j'avais à disposition puisque j'ai commencé à utiliser FreeBSD à cette époque, la situation est bien différente puisque:
Il existe un tutoriel de référence écrit par Adam de Boor, et faisant partie de la documentation standard du système. C'est un document d'excellente qualité qui commence par le
b-a ba
et montre progressivement comment utiliser variables et macros pour raccourcir et assouplir sesMakefile
en introduisant de nouvelles abstractions. C'est aussi un document court et accessible, dont on fait le tour en moins d'une demi-journée.La page de manuel make(1) tient lieu de manuel de référence, elle faisait et fait toujours dans les 8 pages: le logiciel est certe plus simple que la version GNU, mais on trouve rapidement toute l'information! Alors qu'avec le manuel du programme de GNU, j'étais toujours à la recherche de la description de ceci ou de cela, et du passage pas dans l'index deux pages avant…
Il existe une abondante littérature de
Makefile
dans laquelle puiser des idées: la compilation du système FreeBSD est gérée parmake
, j'avais donc sous la main beaucoup d'exemples à étudier. Et cela prouve au passage qu'en s'y prenant bien—c'est à dire, en faisant comme dans les exemples—on peut organiser des tâches extrêmement complexes avecmake
.Alors oui, le
make
de FreeBSD est très certainement bien plus primitif que celui de GNU, mais les trois points ci-dessus font bien plus que contrebalancer cette différence technologique. Après tout, l'apparition de C++ n'empêche pas que chaque jour des programmes nouveaux soient écrits en C, une technologie pourtant inférieure sur le papier (que sait faire C que ne sait pas faire C++?). Les raisons à cela sont très certainement (en partie) celles de ma liste: C est à la fois plus simple que C++, bien éprouvé, et les exemples ne manquent pas.J'ai passé un peu de temps à regarder
omake
— que j'ai redécouvert, puisque je me souviens l'avoir vu il y a quelques années — c'est un logiciel très prometteur qui semble très puissant. La documentation est cependant un problème: comme manuel de référence elle semble très complète, mais un examen rapide me laisse penser qu'il n'y a pas d'exemple simple, un exemple simple sans macro, sans fonction sans rien, juste unDe plus je n'ai pas vraiment réussi à comprendre — dans le temps imparti! — le statut du shell dans
omake
. Dansmake
c'est très clair, si je sais faire quelque chose dans mon shell, je n'ai qu'à le recopier à la fin de monMakefile
en ajoutant une ligne spécifiant les dépendances: c'est à la fois facile à retenir car cela ne fait intervenir que des concepts de base du programme — c'est quelque chose qu'on sait faire même si on s'est arrêté au premier exemple du tutoriel d'Adam de Boore! — et facile à mettre en œuvre car cela s'appuie directement sur le shell.# Problématique
Posté par Guillaum (site web personnel) . Évalué à 3.
J'ai lu la documentation en diagonale et ce qui m’embête c'est que j'ai l'impression que c'est (pour la partie latex du moins) une n-ième version de rubber/latexmk/yourbuildscript.
Ce que j’attends d'un outil de build pour latex c'est une gestion correcte des dépendances générées. Rubber ne sait faire cela que pour des cas simples (i.e.: générer un .poulet à partir d'un .tortue), latexmk à le même problème, mais sait déléguer à make, mais cette délégation se fait en plusieurs passes et généralement c'est le carnage (i.e.: tu appelles make, qui appelle latexmk pour générer la liste des dépendances, qui appele make, qui génère celles-ci et rappel latexmk… 9 fois sur 10 j'ai un truc recompilé pour rien ou pas recompilé, quand je ne parle même pas d'un echec de latexmk qui perd les pédales).
J'ai craqué, j'ai fais une tambouille maison dégueulasse et utilisable seulement par moi et cela me déprime, et chaque fois que je vois quelqu'un proposer un outil de build pour LaTeX, j'espere que on va me sortir de ce calvaire.
Et vous, vous gérez comment vos dépendances générées ? Attention, je ne parle pas de cas simple du genre convertir des .svg en .pdf, mais plutôt de cas du genre vous voulez afficher une image qui est le résultat du rendu d'une scène avec blender, puis passé dans 4 passes d'image magick, passé dans FFMPEG pour ressortir des images de diagnostic, et bien évidement tout cela doit être paramétré dans le .tex car je peux vouloir changer un paramètre de rendu.
[^] # Re: Problématique
Posté par Michaël (site web personnel) . Évalué à 4. Dernière modification le 08 janvier 2014 à 19:44.
Je ne connais ni
rubber
nilatexmk
donc je ne peux pas trop comparer à ce que j'ai écrit.Écrire des macros pour
make
c'est la même chose que de la programmation en shell à ceci près que la logique du traitement n'est pas exprimée par des procédure mais par des recettes et des dépendances. On explique seulement àmake
les étapes élémentaires de la construction etmake
se débrouille pour constuire un plan d'action.Pour ta question précise, j'ai une réponse précise, en trois étapes:
make
.Voilà la spécification que je propose: je suppose que tu as une macro
plopfizz
qui prend en argument les paramètres de ton image et fait deux choses. Premièrement elle écrit ces paramètres dans un fichierid.plopfizz
ouid
caractérise l'appel. Deuxièmement elle regarde si l'imageid.png
résultat du traitement existe déjà pour éventuellement l'inclure dans le document. Ce n'est certainement pas exactement ta situation, mais probablement assez similaire.On prépare une routine shell, disons
process-plopfizz.sh
qui lit un fichierid-plopfizz
et prépare l'imageid.png
. La prépration d'un document ressemble donc àMaintenant on peut intégrer dans le workflow de
make
. Pour cela, commemake
se fie auxtimestamp
d'un fichier pour savoir s'il a été modifié, il faut être un peu sioux et améliorer la macro TeXplopfizz
pour qu'elle lise le fichierid.plopfizz
s'il existe et n'en écrive un nouveau que si les paramètres ont changé.À la fin, le fichier
Makefile
ressemblerait àLa ligne
est l'incantation vaudou qui insère notre solution dans le workflow de
make
. Les déclarations suivantes sont des recettesmake
standard et les deux dernières lignes ajoutent les produits aux listes de fichiers à effacer, avecmake clean
oùmake distclean
. La formemake distclean
efface moins de fichiers quemake clean
. Ici les images sont conservées mais pas les fichiers intermédiairesplopfizz
, ce qui facilite la préparation d'une archive qu'on envoie à son éditeur par exemple.On voit bien que la préparation des images pourrait être améliorée en introduisant des règles génériques ou des variables, mais j'ai pensé qu'on pouvait dans un premier temps se contenter d'une solution “bébête” qui n'aie pas l'air artificiellement compliquée.
Bien-sûr c'est garanti sans test, mais c'est la route à suivre.
P.S.: Si tu prépares un
use case
ou bien uneuse story
un peu plus précis, je peux te donner plus de détails! L'idéal serait quelque chose que je puisse incorporer au source dans le dossier test.[^] # Re: Problématique
Posté par Guillaum (site web personnel) . Évalué à 3.
Sommaire
Merci pour ce message.
Ta solution est intéressante, sauf qu'elle force à décrire dans le makefile la liste de toutes tes dépendances. Ma (courte) thèse contient actuellement plusieurs dizaines de dépendances générées et je n'ai pas envie de devoir les décrire une par une dans le makefile sachant que je le fais déjà dans le .tex.
Use case simple
J'ai besoin de convertir les .poulet en .tortue.
dans latex:
Là latexmk (ou rubber) est capable d'appeler make pour toutes les dépendances, ainsi :
Il y a une règle relativement simple qui dit que :
Use case avancé
J'ai un programme qui prend en paramètre un nom de svg (source.svg) et la liste de calques à exporter (calque1 et calque2) et qui génère un .pdf.
Dans mon latex:
\includegraphics{source__calque1_calque2_layers.pdf}
Le soucis c'est que on ne peut plus faire de règle makefile simple du genre :
avec %1 et %2 des trucs génériques qui seront par la suite associés à $1 et $2
Ce cas reste encore un peu simple, car finalement il suffit d'écrire pour chaque fichier svg du répertoire la règle :
et on peut faire cela avec une macro make:
(ici il me prend tous les .svg que mercurial connait, mais bon)
Ça commence à faire mal ici (en gros, je suis le seul humain de tout ceux qui bossent sur ce projet (i.e, heureusement que c'est ma thèse) qui veut encore lire le makefile).
Cas pathologique (90% de mes use cases)
Je veux un fichier de sortie qui dépend d'un nombre de fichiers d'entrés indéterminé et de N paramètres. Dans mon latex je fais :
et dans mon makefile, et bien je ne sais pas ce que je fais. J'avais adopté une nouvelle solution, je sous-traitais à un script :
qui génère la liste de dépendances qui sera évalué par make à la prochaine passe pour gérer correctement mon build.
Et là je meurs.
Solution actuelle
Alors finalement je fais autrement. J'ai une fonction
Qui prend une commande.
LaTeX ouvre un pipe et écrit cette commande et lit dans un pipe le nom du fichier à inclure.
Un démon (en python, mais on s'en cogne) lit dans le pipe la commande à exécuter, et écrit le nom temporaire de sortie après exécution (en gérant bien évidement un cache pour ne pas reconstruire tout à chaque fois).
Exemple :
Et dans mon code python, j'ai défini une fonction :
Ainsi:
a) chaque action de build est en fait une simple fonction python dans un fichier, fonction paramétrée comme bon me semble et appelée naturellement depuis mon .tex. Mon pire exemple c'est :
b) Je m’embête plus à trouver des noms pour mes fichiers générés, j'ai une fonction de hash à la con qui fait cela, met tout dans /tmp et voila. En plus c'est sympa, le nom dépend des paramètres de la commande et pas de l'endroit ou elle est appelée dans le .tex. Ainsi si je décide de tester en changeant un paramètre, cela va compiler pendant 2 heures, et si je revient sur la version précédente, cela va reprendre l'ancien fichier déjà présent dans le cache.
c) Toutes les dépendances sont mise à jour lors de la passe sur le .tex et dirigées par le contenu du .tex. Ainsi tout est bien synchronisé.
d) Je peux intégrer des "plugins" dans mon outil de rendu. Par exemple, à tout moment, je peux dire que les résultats images qui sortent sont downscalés, ainsi mon pdf se construit plus vite (cela permet d'avoir le bon visuel dans le pdf, à la qualité près, sans prendre 30 minutes parce que toutes mes images hautes résolutions tuent les performances)
Ma plus grosse limitation actuellement, hormis le coté code non robuste et pas du tout vendable, c'est que cela ne gère pas la construction en parallèle des dépendances.
Donc pour conclure, je cherche un outil plus puissant pour générer mes dépendances. Actuellement j'ai une solution foireuse qui fonctionne, mais pas très sérieuse.
[^] # Re: Problématique
Posté par Guillaum (site web personnel) . Évalué à 3.
tl;dr: Je ne veux pas à avoir à lister mes dépendances autre part que dans le .tex et je veux pouvoir lister facilement celles-ci, même quand elle proviennent d'un processus de construction très complexe ayant plusieurs fichiers en dépendance et plusieurs paramètres.
[^] # Re: Problématique
Posté par Michaël (site web personnel) . Évalué à 2.
J'ai bien aimé le TL;DR! :-)
[^] # Re: Problématique
Posté par Michaël (site web personnel) . Évalué à 2.
Ta solution est beaucoup trop compliquée!
Pour tirer parti correctement de
make
tu as besoin de préciser correctement tes dépendances et de tenir compte destimestamps
. Comme tu sais programmer des dæmons en Python, je suppose que des programmes plus simples sont également à ta portée.Voici ce que je propose:
Pour commencer, on définit une commande TeX
MyFancyGraphic
qu'on utilise comme suit:Dont l'effet est d'inclure l'image
filename
et de poubelliser (ignorer) le reste.Ensuite on écrit un programme
makedepend_blender
— en OCaml, mais on s'en cogne ;) — qui prépare les dépendances. Il lit tes fichiers TeX et écrit un fichier.depend_blender
contenant des lignes du type(Si les fichiers image ont d'autres dépendances, il faut trouver une convention pour les ajouter dans
MyFancyGraphic
et demander àmakedepend_blender
d'écrire leurs noms à droite defilename.in
.)De plus
makdepend_blender
écrit aussi le contenu de l'appel à la commande dans le fichierfilename.in
— mais ne réécrit pas le fichier si le contenu n'a pas changé, ce qui évite de changer inutilement le timestamp.Finalement, côté
Makefile
cela donne:Et voilà. :)
[^] # Re: Problématique
Posté par Guillaum (site web personnel) . Évalué à 2.
Donc il faut inventer un nom, c'est à mon sens une limitation.
Donc il faut que le programme parse le document racine à la recherche d'inclusions vers d'autres documents. C'est faisable, mais c'est dur à rendre robuste (si par exemple quelqu'un défini une macro qui appelle \input).
Donc tu dois spécifier les dépendances à la main, alors que certaines commandes pourraient les gérer d'elles mêmes.
Par contre ce que tu propose me donne une idée pour simplifier mon implémentation. Je garde la commande "MyFancyGraphic", sans le "filename", et la seule chose que fait latex c'est générer un nom de fichier unique basé sur la commande et d'inclure ce nom de fichier unique. Après mon script de build parse le fichier .tex (et ses sous-fichiers) et génère les dépendances en utilisant le même mécanisme, et c'est gagné.
[^] # Re: Problématique
Posté par Michaël (site web personnel) . Évalué à 2.
Pas forcément c'est just un exemple. Ce qui compte c'est d'avoir une idée claire de ce qu'on veut pour pouvoir l'implémenter — c'est pour ça que j'ai choisi un exemple. Mon but est plutôt d'expliquer la partie
make
.Il y a mille façons de régler ça. Moi, ça ne me dérange pas d'écrire la liste de mes sources TeX à la main dans le Makefile et c'est facile. Une solution automatique pourait par exemple parser le log du job TeX — si c'est trop difficile on peut redéfinir la primitive
input
pour qu'elle écrive le nom du fichier de façon facile à reconnaître.Encore une fois c'est juste un exemple, et mon but est plutôt d'expliquer la partie
make
. Simakedepend_blender
peut calculer une partie des dépendance, pas de raison de s'en priver.Ceci dit, écrire les dépendances à la main est en général peut contraignant — si on écrit la liste une seule fois à un seul endroit — car il s'agit d'une liste stable et cela permet d'avoir cette liste sous les yeux pour déboguer.
[^] # Re: Problématique
Posté par Guillaum (site web personnel) . Évalué à 2.
Il faut que je prenne quelque temps pour réfléchir à l'approche que tu proposes, mais c'est en effet intéressant, merci.
C'est un point sur lequel je ne suis pas d'accord, la liste de dépendance c'est implicitement le document .tex qui la donne et je n'ai pas envie de me répéter, sachant que je change souvent celles-ci.
[^] # Re: Problématique
Posté par Michaël (site web personnel) . Évalué à 2.
Donc dans ton cas la liste n'est pas stable! Une solution automatique de type
makedepend
est effectivement à envisager.Si tu as des problèmes avec BSD Make, n'hésite pas! :D
Et bonne chance pour ta thèse, après c'est que des bons souvenirs!
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.