Just, make, task : trois outils pour faire (des trucs)
by ascendances from ascendances
Sous Unix, un fichier Makefile est le moyen classique d’exécuter diverses tâches (en premier lieu des compilations de binaires). Récemment, deux outils (just et task) ont gagné en popularité. Ils ont le même objectif, tout en cherchant à être plus adaptés aux usages de développement actuels.
L’installation des différents outils est simple :
- Le binaire
makeest dans le paquetmake(incroyable !) et est probablement déjà installé. - Le binaire
justest dans le paquetjust(bis). - Debian ne contient pas de paquet
task. Un binairetaskest bien disponible dans le paquettaskwarriormais c’est un outil pour décompter le temps passé. Les développeurs de Taskfile fournissent un paquet Debian, déclaré comme incompatible avectaskwarriorà cause du nom identique de l’exécutable. Compiler le binaire soi-même est facile une fois que les outils pour compiler du Go sont déjà présents sur la machine.
A. Formats de fichier
Voici des exemples minimaux pour les trois outils :
1. Makefile
cible: commande
Les fichiers Makefile utilisent des tabulations. Aujourd’hui, on s’attend plutôt à des espaces. Un éditeur correct sait déjà le gérer donc ça ne devrait pas être vraiment un problème mais peut surprendre un nouvel arrivant.
2. Justfile
cible: commande
Il n’y a pas de différence visible avec le Makefile précédent car les fichiers Justfile en sont proches. Le format est simple et utilise des espaces plutôt que des tabulations.
C’est un format spécifique que les autres outils ne prennent pas toujours bien en charge (ou pas par défaut). Par exemple, bat (dans le paquet Debian nommé batcat) ou pygments ne savent pas faire de la coloration syntaxique sur ce format. Par contre, il existe des greffons pour Codium ou pour emacs (par exemple, just-mode, son code source et le dépôt Melpa), etc. De même, WordPress ne le prend pas en compte donc tous les codes source de Justfile ne bénéficieront pas de coloration syntaxique dans cet article.

