Comment puis-je vérifier si un programme peut être appelé à partir d'un Makefile?
(Autrement dit, le programme doit exister dans le chemin ou être appelable d'une autre manière.)
Il pourrait être utilisé pour vérifier pour quel compilateur est installé, par exemple.
Par exemple, quelque chose comme cette question , mais sans supposer que le shell sous-jacent est compatible POSIX.
automake
script qui vérifie les différents prérequis et écrit un fichier appropriéMakefile
.Réponses:
Parfois, vous avez besoin d'un Makefile pour pouvoir s'exécuter sur différents OS cibles et vous voulez que la construction échoue tôt si un exécutable requis n'est pas dans
PATH
plutôt que de s'exécuter pendant une période éventuellement longue avant d'échouer.L'excellente solution fournie par engineerchuan nécessite de faire une cible . Cependant, si vous avez de nombreux exécutables à tester et que votre Makefile a de nombreuses cibles indépendantes, dont chacune nécessite les tests, alors chaque cible nécessite la cible de test en tant que dépendance. Cela entraîne beaucoup de frappe supplémentaire ainsi que du temps de traitement lorsque vous créez plus d'une cible à la fois.
La solution fournie par 0xf peut tester un exécutable sans faire de cible. Cela économise beaucoup de temps de frappe et d'exécution lorsqu'il y a plusieurs cibles qui peuvent être construites séparément ou ensemble.
Mon amélioration de cette dernière solution est d'utiliser l'
which
exécutable (where
sous Windows), plutôt que de compter sur l'existence d'une--version
option dans chaque exécutable, directement dans laifeq
directive GNU Make , plutôt que de définir une nouvelle variable, et d'utiliser le GNU Makeerror
pour arrêter la construction si un exécutable requis n'est pas dans${PATH}
. Par exemple, pour tester l'lzop
exécutable:Si vous avez plusieurs exécutables à vérifier, vous pouvez utiliser une
foreach
fonction avec l'which
exécutable:Notez l'utilisation de l'
:=
opérateur d'affectation qui est requis pour forcer l'évaluation immédiate de l'expression RHS. Si votre Makefile change lePATH
, alors au lieu de la dernière ligne ci-dessus, vous aurez besoin de:Cela devrait vous donner une sortie similaire à:
la source
where my_exe 2>NUL
place dewhich
.Bash
, il n'est pas nécessaire de passer un appel externe verswhich
. Utilisezcommand -v
plutôt la fonction intégrée . Plus d'infos .J'ai mélangé les solutions de @kenorb et @ 0xF et j'ai obtenu ceci:
Cela fonctionne à merveille car "commande -v" n'affiche rien si l'exécutable n'est pas disponible, donc la variable DOT n'est jamais définie et vous pouvez simplement la vérifier quand vous le souhaitez dans votre code. Dans cet exemple, je lance une erreur, mais vous pouvez faire quelque chose de plus utile si vous le souhaitez.
Si la variable est disponible, "commande -v" effectue l'opération peu coûteuse d'impression du chemin de commande, définissant la variable DOT.
la source
$(shell command -v dot)
échoue avecmake: command: Command not found
. Pour résoudre ce problème, redirect stderr vers / dev / null:$(shell command -v dot 2> /dev/null)
. Explicationcommand
est un bash intégré, pour plus de portabilité, envisagez d'utiliserwhich
?command
utilitaire est requis par posix (y compris l'-v
option) Par contrewhich
n'a pas de comportement standardisé (que je connaisse) et est parfois carrément inutilisablecommand -v
nécessite un environnement shell de type POSIX. Cela ne fonctionnera pas sous Windows sans cygwin ou une émulation similaire.command
souvent ne fonctionne pas n'est pas à cause de son absence , mais à cause d'une optimisation particulière que fait GNU Make: si une commande est "assez simple", elle contournera le shell; cela signifie malheureusement que les fonctions intégrées ne fonctionneront parfois pas à moins que vous ne modifiiez un peu la commande.C'est ce que tu as fait?
crédit à mon collègue.
la source
Utilisez la
shell
fonction pour appeler votre programme de manière à ce qu'il imprime quelque chose sur la sortie standard. Par exemple, passez--version
.GNU Make ignore l'état de sortie de la commande passée à
shell
. Pour éviter le message potentiel «commande introuvable», redirigez l'erreur standard vers/dev/null
.Ensuite , vous pouvez vérifier le résultat en utilisant
ifdef
,ifndef
,$(if)
etc.En prime, la sortie (telle que la version du programme) peut être utile dans d'autres parties de votre Makefile.
la source
*** missing separator. Stop.
Si j'ajoute des onglets à toutes les lignes aprèsall:
une erreurmake: ifdef: Command not found
ifdef
évaluera vrai même s'ilyour_program
n'existe pas gnu.org/software/make/manual/make.html#Conditional-Syntaxifdef
,else
,endif
lignes. Assurez-vous simplement que les@echo
lignes commencent par des onglets.ifdef
valeur de la variable n'est pas vide. Si votre variable n'est pas vide, à quoi s'évalue-t-elle?ifdef
ouifndef
(comme dans la réponse acceptée) ne fonctionne que si la variable évaluée est immédiatement set (:=
) au lieu de paresseusement set (=
). Cependant, un inconvénient de l'utilisation de variables définies immédiatement est qu'elles sont évaluées au moment de la déclaration, tandis que les variables définies paresseusement sont évaluées lorsqu'elles sont appelées. Cela signifie que vous exécuteriez des commandes pour des variables:=
même si Make n'exécute que des règles qui n'utilisent jamais ces variables! Vous pouvez éviter cela en utilisant un=
avecifneq ($(MY_PROG),)
Nettoyé certaines des solutions existantes ici ...
le
$(info ...)
vous pouvez exclure si vous voulez que ce soit plus calme.Cela échouera rapidement . Aucune cible requise.
la source
Ma solution implique un petit script d'aide 1 qui place un fichier indicateur si toutes les commandes requises existent. Cela présente l'avantage que la vérification des commandes requises n'est effectuée qu'une seule fois et non toutes les
make
appel.check_cmds.sh
Makefile
1 Pour en savoir plus sur la
command -v
technique, cliquez ici .la source
if
instruction.Pour moi, toutes les réponses ci-dessus sont basées sur Linux et ne fonctionnent pas avec Windows. Je suis nouveau à faire, donc mon approche n'est peut-être pas idéale. Mais un exemple complet qui fonctionne pour moi à la fois sous Linux et Windows est le suivant:
éventuellement lorsque j'ai besoin de détecter plus d'outils que je peux utiliser:
la source
Vous pouvez utiliser des commandes intégrées bash telles que
type foo
oucommand -v foo
, comme ci-dessous:Où
foo
est votre programme / commande. Redirigez vers> /dev/null
si vous le souhaitez silencieux.la source
Supposons que vous ayez des cibles et des constructeurs différents, chacun nécessitant un autre ensemble d'outils. Définissez une liste de ces outils et considérez-les comme une cible pour forcer la vérification de leur disponibilité
Par exemple:
la source
Je définis personnellement un
require
objectif qui passe avant tous les autres. Cette cible exécute simplement les commandes de version de toutes les exigences une par une et imprime les messages d'erreur appropriés si la commande n'est pas valide.La sortie du script ci-dessous est
la source
Résolu en compilant un petit programme spécial dans une autre cible de makefile, dont le seul but est de vérifier les éléments d'exécution que je recherchais.
Ensuite, j'ai appelé ce programme dans une autre cible de makefile.
C'était quelque chose comme ça si je me souviens bien:
la source
Les solutions vérifiant la
STDERR
sortie de--version
ne fonctionnent pas pour les programmes qui impriment leur version à laSTDOUT
place deSTDERR
. Au lieu de vérifier leur sortie versSTDERR
ouSTDOUT
, vérifiez le code de retour du programme. Si le programme n'existe pas, son code de sortie sera toujours différent de zéro.la source