tutorial make español comando makefile gnu

español - Probar si un archivo existe en el destino de makefile, y salir si no está presente



makefile linux c (5)

Cada línea de comando en make se ejecuta en su propio sub-shell. Por lo tanto, ejecutar exit solo sale de ese sub-shell, no el archivo make en su totalidad. De forma predeterminada, la ejecución de la ejecución se detendrá si cualquier sub-shell devuelve un estado de salida sin éxito (por convención, 0 significa éxito, por lo que cualquier otra cosa detendrá la ejecución). El método más simple sería utilizar el estado de salida del comando de test :

all: foo foo: test -s /opt/local/bin/gsort

Imprimir un mensaje de diagnóstico complica un poco las cosas porque los comandos como echo devolverán un estado de salida de 0, lo que make que todo esté bien. Para solucionar esto, debe ejecutar un comando después de él que le dará al sub-shell un estado de salida distinto de cero:

all: foo foo: test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; }

o incluso simplemente

all: foo foo: test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; false; }

¿Hay alguna manera de salir con una condición de error si no existe un archivo? Actualmente estoy haciendo algo como esto:

all: foo foo: test -s /opt/local/bin/gsort || echo "GNU sort does not exist! Exiting..." && exit

Ejecutar make ejecuta el objetivo all , que ejecuta foo .

La expectativa es que si la test -s condicional falla, entonces se ejecutan las sentencias echo/exit .

Sin embargo, incluso si existe /usr/bin/gsort , obtengo el resultado de la instrucción echo pero el comando exit no se ejecuta. Esto es lo contrario de lo que espero lograr.

¿Cuál es la forma correcta de hacer algo como lo anterior?


Me doy cuenta de que esto es un poco viejo en este momento, pero no es necesario que uses una subshell para probar si existe un archivo en Make.

También depende de cómo quieras / esperes que se ejecute.

Usando la función de comodín, así:

all: foo foo: ifeq (,$(wildcard /opt/local/bin/gsort)) $(error GNU Sort does not exist!) endif

Es una buena manera de hacerlo. Tenga en cuenta que la cláusula ifeq no tiene sangría porque se evalúa antes que el objetivo en sí.

Si desea que esto suceda sin condiciones para cada objetivo, simplemente puede moverlo fuera de un objetivo:

ifeq (,$(wildcard /opt/local/bin/gsort)) $(error GNU Sort does not exist!) endif


Simplemente haz:

all: /opt/local/bin/gsort

y si falta /opt/local/bin/gsort , aparecerá un mensaje de error "no hay regla para hacer que el objetivo` / opt / local / bin / gsort ''".

Pero si también quieres una buena explicación, hazlo:

/opt/local/bin/gsort: echo "GNU sort does not exist! Exiting..." false

En GNU / Make si el destino no está declarado .PHONEY y no tiene ninguna dependencia, se invocará la regla si no existe un archivo que coincida con ese objetivo.

El código anterior activará el comando false solo cuando /opt/local/bin/gsort no existe, devolverá un valor distinto de 0 y la marca fallará.


Ya que está verificando si existe el archivo ejecutable gsort , puede usar which o el comando de shell para eso, por ejemplo:

all: foo : foo: which gsort || exit 1 # or type gsort || exit 1

No necesita un mensaje de error, ya que se imprimirá automáticamente:

/ bin / sh: línea 0: tipo: gsort : no encontrado

que es obvio

Alternativamente, use test o [ (ver: help test / help [ para sintaxis), por ejemplo,

test -x /opt/local/bin/gsort || { echo Error msg; exit 1; }

que comprueba si el archivo dado existe y es ejecutable, de lo contrario muestra el mensaje y sale. Los paréntesis son importantes para anular la precedencia normal de los operadores (de izquierda a derecha) agrupando los comandos (consulte la sección Compound Commands en man bash para obtener más información).

Otra forma es usar los objetivos de la regla para verificar si el archivo existe y agregar como dependencia a all , por ejemplo,

all: /opt/local/bin/gsort @echo Success. /opt/local/bin/gsort: @echo "GNU sort does not exist! Exiting..." exit 1

Resultado:

$ make GNU sort does not exist! Exiting... exit 1 make: *** [/opt/local/bin/gsort] Error 1


solo exit devuelve el estado del último comando ejecutado. En este caso, devuelve cero, lo que significa que todo está bien.

Esto es, porque || y && tienen la misma prioridad , y el shell interpreta el comando como si estuviera escrito

( test ... || echo ... ) && exit

Si desea señalar una falla, debe salir con un valor que no sea cero, por ejemplo, la exit 1 . Y si desea hacer eco y salir, simplemente ponga los comandos en secuencia separados por ;

all: foo foo: test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; }