Comment puis-je intercepter les erreurs et les interruptions dans GNU make?
Question
Je me demande s'il y a un moyen de mettre en œuvre trap
dans GNU make
, semblable à celui construit en BASH
?
Si l'utilisateur appuie sur CTRL-C
, ou si elle-même ne make
(sortie non nulle), je voudrais appeler une cible particulière ou macro.
La solution
Non. Le traitement du signal de GNU make laisse déjà beaucoup à désirer. À partir de son gestionnaire de signaux, il appelle des fonctions telles que printf
qui ne sont pas sûrs d'être appelé à partir d'un gestionnaire de signal. Je l'ai vu ces problèmes de cause, par exemple, les règles de .DELETE_ON_ERROR
ne fonctionnent pas toujours si stderr
est redirigé vers stdout
.
Par exemple, sur une boîte CentOS 7.4:
-
Créer le
Makefile
suivant:.DELETE_ON_ERROR: foo: touch $@ sleep 10
-
Ouvrir dans
vim
de:make
et exécuter, - Alors qu'il dort, appuyez sur Ctrl - C
vim / faire des impressions
Press ENTER or type command to continue
touch foo
sleep 10
^C
shell returned 130
Interrupt: Press ENTER or type command to continue
Make a été envoyé un signal d'interruption, mais foo
existe toujours.
Autres conseils
A ce moment, GNU make ne prend pas en charge native.
Il existe une solution fiable cependant:
.PHONY: internal-target external-target
external-target:
bash -c "trap 'trap - SIGINT SIGTERM ERR; <DO CLEANUP HERE>; exit 1' SIGINT SIGTERM ERR; $(MAKE) internal-target"
internal-target:
echo "doing stuff here"
Ce captures d'interruptions, terminaisons et des codes de sortie non nul.
Notez la $(MAKE)
donc cmdline et overrides faire des options sont transmis à submake.
Le piège:
- gestionnaire d'interruptions clair (avec -)
- faire le nettoyage
- sortie avec le statut de sortie non-zéro, construire des outils d'automatisation rapport de la construction a échoué.
DELETE_ON_ERROR ne fonctionne pas pour les répertoires, de sorte que ce qui est essentiel pour le nettoyage après mktemp -d
, par exemple
Remplacer <DO CLEANUP HERE>
valide avec CMD.
Une version simplifiée de la réponse de @ kevinf qui semble assez bon pour les cas de base:
run:
bash -c "trap 'docker-compose down' EXIT; docker-compose up --build"
(Cet exemple est pour une raison: docker-compose up
ne dit
les sorties de commande, tous les conteneurs sont arrêtés.
mais il ne rm
pas les récipients bouchés comme docker run --rm
serait, pour que vous puissiez les voir encore avec docker ps -a
.)
Marque ne supporte pas, mais en utilisant des astuces BASH vous pouvez accomplir quelque chose de similaire.
default: complete
complete: do_mount
echo "Do something here..."
do_mount:
mkdir -p "$(MOUNTPOINT)"
( while ps -p $$PPID >/dev/null ; do \
sleep 1 ; \
done ; \
unmount "$(MOUNTPOINT)" \
) &
mount "$(MOUNTSOURCE)" "$(MOUNTPOINT)" -o bind
Le « unmount » se déroulera après le « faire » vient compléter. Ceci est généralement une solution satisfaisante si vous essayez d'opérations de nettoyage qui peuvent se produire lors de la construction, mais ne sont pas nettoyés normalement à la sortie « make ».
Non. Pour autant que je sais qu'il n'y a pas une telle fonctionnalité.
make produit des codes de retour. Pour autant que je me souviens en ce moment, elle retourne 0 pour le succès, 2 pour l'échec (s'il vous plaît vérifier la documentation). Par conséquent, serait-il suffisant pour vous envelopper faire l'intérieur d'un script shell par exemple?