En un Makefile, una deploy
receta necesita ENV
que se configure una variable de entorno 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?
deploy: make-sure-ENV-variable-is-set
?
Gracias.
make
configurarlo, dar una advertencia o generar un error fatal?make ENV=dev
pero si se olvidaENV=dev
, ladeploy
receta fallará ...Respuestas:
Esto causará un error fatal si
ENV
no está definido y algo lo necesita (en GNUMake, de todos modos).(Tenga en cuenta que si ifndef y endif no están sangrados, controlan lo que hace "ve" , surten efecto antes de que se ejecute el Makefile. "$ (Error" está sangrado con una pestaña para que solo se ejecute en el contexto de la regla).
fuente
ENV is undefined
cuando ejecuto una tarea que no tiene check-env como requisito previo.check-env
regla; Make no lo expandirá a menos que / hasta que ejecute la regla. Si no comienza con una TAB (como en el ejemplo de @ rane), Make lo interpreta como si no estuviera en una regla y lo evalúa antes de ejecutar cualquier regla, independientemente del objetivo.Puede crear un objetivo de protección implícito, que verifique que la variable en la raíz esté definida, así:
Luego agrega un
guard-ENVVAR
objetivo en cualquier lugar donde desee afirmar que una variable está definida, como esta:Si llama
make change-hostname
, sin agregarHOSTNAME=somehostname
la llamada, obtendrá un error y la compilación fallará.fuente
if [ -z '${${*}}' ]; then echo 'Environment variable $* not set' && exit 1; fi
DVariante en línea
En mis archivos MAKE, normalmente uso una expresión como:
Las razones:
No olvide el comentario que es importante para la depuración:
... te obliga a buscar el Makefile mientras ...
... explica directamente lo que está mal
Variante global (para completar, pero no solicitada)
Además de tu Makefile, también puedes escribir:
Advertencias:
clean
objetivo fallará si no se establece ENV. De lo contrario, vea la respuesta de Hudon, que es más complejafuente
@
. -> gnu.org/software/make/manual/make.html#Echoing@test -n "$(name)" || (echo 'A name must be defined for the backup. Ex: make backup name=xyz' && exit 1)
Un posible problema con las respuestas dadas hasta ahora es que el orden de dependencia en make no está definido. Por ejemplo, ejecutando:
cuando
target
tiene algunas dependencias no garantiza que se ejecutarán en un orden determinado.La solución para esto (para garantizar que se verifique el ENV antes de elegir las recetas) es verificar el ENV durante la primera pasada, fuera de cualquier receta:
Puede leer sobre las diferentes funciones / variables utilizadas aquí y
$()
es solo una forma de declarar explícitamente que estamos comparando con "nada".fuente
He encontrado que la mejor respuesta no se puede usar como un requisito, a excepción de otros objetivos PHONY. Si se usa como una dependencia para un objetivo que es un archivo real, el uso
check-env
forzará la reconstrucción del objetivo del archivo.Otras respuestas son globales (por ejemplo, la variable se requiere para todos los objetivos en el Makefile) o usan el shell, por ejemplo, si faltaba ENV, make terminaría independientemente del objetivo.
Una solución que encontré para ambos problemas es
La salida se ve como
value
tiene algunas advertencias de miedo, pero para este uso simple, creo que es la mejor opción.fuente
Como veo, el comando en sí necesita la variable ENV para que pueda verificarlo en el comando en sí:
fuente
deploy
no es necesariamente la única receta que necesita esta variable. Con esta solución, tengo que probar el estado deENV
cada uno ... mientras me gustaría tratarlo como un prerrequisito único (más o menos).Sé que esto es viejo, pero pensé en compartir con mis propias experiencias para futuros visitantes, ya que es un poco más ordenado en mi humilde opinión.
Normalmente,
make
se usarásh
como su shell predeterminado ( establecido a través de laSHELL
variable especial ). Ensh
y sus derivados, es trivial salir con un mensaje de error al recuperar una variable de entorno si no se establece o es nulo al hacer:${VAR?Variable VAR was not set or null}
.Extendiendo esto, podemos escribir un objetivo de fabricación reutilizable que se puede utilizar para fallar otros objetivos si no se estableció una variable de entorno:
Cosas de nota:
$$
requiere el signo de dólar escapado ( ) para diferir la expansión al shell en lugar de dentro demake
test
es solo para evitar que el shell intente ejecutar el contenido deVAR
(no sirve para ningún otro propósito significativo).check-env-vars
se puede extender trivialmente para buscar más variables de entorno, cada una de las cuales agrega solo una línea (por ejemplo@test $${NEWENV?Please set environment variable NEWENV}
)fuente
ENV
contiene espacios, esto parece fallar (al menos para mí)Puede usar en
ifdef
lugar de un objetivo diferente.fuente
deploy
no es la única receta que tiene que verificar laENV
variable de estado..PHONY: deploy
ydeploy:
antes del bloque ifdef y elimine la duplicación. (por cierto, he editado la respuesta para reflejar el método correcto)