¿Cómo puedo comprobar si se puede llamar a un programa desde un Makefile?
(Es decir, el programa debe existir en la ruta o ser invocable).
Podría usarse para verificar qué compilador está instalado, por ejemplo.
Por ejemplo, algo como esta pregunta , pero sin asumir que el shell subyacente es compatible con POSIX.

automakescript que verifique varios requisitos previos y escriba un archivoMakefile.Respuestas:
A veces, necesita un archivo Makefile para poder ejecutarse en diferentes sistemas operativos de destino y desea que la compilación falle antes si un ejecutable requerido no está en
PATHlugar de ejecutarse durante un tiempo posiblemente largo antes de fallar.La excelente solución proporcionada por Engineerchuan requiere hacer un objetivo . Sin embargo, si tiene muchos ejecutables para probar y su Makefile tiene muchos objetivos independientes, cada uno de los cuales requiere las pruebas, entonces cada objetivo requiere el objetivo de prueba como una dependencia. Eso genera una gran cantidad de escritura adicional, así como tiempo de procesamiento cuando crea más de un objetivo a la vez.
La solución proporcionada por 0xf puede probar un ejecutable sin hacer un objetivo. Eso ahorra mucho tiempo de escritura y ejecución cuando hay varios objetivos que se pueden construir por separado o juntos.
Mi mejora con respecto a la última solución es usar el
whichejecutable (whereen Windows), en lugar de confiar en que haya una--versionopción en cada ejecutable, directamente en laifeqdirectiva GNU Make , en lugar de definir una nueva variable y usar GNU Makeerrorfunción para detener la compilación si un ejecutable requerido no está en${PATH}. Por ejemplo, para probar ellzopejecutable:Si tiene varios ejecutables para verificar, entonces es posible que desee usar una
foreachfunción con elwhichejecutable:Tenga en cuenta el uso del
:=operador de asignación que se requiere para forzar la evaluación inmediata de la expresión RHS. Si su Makefile cambiaPATH, entonces en lugar de la última línea de arriba necesitará:Esto debería darle un resultado similar a:
fuente
where my_exe 2>NULlugar dewhich.Bash, no es necesario realizar una llamada externa awhich. Utilice el integrado en sucommand -vlugar. Más info .Mezclé las soluciones de @kenorb y @ 0xF y obtuve esto:
Funciona de maravilla porque "command -v" no imprime nada si el ejecutable no está disponible, por lo que la variable DOT nunca se define y puede verificarla cuando lo desee en su código. En este ejemplo, arrojo un error, pero podría hacer algo más útil si quisiera.
Si la variable está disponible, "comando -v" realiza la operación económica de imprimir la ruta del comando, definiendo la variable DOT.
fuente
$(shell command -v dot)falla conmake: command: Command not found. Para solucionar este problema, la salida stderr redirección a / dev / null:$(shell command -v dot 2> /dev/null). Explicacióncommandes un bash incorporado, para mayor portabilidad, considere usarwhich?commandrequiere la utilidad (incluida la opción) Por otro lado, no tiene un comportamiento estandarizado (que yo sepa) y, a veces, es completamente inutilizable-vwhichcommand -vrequiere un entorno de shell similar a POSIX. Esto no funcionará en Windows sin cygwin o una emulación similar.commandmenudo no funciona no es por su ausencia , sino por una optimización peculiar que hace GNU Make: si un comando es "suficientemente simple", saltará el shell; desafortunadamente, esto significa que los elementos integrados a veces no funcionarán a menos que modifique un poco el comando.¿Es esto lo que hiciste?
crédito a mi compañero de trabajo.
fuente
Utilice la
shellfunción para llamar a su programa de manera que imprima algo en la salida estándar. Por ejemplo, pase--version.GNU Make ignora el estado de salida del comando pasado
shell. Para evitar el mensaje potencial "comando no encontrado", redirija el error estándar a/dev/null.A continuación puede consultar el resultado utilizando
ifdef,ifndef,$(if)etc.Como beneficio adicional, la salida (como la versión del programa) puede ser útil en otras partes de su Makefile.
fuente
*** missing separator. Stop.Si agrego pestañas en todas las líneas después deall:recibir el errormake: ifdef: Command not foundifdefevaluará verdadero incluso siyour_programno existe gnu.org/software/make/manual/make.html#Conditional-Syntaxifdef,else,endiflíneas. Solo asegúrate de que las@echolíneas comiencen con tabulaciones.ifdefverifica el valor de la variable no vacía. Si su variable no está vacía, ¿a qué se evalúa?ifdefoifndef(como en la respuesta aceptada) solo funciona si la variable que se evalúa se establece inmediatamente (:=) en lugar de establecer perezosamente (=). Sin embargo, una desventaja de usar variables establecidas inmediatamente es que se evalúan en el momento de la declaración, mientras que las variables establecidas de forma perezosa se evalúan cuando se llaman. Esto significa que estaría ejecutando comandos para variables con:=incluso cuando Make solo ejecuta reglas que nunca usan esas variables. Puede evitar esto usando un=conifneq ($(MY_PROG),)Limpió algunas de las soluciones existentes aquí ...
El
$(info ...)puede excluir si quieres que esto sea más silencioso.Esto fallará rápidamente . No se requiere objetivo.
fuente
Mi solución implica un pequeño script auxiliar 1 que coloca un archivo de bandera si existen todos los comandos necesarios. Esto tiene la ventaja de que la verificación de los comandos requeridos solo se realiza una vez y no en cada
makeinvocación.check_cmds.sh
Makefile
1
command -vPuede encontrar más información sobre la técnica aquí .fuente
ifdeclaración.Para mí, todas las respuestas anteriores se basan en Linux y no funcionan con Windows. Soy nuevo en hacer, por lo que mi enfoque puede no ser el ideal. Pero el ejemplo completo que funciona para mí tanto en Linux como en Windows es este:
opcionalmente, cuando necesito detectar más herramientas que puedo usar:
fuente
Puede usar comandos integrados en bash como
type fooocommand -v foo, como se muestra a continuación:¿Dónde
fooestá tu programa / comando? Redirigir a> /dev/nullsi lo desea en silencio.fuente
Suponga que tiene diferentes objetivos y constructores, cada uno requiere otro conjunto de herramientas. Establezca una lista de tales herramientas y considérelas como objetivo para forzar la verificación de su disponibilidad.
Por ejemplo:
fuente
Personalmente estoy definiendo un
requireobjetivo que se ejecuta antes que todos los demás. Este objetivo simplemente ejecuta los comandos de versión de todos los requisitos uno a la vez e imprime los mensajes de error apropiados si el comando no es válido.La salida del siguiente script es
fuente
Resuelto compilando un pequeño programa especial en otro destino de archivo MAKE, cuyo único propósito es verificar cualquier material de tiempo de ejecución que esté buscando.
Luego, llamé a este programa en otro destino de archivo MAKE.
Era algo como esto si no recuerdo mal:
fuente
Las soluciones que comprueban la
STDERRsalida de--versionno funcionan para programas que imprimen su versión enSTDOUTlugar deSTDERR. En lugar de verificar su salida aSTDERRoSTDOUT, verifique el código de retorno del programa. Si el programa no existe, su código de salida siempre será distinto de cero.fuente