Definir variable de maquillaje en el tiempo de ejecución de reglas
Pregunta
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)
Como está escrito, la regla anterior crea el directorio temporal en el momento que la regla es analizada . Esto significa que, aunque no hago out.tar todo el tiempo, muchos directorios temporales se crean. Me gustaría evitar mi / tmp está llena de directorios temporales no utilizados.
¿Hay una manera de hacer que la variable que sólo se define cuando se dispara la regla, en lugar de cada vez que se define?
Mi idea principal es para volcar el mktemp y alquitrán en un script de shell, pero que parece un poco desagradable.
Solución
En el ejemplo, se establece la variable TMP
(y el directorio temporal creado) cada vez que se evalúan los reglas para out.tar
. Con el fin de crear el directorio sólo cuando out.tar
es en realidad despedido, tiene que 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)
El href="http://www.gnu.org/software/make/manual/make.html#Eval-Function" rel="noreferrer"> eval función TMP al resultado de la llamada a la función shell
.
editar (en respuesta a los comentarios):
Para crear una variable única, se puede hacer lo siguiente:
out.tar :
$(eval $@_TMP := $(shell mktemp -d))
@echo hi $($@_TMP)/hi.txt
tar -C $($@_TMP) cf $@ .
rm -rf $($@_TMP)
Esto anteponer el nombre del destino (out.tar, en este caso) a la variable, produciendo una variable con el nombre out.tar_TMP
. Con suerte, eso es suficiente para evitar conflictos.
Otros consejos
Una forma relativamente fácil de hacer esto es escribir la secuencia entera como una secuencia de comandos 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
Otra posibilidad es utilizar líneas separadas para establecer Hacer variables cuando se activa una regla.
Por ejemplo, aquí es un makefile con dos reglas. Si se activa una regla, se crea un directorio temporal y establece TMP al nombre de 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}
Al ejecutar el código produce el resultado esperado:
$ ls
Makefile
$ make ruleB
echo testruleB_Y4Ow
testruleB_Y4Ow
$ ls
Makefile testruleB_Y4Ow