3. Taskfile
version: '3'tasks: cible: cmd: commande
Taskfile réutilise le format YAML. Cela permet d’avoir une syntaxe connue et un outillage déjà prêt (coloration syntaxique et vérification de la syntaxe). Cependant, cela donne aussi des contenus plus verbeux que les Justfiles.
À noter que la ligne version est indispensable aux Taskfile car des versions antérieures du format de fichier sont incompatibles.
B. Exemples équivalents
Voici trois fichiers d’exemple montrant les mêmes commandes basiques pour les Makefile, Justfile et Taskfile :
1. Makefile
BINNAME = hellomake.PHONY: build clean testbuild: ## Compile le binaire gcc -o $(BINNAME) main.c ./gen_assets.shclean: ## Supprime les fichiers générés rm -f $(BINNAME)test: ## Exécute les tests ./tests.sh
Historiquement, les Makefile étaient (et sont encore) utilisés pour produire des fichiers. Les cibles peuvent être des fichiers et donc on se retrouve régulièrement à utiliser .PHONY. C’est pratique mais ça ne me semble pas très élégant.
2. Justfile
BINNAME := "hellojust"# Compile le binairebuild: gcc -o {{BINNAME}} main.c ./gen_assets.sh# Supprime les fichiers générésclean: rm -f {{BINNAME}}# Exécute les teststest: ./tests.sh
La syntaxe reste très proche d’un Makefile. En terme de possibilité, il n’y a pas de dépendances sur les fichiers pour exécuter (ou non) une commande.
3. Taskfile.yml
version: '3'vars: BINNAME: hellotasktasks: build: desc: Compile le binaire cmds: - gcc -o {{.BINNAME}} main.c - ./gen_assets.sh clean: desc: Supprime les fichiers générés cmd: rm -f {{.BINNAME}} test: desc: Exécute les tests cmd: ./tests.sh
Le format YAML permet de faire des listes ou de laisser sur une seule ligne s’il n’y a qu’une seule instruction (cf. cmd). L’ensemble des attributs rend le contenu assez explicite. Il n’y a pas de dépendances sur les fichiers (comme just).
C. Paramètres à passer à la commande
1. Makefile
Il est possible de fournir une valeur par défaut, modifiable sur la ligne de commande :
PORT ?= 8000staticserver: python3 -m http.server $(PORT)
Le résultat dans un terminal :
$ make staticserverpython3 -m http.server 8000Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...[...]$ make staticserver PORT=8888python3 -m http.server 8888Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) ...
2. Justfile
Justfile a des paramètres avec des valeurs par défaut :
staticserver port="8000": python3 -m http.server {{port}}
Le résultat dans un terminal :
$ just staticserverpython3 -m http.server 8000Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) …[...]$ just staticserver 8888python3 -m http.server 8888Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) …
À noter que just staticserver PORT=8888 provoque une erreur (invalid int value: 'PORT=8888').
3. Taskfile
version: '3'tasks: staticserver: vars: PORT: '{{default "8000" .PORT}}' cmds: - python3 -m http.server {{.PORT}}
Le résultat dans un terminal :
$ task staticservertask: [staticserver] python3 -m http.server 8000Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...[...]$ task staticserver PORT=8888task: [staticserver] python3 -m http.server 8888Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) ...
D. Prise en compte de fichier .env
La prise en charge est plus ou moins directe mais rien d’insurmontable.
1. Makefile
Contrairement à just et task, make ne prend pas nativement les fichiers .env en charge. Il suffit d’ajouter ces lignes en début de fichier pour que le fichier .env soit chargé :
# Chargement du fichier .envifneq (,$(wildcard ./.env)) include .env exportendif
C’est simplement du code valide pour make : ici, la fonction wildcard permet de détecter l’existence du fichier .env. La directive include charge le fichier donc les données du fichier .env deviennent disponibles comme variables dans le Makefile. La directive export passe l’ensemble des variables en tant que variables d’environnement aux commandes exécutées par le Makefile.
C’est plus simple pour just et task car le chargement de fichiers d’environnement est déjà intégré aux outils.
2. Justfile
Il suffit d’activer l’usage de fichier .env puis de récupérer la variable d’environnement souhaitée :
set dotenv-loadport := env("PORT", "8000")
La variable port dans just vaudra ce que contient la variable d’environnement PORT si elle est disponible, sinon elle vaudra 8000.
3. Taskfile
Il est possible de définir plusieurs fichiers qui écrasent leurs valeurs selon l’ordre de leur définition :
dotenv: - .env.local # config locale (priorité la plus haute) - [...] - .env # fichier par défaut (priorité la plus faible)
La variable d’environnement PORT définie (ou redéfinie) par le fichier d’environnement de plus grande priorité sera disponible via $PORT.
E. Lister les commandes disponibles
Cette possibilité est disponible nativement pour just et task :
just --listutilise le commentaire situé au-dessus de la commande.task --listutilise la valeur dedescsi elle est disponible pour documenter la commande.
L’usage est visible dans les exemples de la section « B. Exemples équivalents ».
Pour make, cela devrait être possible avec --print-targets dans le futur lorsqu’une nouvelle version sera publiée.
En attendant, il faut écrire une cible dédiée. Par exemple :
help: ## Montre les commandes disponibles @echo "Commandes disponibles :" @grep -E '^[a-zA-Z_-]+:.*?##' $(MAKEFILE_LIST) | \ sort | \ awk 'BEGIN{FS=":.*?## "}{printf " %-10s %s\n", $$1, $$2}'
Cela suppose que l’on a un commentaire qui suit la convention attendue par la cible help :
cible: ## viser le centre guillaume --tell --vise=pomme
F. Ne pas afficher la commande exécutée
Dans ce cas, seules les sorties standard et d’erreur sont affichées.
make et just utilisent la même astuce : préfixer la commande par @.
task utilise l’attribut silent qui peut être inséré à plusieurs endroits. Une variable d’environnement est aussi disponible.
tasks: echo: cmds: - cmd: echo "Print something" silent: true
Conclusion
Les trois outils ont des capacités non abordées dans cet article. J’ai l’impression que les cas d’usage entre just et task se recoupent complètement.
make est le choix classique avec la barrière à l’entrée la plus faible pour entrer sur une base de code. Cependant, si just ou task est déjà installé pour développer des services web par exemple, autant le mettre partout.
Entre les deux, j’ai une préférence pour just qui est moins verbeux. La popularité des deux projets est grandissante mais just a l’air de prendre l’avantage :

Actuellement :
Les restes
Versions utilisées pour l’article :
make4.4.1just1.50.0task3.41.0
Un serveur HTTP de fichiers statiques est vraiment fourni avec Python : la commande python3 -m http.server est fonctionnelle. C’est pratique pour du réseau local mais une mauvaise idée en production.
Le graphique montrant l’évolution des étoiles Github a été téléchargé depuis https://www.star-history.com/?repos=go-task%2Ftask%2Ccasey%2Fjust&type=timeline&legend=top-left. Le service permet aussi de télécharger un fichier .csv si besoin.
