run phony makefile

makefile - phony - Anula el archivo MAKE si la variable no está establecida



makefile windows (3)

Use la test función de shell:

foo: test $(something)

Uso:

$ make foo test Makefile:2: recipe for target ''foo'' failed make: *** [foo] Error 1 $ make foo something=x test x

¿Cómo podría abortar una ejecución de make / makefile en función de que la variable de un archivo MAKE no se haya establecido / valorado?

Se me ocurrió esto, pero funciona solo si la persona que llama no ejecuta explícitamente un objetivo (es decir, ejecuta solo).

ifeq ($(MY_FLAG),) abort: ## This MUST be the first target :( ugly @echo Variable MY_FLAG not set && false endif all: @echo MY_FLAG=$(MY_FLAG)

Creo que algo así sería una buena idea, pero no encontré nada en el manual de make:

ifndef MY_FLAG .ABORT endif


Utilice el manejo de errores de shell para las variables no establecidas (tenga en cuenta el doble $ ):

$ cat Makefile foo: echo "something is set to $${something:?}" $ make foo echo "something is set to ${something:?}" /bin/sh: something: parameter null or not set make: *** [foo] Error 127 $ make foo something=x echo "something is set to ${something:?}" something is set to x

Si necesita un mensaje de error personalizado, agréguelo después de ? :

$ cat Makefile hello: echo "hello $${name:?please tell me who you are via /$$name}" $ make hello echo "hello ${name:?please tell me who you are via /$name}" /bin/sh: name: please tell me who you are via $name make: *** [hello] Error 127 $ make hello name=jesus echo "hello ${name:?please tell me who you are via /$name}" hello jesus


TL; DR : use la función de error :

ifndef MY_FLAG $(error MY_FLAG is not set) endif

Tenga en cuenta que las líneas no deben estar sangradas. Más precisamente, no deben aparecer pestañas delante de estas líneas.

Solución genérica

En caso de que vaya a probar muchas variables, vale la pena definir una función auxiliar para eso:

# Check that given variables are set and all have non-empty values, # die with an error otherwise. # # Params: # 1. Variable name(s) to test. # 2. (optional) Error message to print. check_defined = / $(strip $(foreach 1,$1, / $(call __check_defined,$1,$(strip $(value 2))))) __check_defined = / $(if $(value $1),, / $(error Undefined $1$(if $2, ($2))))

Y aquí está cómo usarlo:

$(call check_defined, MY_FLAG) $(call check_defined, OUT_DIR, build directory) $(call check_defined, BIN_DIR, where to put binary artifacts) $(call check_defined, / LIB_INCLUDE_DIR / LIB_SOURCE_DIR, / library path)


Esto generaría un error como este:

Makefile:17: *** Undefined OUT_DIR (build directory). Stop.

Control específico del objetivo

También es posible ampliar la solución para que uno pueda requerir una variable solo si se invoca un determinado objetivo.

$(call check_defined, ...) desde el interior de la receta

Simplemente mueva el cheque a la receta:

foo : @:$(call check_defined, BAR, baz value)

El signo @ inicial apaga el eco del comando y : es el comando real, un código auxiliar sin shell.

Mostrando nombre de destino

La función check_defined se puede mejorar para generar también el nombre del objetivo (proporcionado a través de la variable $@ ):

check_defined = / $(strip $(foreach 1,$1, / $(call __check_defined,$1,$(strip $(value 2))))) __check_defined = / $(if $(value $1),, / $(error Undefined $1$(if $2, ($2))$(if $(value @), / required by target `$@'')))

Entonces, ahora un chequeo fallido produce un resultado muy formateado:

Makefile:7: *** Undefined BAR (baz value) required by target `foo''. Stop.

check-defined-MY_FLAG objetivo especial

Personalmente, usaría la solución simple y directa anterior. Sin embargo, por ejemplo, esta respuesta sugiere el uso de un objetivo especial para realizar el control real. Uno podría tratar de generalizar eso y definir el objetivo como una regla de patrón implícito:

# Check that a variable specified through the stem is defined and has # a non-empty value, die with an error otherwise. # # %: The name of the variable to test. # check-defined-% : __check_defined_FORCE @:$(call check_defined, $*, target-specific) # Since pattern rules can''t be listed as prerequisites of .PHONY, # we use the old-school and hackish FORCE workaround. # You could go without this, but otherwise a check can be missed # in case a file named like `check-defined-...` exists in the root # directory, e.g. left by an accidental `make -t` invocation. .PHONY : __check_defined_FORCE __check_defined_FORCE :

Uso:

foo :|check-defined-BAR

Observe que check-defined-BAR se enumera como el requisito previo order-only ( |... ).

Pros:

  • (discutible) una sintaxis más limpia

Contras:

  • No se puede especificar un mensaje de error personalizado
  • Ejecutar make -t (ver en lugar de ejecutar recetas ) contaminará tu directorio raíz con muchos archivos check-defined-... Este es un triste inconveniente del hecho de que las reglas de patrones no se pueden declarar .PHONY .

Creo que estas limitaciones se pueden superar usando algunas magic eval y hacks secundarios de expansión , aunque no estoy seguro de que valga la pena.