Le site arthur.bebou.netlib.re - retour accueil
git clone git://bebou.netlib.re/arthur.bebou
Log | Files | Refs |
index.sh (9767B)
1 #! page 2 title: Rendre catium portable 3 author: Arthur Pons 4 description: Faisons des efforts pour rendre catium fonctionnel sur macos et les *bsd 5 publication: 2024-01-12 6 7 sectionmd: main 8 9 A Katzele on écrit souvent du shell. On (je du moins) aime bien dire que ce que 10 l'on écrit est POSIX ou presque et que ça fonctionne donc sur tous les dérivés 11 d'Unix[^1]. De fait, une majorité d'entre nous utilise des systèmes Debian ou 12 basés sur Debian (Ubuntu) et nous testons rarement nos créations sur autre chose. 13 Même si l'on essaye d'énoncer clairement les dépendances d'un projet, la 14 portabilité vers d'autres systèmes ne prend qu'assez peu de notre temps pour 15 quatre raisons : 16 17 1. La faible demande d'adaptation vers d'autres distributions 18 2. Le manque de temps 19 3. Le manque de matériel (nous n'avons pas facilement accès à un mac) 20 4. La croyance que puisque l'on fait du shell simple alors ce sera portable de toute façon 21 22 En profitant d'une rare exception à la première raison, je propose de tester 23 les deux dernières raisons en portant Catium sur MacOs version 10.x et 24 supérieure ainsi qu'OpenBSD 7.4. 25 26 Merci à mon frère qui m'a prêté son mac pour faire des tests. 27 28 ## La demande 29 30 [Timothée Goguely], designer et dev web basé à Strasbourg, souhaite tester 31 Catium pour la création d'un site pour l'un de ses clients soucieux de faire 32 très simple. Timothée utilise un mac, le client utilise un mac, il est donc 33 opportun de tester Catium sur un mac. 34 35 Par la suite j'ai profité de la gentillesse de Victor Hoffner pour tester 36 la version modifiée sur OpenBSD. 37 38 ## Les tests 39 40 ### Construire le projet (make) 41 42 Première chose à faire, cloner le projet. Mac vient avec git (en tout cas je 43 n'ai pas eu à l'installer sur les deux macs que j'ai utilisé), il suffit donc 44 de faire : 45 46 git clone git://katzele.netlib.re/catium 47 48 En théorie, si tout fonctionne bien il suffit ensuite d'installer lowdown, de 49 créer le dossier root dans lequel on génère le site et de lancer `make`. Pas 50 de souci à l'installation de lowdown via le gestionnaire de paquet 51 communautaire [homebrew]. Pas de souci pour créer le dossier mais en lançant 52 `make` on constate que seules les copies du favicon et de la feuille de style css 53 se font. Pas d'exécution de l'unique page de démo du projet. Il se trouve que 54 le make fourni par défaut par Apple sur les Mac (du moins ceux que j'ai testé) 55 est GNU Make version 3.8[^8]. Elle ne supporte manifestement pas la syntaxe 56 suivante, présente dans notre makefile : 57 58 pages = ${sources:src/%.md=root/%.html} 59 60 Or cette syntaxe "traduit" le chemin du fichier source vers le chemin du 61 fichier de destination. Si cette ligne ne fonctionne pas, le makefile ne 62 cherchera jamais à créer le fichier de destination et n'appellera jamais la 63 règle correspondante. Pour y remédier il faut installer GNU Make via brew en 64 faisant `brew install make`. Brew package une version plus récente de GNU Make 65 (4.1.1) qui supporte cette syntaxe. Après l'installation, brew nous informe 66 que l'on peut appeler cette version de GNU Make en lançant la commande `gmake` 67 mais qu'une opération sur le `PATH` peut rendre cette version là disponible en 68 tapant `make`. 69 70 > GNU "make" has been installed as "gmake". 71 > If you need to use it as "make", you can add a "gnubin" directory 72 > to your PATH from your bashrc like: 73 > 74 > PATH="$HOMEBREW_PREFIX/opt/make/libexec/gnubin:$PATH" 75 76 J'en conviens, cette solution est quelque peu 77 confuse puisqu'elle a pour résultat d'avoir deux version différentes 78 de GNU Make installées sur son ordi, l'une appelée make et l'autre 79 gmake mais ça fait l'affaire. 80 81 Lançons maintenant `gmake`. On constate que la génération de la page html 82 essaye bien d'avoir lieu mais qu'un message d'erreur (parmi d'autres) indique 83 que `-D` n'est pas une option pour la commande install. Il se trouve que 84 d'après le standard POSIX[^2], install n'est pas POSIX. Cela ne veut pas dire 85 qu'il ne faut jamais l'utiliser ni qu'il ne se trouvera sur aucun *nix mais que 86 l'on en a pas la garantie et surtout que l'on ne peut pas prédire son 87 comportement et ses options. La preuve, la version disponible sur MacOs ne 88 comporte pas l'option `-D` qui existe pourtant dans l'install des GNU core 89 utils. Ne trouvant pas d'équivalent commun aux deux versions j'ai préféré le 90 remplacer par : 91 92 mkdir -p $(dirname $@) 93 $< > $@ 94 95 Qui créé d'abord le dossier de destination à l'aide d'mkdir et dirname qui 96 sont tous les deux POSIX puis exécute le script en redirigeant la sortie vers 97 le fichier de destination. 98 99 Si vous exécutiez `gmake` vous verriez une nouvelle erreur informant qu'il 100 manque une quelque chose à mkdir pour bien fonctionner. En effet la capture 101 de commande `$(dirname $@)` ne fonctionnera pas tel quel dans le makefile. Il 102 faut faire appel à la fonction `shell`[^3] pour exécuter `dirname` avant que le 103 makefile n'exécute le `mkdir`. Cela donne donc 104 105 mkdir -p $(shell dirname $@) 106 $< > $@ 107 108 Avec cette modification nous avons un makefile parfaitement fonctionnel sur MacOs à 109 condition d'avoir mis jour make. 110 111 ### Exécuter les scripts 112 113 Si vous suivez l'article vous aurez remarqué qu'il y a d'autres erreurs que 114 nous avons jusque là ignoré. Le "préprocesseur" des pages et le fichier common 115 associé, les fichiers page et common ont été écrit pour [Dash], le shell POSIX 116 de Debian par défaut. Il est disponible sur d'autres systèmes. 117 118 Les shebang utilisés sur ces deux scripts sont `#! /bin/sh`. Sous Debian 119 `/bin/sh` est un lien symbolique vers `dash` mais ce n'est pas le cas 120 sous tous les systèmes. En l'occurence sur MacOs `/bin/sh` est un lien 121 symbolique vers le shell de login par défaut du système, c'est à dire zsh. 122 Il fallait donc être plus explicite. J'ai initialement changé les shebang en 123 `#! /bin/dash`, ce qui fonctionne sous MacOs, mais pour des raisons de 124 meilleure portabilité je l'ai ensuite changé en `#! /usr/bin/env dash` au 125 cas-où `dash` soit installé ailleurs qu'à `/bin/dash`[^9]. 126 127 Ce changement corrige une partie des problèmes, lorsque bash n'interprètent pas 128 les scripts comme dash mais certaines erreurs subsistent du type : 129 130 src/index.md: ligne 2 : fg: pas de contrôle de tâche 131 src/index.md: ligne 3 : fg: pas de contrôle de tâche 132 src/index.md: ligne 4 : fg: pas de contrôle de tâche 133 src/index.md: ligne 5 : fg: pas de contrôle de tâche 134 src/index.md: ligne 9: Cette : commande introuvable 135 src/index.md: ligne 13: bin : commande introuvable 136 137 Ces erreurs pointent vers le fait que les alias présents dans common ne sont 138 pas instanciés correctement. Si l'on vérifie quel processus se lance lorsque 139 l'on exécute "à la main" la page en faisant `src/index.md`, on constate que le 140 script est lancé avec le shell par défaut du système (`bash src/index.md` par 141 exemple). Or, le shebang de `src/index.md` est `#! page`. Ce que l'on souhaite 142 c'est qu'en exécutant une page, elle soit passée en argument au script page 143 qui lui même sera exécutée par dash et fera tourner le code dans common. 144 Pour une raison ou pour une autre le shebang est ignoré, page et common non 145 exécutés, le nécessaire n'est pas créé et l'on obtient des erreurs. 146 147 Avec Timothée nous avons cherché un moment pourquoi nous constations ce 148 comportement. Il se trouve que MacOs et *BSD ne supportent pas l'utilisation 149 d'un script contenant lui même un shebang[^4][^5][^6]. Le shebang doit pointer 150 sur un binaire. Un contournement est d'utiliser `/usr/bin/env` et de lui donner 151 en argument notre interpréteur perso[^7] : 152 153 #! /usr/bin/env ./page 154 155 Je n'aime pas trop cette solution que je trouve bien moins sympathique pour 156 l'utilisateurice que d'écrire `#! page` ou `#! page` mais c'est le prix 157 de la portabilité. Cela n'empêche évidemment pas d'utiliser la forme courte 158 sur les systèmes Linux. 159 160 Avec cette dernière modification on devrait pouvoir faire 161 162 gmake 163 164 et constater la bonne génération de `root.index.html`. 165 166 ## Conclusion 167 168 J'avais tort en disant "On fait du shell POSIX simple, ça fonctionne 169 partout !". Je n'aurais pas eu tort si j'avais dit "On fait du shell 170 à peu près POSIX et simple, ça devrait pas être très compliqué à faire 171 fonctionner ailleurs". 172 173 J'en retire qu'il faut être encore plus clair sur les dépendances. Par exemple 174 ne pas dire "make" mais "GNU Make testé en version >4.3", ne pas dire 175 "interpréteur shell POSIX" mais "Dash". Cela dit, nous avons testé et 176 Catium fonctionne avec zsh et ksh, pas bash. 177 178 La totalité de ce travail, y compris la rédaction de cet article, aura pris 179 quelque part entre 6h et 8h, ce que je trouve raisonnable. La quantité de code 180 modifié est petite, l'esprit du projet n'a pas changé. Je pense que l'on a fait 181 la démonstration qu'à défaut d'avoir été portable directement en faisant des 182 choses simples et en essayant de garder, ne serait-ce qu'un peu, la portabilité 183 en tête on se facilite la tâche pour le jour où il faudra réellement le faire. 184 185 [^1]: Linux, *BSD, MacOs notamment 186 [Timothée Goguely]: https://timothee.goguely.com/ 187 [homebrew]: https://brew.sh/ 188 [^2]: https://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html 189 [^3]: https://www.gnu.org/software/make/manual/html_node/Shell-Function.html 190 [Dash]: https://fr.wikipedia.org/wiki/Debian_Almquist_shell 191 [^4]: https://stackoverflow.com/questions/9988125/shebang-pointing-to-script-also-having-shebang-is-effectively-ignored 192 [^5]: https://en.wikipedia.org/wiki/Shebang_(Unix) 193 [^6]: https://www.in-ulm.de/~mascheck/various/shebang/#interpreter-script 194 [^7]: https://theinfocentric.com/bash-shebang/ 195 [^8]: Vieille de 21 ans ! 196 [^9]: Im me semble qu'env peut se retrouver ailleurs que /usr/bin/env mais bon. Je pense pas que l'on puisse faire beaucoup mieux.