2008-10-22 11 views
18

J'ai un Makefile qui démarre en exécutant un outil avant d'appliquer les règles de construction (que cet outil écrit pour moi). Si cet outil, qui est un script python, se termine avec un code d'état non nul, je veux que GNU Make s'arrête là et ne continue pas à construire le programme.

Actuellement, je fais quelque chose comme ça (niveau supérieur, à savoir la colonne 1):

$(info Generating build rules...) 
$(shell python collect_sources.py) 
include BuildRules.mk 

Mais cela ne s'arrête pas faire si collect_sources.py sorties avec un code d'état 1. Cette capture également la sortie standard de collect_sources.py mais ne l'imprime pas, donc j'ai le sentiment que je regarde dans la mauvaise direction.

Si possible, la solution devrait même fonctionner lorsqu'un simple shell MS-DOS est le shell système standard.

Une suggestion?

+1

Si vous avez GNU make 4.2 ou supérieur, vous pouvez vérifier la variable '$ (. SHELL_STATUS)' qui contiendra l'état de sortie de la dernière fonction '$ (shell ...)' évaluée. – MadScientist

+0

Le nom de la variable est '$ (. SHELLSTATUS)', sans '_'. https://www.gnu.org/software/make/manual/html_node/Shell-Function.html # Shell-Function – user3159253

Répondre

4

Ok, voici ma propre solution, qui est malheureusement pas basé sur le code d'état du script collect_sources.py, mais qui fonctionne pour moi (TM) et me permet de voir toute sortie que le script produit:

SHELL_OUTPUT := $(shell python collect_sources.py 2>&1) 
ifeq ($(filter error: [Errno %],$(SHELL_OUTPUT)),) 
    $(info $(SHELL_OUTPUT)) 
else 
    $(error $(SHELL_OUTPUT)) 
endif 

Le script est écrit afin que toute erreur produise une sortie commençant par "collect_sources: error:". De plus, si python ne peut pas trouver ou exécuter le script donné, il sort un message d'erreur contenant le message "[Errno 2]" ou similaire. Donc, ce petit morceau de code capture simplement la sortie (en redirigeant stderr vers stdout) et recherche les messages d'erreur. Si aucun n'est trouvé, il utilise simplement $(info) pour imprimer la sortie, sinon il utilise $(error), ce qui fait effectivement s'arrêter.

Notez que l'indentation dans le ifeq ... endif est faite avec des espaces. Si des onglets sont utilisés, Make pense que vous essayez d'invoquer une commande et s'en plaint.

6

Il pourrait y avoir une meilleure façon, mais j'essayé ce qui suit et il fonctionne:

$(if $(shell if your_command; then echo ok; fi), , $(error your_command failed)) 

Ici, je ne suppose que your_command ne donne pas de sortie, mais il ne devrait pas être difficile de travailler dans ce une situation. Editer: Pour le faire fonctionner avec le shell Windows par défaut (et probablement tout shell décent), vous pouvez écrire your_command && echo ok au lieu de if dans la fonction shell. Je ne pense pas que cela soit possible pour les obus DOS (plus anciens). Pour ceux-ci, vous voulez probablement adapter your_command ou écrire un script wrapper pour imprimer quelque chose en cas d'erreur (ou de succès).

+0

Il suppose un shell unix, cependant. – JesperE

+0

Merci, cela ressemble à un pas dans la bonne direction; souhaite qu'il pourrait être macro-comme sherr(), n'ont pas réussi jusqu'à présent. –

+0

Juste le mettre là, si vous êtes prêt à assumer Unix (je suis totalement), ce fut la seule variante que j'ai trouvé qui a fonctionné. Je faisais un non-sens total dans un 'define template' qui plus tard était' $ (eval $ (call template, arg1, arg2) '... ce qui était horrible, mais ça marche totalement avec ce qui précède, en faisant attention à doubler' $ $ '* tout *. J'espère que someboedy en profite un jour (le' @ 'au début est parce que je suis dans une définition cible):' @ $$ (si $$ (shell si ./generate.sh $ (2) $ (1), puis echo "score"; fi),, $$ (erreur Impossible de générer [$ (2)] à partir de [$ (1)])) ' – sjm324

4

Vous devez utiliser une cible régulière pour créer BuildRules.mk:

BuildRules.mk: collect_sources.py 
     python $< >[email protected] 

include BuildRules.mk 

C'est le truc standard pour utiliser lors de la génération automatique des dépendances.

+0

Jesper, merci pour votre contribution, mais je don Ne voyez pas comment votre règle peut résoudre mon problème.J'ai besoin de collect_sources.py pour exécuter à chaque fois, afin que je puisse mettre à jour la liste des fichiers et des règles source, etc –

+0

Ajoutez un ".PHONY: BuildRules. mk "en haut, alors – JesperE

+0

Peut-être qu'il me manque quelque chose d'évident ici, mais je n'arrive pas à le faire fonctionner correctement BuildRules.mk est refait à chaque fois (en utilisant .PHONY), mais l'inclusion se produit avant cette est fait, ce qui signifie que vous êtes toujours s en utilisant le BuildRules.mk précédent. – mweerden

-1

Assurez-vous de ne pas appeler make/gmake avec l'option -k.

+0

Votre suggestion semble logique, mais la vérité est que l'option '-k' n'a aucun effet sur le comportement de' make' en cas d'échec des commandes dans la fonction 'shell'. –