¿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.
automake
script 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
PATH
lugar 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
which
ejecutable (where
en Windows), en lugar de confiar en que haya una--version
opción en cada ejecutable, directamente en laifeq
directiva GNU Make , en lugar de definir una nueva variable y usar GNU Makeerror
función para detener la compilación si un ejecutable requerido no está en${PATH}
. Por ejemplo, para probar ellzop
ejecutable:Si tiene varios ejecutables para verificar, entonces es posible que desee usar una
foreach
función con elwhich
ejecutable: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>NUL
lugar dewhich
.Bash
, no es necesario realizar una llamada externa awhich
. Utilice el integrado en sucommand -v
lugar. 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óncommand
es un bash incorporado, para mayor portabilidad, considere usarwhich
?command
requiere la utilidad (incluida la opción) Por otro lado, no tiene un comportamiento estandarizado (que yo sepa) y, a veces, es completamente inutilizable-v
which
command -v
requiere un entorno de shell similar a POSIX. Esto no funcionará en Windows sin cygwin o una emulación similar.command
menudo 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
shell
funció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 found
ifdef
evaluará verdadero incluso siyour_program
no existe gnu.org/software/make/manual/make.html#Conditional-Syntaxifdef
,else
,endif
líneas. Solo asegúrate de que las@echo
líneas comiencen con tabulaciones.ifdef
verifica el valor de la variable no vacía. Si su variable no está vacía, ¿a qué se evalúa?ifdef
oifndef
(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
make
invocación.check_cmds.sh
Makefile
1
command -v
Puede encontrar más información sobre la técnica aquí .fuente
if
declaració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 foo
ocommand -v foo
, como se muestra a continuación:¿Dónde
foo
está tu programa / comando? Redirigir a> /dev/null
si 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
require
objetivo 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
STDERR
salida de--version
no funcionan para programas que imprimen su versión enSTDOUT
lugar deSTDERR
. En lugar de verificar su salida aSTDERR
oSTDOUT
, verifique el código de retorno del programa. Si el programa no existe, su código de salida siempre será distinto de cero.fuente