configurar - makefile windows
Variable Makefile como requisito previo (7)
Como veo, el comando necesita la variable ENV para que pueda verificarlo en el comando mismo:
.PHONY: deploy check-env
deploy: check-env
rsync . $(ENV).example.com:/var/www/myapp/
check-env:
if test "$(ENV)" = "" ; then /
echo "ENV not set"; /
exit 1; /
fi
En un archivo Makefile, una receta de deploy
necesita una variable de entorno ENV
para establecerse para ejecutarse correctamente, mientras que a otros no les importa, por ejemplo:
ENV =
.PHONY: deploy hello
deploy:
rsync . $(ENV).example.com:/var/www/myapp/
hello:
echo "I don''t care about ENV, just saying hello!"
¿Cómo puedo asegurarme de que esta variable esté configurada, por ejemplo, hay una forma de declarar esta variable de archivo MAKE como un requisito previo de la receta de implementación, como:
deploy: make-sure-ENV-variable-is-set
?
Gracias.
Esto causará un error fatal si ENV
no está definido y algo lo necesita (en GNUMake, de todos modos).
.PHONY: deploy check-env
deploy: check-env
...
other-thing-that-needs-env: check-env
...
check-env:
ifndef ENV
$(error ENV is undefined)
endif
(Tenga en cuenta que ifndef y endif no están sangrados, "$ (error" está indentado con espacios, no una pestaña; ellos controlan qué hace que "ve", surta efecto antes de que se ejecute Makefile ).
He encontrado que la mejor respuesta no se puede usar como un requisito, a excepción de otros objetivos de PHONY. Si se usa como una dependencia para un objetivo que es un archivo real, el uso de check-env
obligará a reconstruir el objetivo del archivo.
Otras respuestas son globales (p. Ej., La variable es necesaria para todos los objetivos en el Makefile) o utilizan el intérprete de comandos, por ejemplo, si faltara ENV, la marca terminaría independientemente del objetivo.
Una solución que encontré para ambos problemas es
ndef = $(if $(value $(1)),,$(error $(1) not set))
.PHONY: deploy
deploy:
$(call ndef,ENV)
echo "deploying $(ENV)"
.PHONY: build
build:
echo "building"
La salida se ve como
$ make build
echo "building"
building
$ make deploy
Makefile:5: *** ENV not set. Stop.
$ make deploy ENV="env"
echo "deploying env"
deploying env
$
value
tiene algunas advertencias atemorizantes, pero para este simple uso creo que es la mejor opción.
Puede crear un objetivo de guardia implícito, que verifica que la variable en el tallo esté definida, así:
guard-%:
@ if [ "${${*}}" = "" ]; then /
echo "Environment variable $* not set"; /
exit 1; /
fi
A continuación, agregue un objetivo guard-ENVVAR donde desee afirmar que se define una variable, como esta:
change-hostname: guard-HOSTNAME
./changeHostname.sh ${HOSTNAME}
Si llama a ''make change-hostname'', sin agregar HOSTNAME = somehostname en la llamada, entonces obtendrá un error y la compilación fallará.
Puede usar ifdef
lugar de un objetivo diferente.
.PHONY: deploy
deploy:
ifdef ENV
rsync . $(ENV).example.com:/var/www/myapp/
else
@echo 1>&2 "ENV must be set"
false # Cause deploy to fail
endif
Un posible problema con las respuestas dadas hasta ahora es que el orden de dependencia en make no está definido. Por ejemplo, ejecutando:
make -j target
cuando el target
tiene algunas dependencias no garantiza que se ejecutarán en un orden determinado.
La solución para esto (para garantizar que se verifique ENV antes de que se elijan las recetas) es verificar ENV durante el primer pase del fabricante, fuera de cualquier receta:
## Are any of the user''s goals dependent on ENV?
ifneq ($(filter deploy other-thing-that-needs-ENV,$(MAKECMDGOALS)),$())
ifndef ENV
$(error ENV not defined)
endif
endif
.PHONY: deploy
deploy: foo bar
...
other-thing-that-needs-ENV: bar baz bono
...
Puede leer sobre las diferentes funciones / variables utilizadas here y $()
es solo una manera de afirmar explícitamente que estamos comparando contra "nada".
Variante en línea
En mis makefiles, normalmente uso una expresión como:
deploy:
test -n "$(ENV)" # $$ENV
rsync . $(ENV).example.com:/var/www/myapp/
Las razones:
- es un simple trazador de líneas
- es compacto
- está ubicado cerca de los comandos que usan la variable
No olvides el comentario que es importante para la depuración:
test -n ""
Makefile:3: recipe for target ''deploy'' failed
make: *** [deploy] Error 1
... te obliga a buscar el Makefile mientras ...
test -n "" # $ENV
Makefile:3: recipe for target ''deploy'' failed
make: *** [deploy] Error 1
... explica directamente lo que está mal
Variante global (para completar, pero no se pide)
Además de tu Makefile, también puedes escribir:
ifeq ($(ENV),)
$(error ENV is not set)
endif
Advertencias:
- no use la pestaña en ese bloque
- use con cuidado: incluso el objetivo
clean
fallará si ENV no está configurado. De lo contrario, vea la respuesta de Hudon que es más compleja