Definir make variable en tiempo de ejecución de la regla
En mi GNUmakefile, me gustaría tener una regla que utiliza un directorio temporal. Por ejemplo:
out.tar: TMP := $(shell mktemp -d)
echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
Tal como está escrito, la regla anterior crea el directorio temporal en el momento en que la regla se analiza . Esto significa que, ni siquiera yo lo hago.tar todo el tiempo, muchos directorios temporales se crean. Me gustaría evitar que mi /tmp esté lleno de directorios temporales no utilizados.
Hay una manera de hacer que la variable solo se defina cuando se dispara la regla, a diferencia de cada vez que se define?
Mi pensamiento principal es volcar el mktemp y tar en un script de shell, pero eso parece algo antiestético.
3 answers
En su ejemplo, la variable TMP
se establece (y el directorio temporal se crea) cada vez que se evalúan las reglas para out.tar
. Para crear el directorio solo cuando out.tar
está realmente activado, necesita mover la creación del directorio hacia abajo en los pasos:
out.tar :
$(eval TMP := $(shell mktemp -d))
@echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
La función eval evalúa una cadena como si hubiera sido escrita en el makefile manualmente. En este caso, establece la variable TMP
al resultado de la función shell
llamada.
Editar (en respuesta a los comentarios):
Para crear una variable única, puede hacer lo siguiente:
out.tar :
$(eval $@_TMP := $(shell mktemp -d))
@echo hi $($@_TMP)/hi.txt
tar -C $($@_TMP) cf $@ .
rm -rf $($@_TMP)
Esto precedería el nombre del objetivo (out.tar, en este caso) a la variable, produciendo una variable con el nombre out.tar_TMP
. Esperemos que eso sea suficiente para prevenir los conflictos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-15 22:18:59
Una forma relativamente fácil de hacer esto es escribir toda la secuencia como un script de shell.
out.tar:
set -e ;\
TMP=$$(mktemp -d) ;\
echo hi $$TMP/hi.txt ;\
tar -C $$TMP cf $@ . ;\
rm -rf $$TMP ;\
He consolidado algunos consejos relacionados aquí: https://stackoverflow.com/a/29085684/86967
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:43
Otra posibilidad es usar líneas separadas para configurar las variables Make cuando se dispara una regla.
Por ejemplo, aquí hay un makefile con dos reglas. Si una regla se dispara, crea un directorio temporal y establece TMP en el nombre del directorio temporal.
PHONY = ruleA ruleB display
all: ruleA
ruleA: TMP = $(shell mktemp -d testruleA_XXXX)
ruleA: display
ruleB: TMP = $(shell mktemp -d testruleB_XXXX)
ruleB: display
display:
echo ${TMP}
Ejecutar el código produce el resultado esperado:
$ ls
Makefile
$ make ruleB
echo testruleB_Y4Ow
testruleB_Y4Ow
$ ls
Makefile testruleB_Y4Ow
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-21 01:32:21