Definir make variável em tempo de execução da regra
Pergunta
Na minha GNUmakefile, eu gostaria de ter uma regra que usa um diretório temporário. Por exemplo:
out.tar: TMP := $(shell mktemp -d)
echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
Como escrito, a regra acima cria o diretório temporário no momento em que a regra é analisado . Isto significa que, mesmo que eu não faça out.tar todo o tempo, muitos diretórios temporários são criados. Eu gostaria de evitar o meu / tmp sendo repleta de diretórios temporários não utilizados.
Existe uma maneira de fazer com que a variável a ser apenas definido quando a regra é disparada, ao contrário de quando ele é definido?
Meu pensamento principal é para despejar o mktemp e alcatrão em um shell script, mas que parece um pouco sem graça.
Solução
No seu exemplo, a variável TMP
está definido (e o diretório temporário criado) sempre que o regras para out.tar
são avaliados. A fim de criar o diretório somente quando out.tar
é realmente demitido, você precisa mover a criação de diretório para baixo nas etapas:
out.tar :
$(eval TMP := $(shell mktemp -d))
@echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
O href="http://www.gnu.org/software/make/manual/make.html#Eval-Function" rel="noreferrer"> eval função TMP ao resultado da chamada de função shell
.
Editar (em resposta aos comentários):
Para criar uma variável única, você pode fazer o seguinte:
out.tar :
$(eval $@_TMP := $(shell mktemp -d))
@echo hi $($@_TMP)/hi.txt
tar -C $($@_TMP) cf $@ .
rm -rf $($@_TMP)
Isto prefixar o nome do alvo (out.tar, neste caso) para a variável, produzindo uma variável com o nome out.tar_TMP
. Felizmente, isso é suficiente para evitar conflitos.
Outras dicas
Uma maneira relativamente fácil de fazer isso é escrever a seqüência inteira como um script shell.
out.tar:
set -e ;\
TMP=$$(mktemp -d) ;\
echo hi $$TMP/hi.txt ;\
tar -C $$TMP cf $@ . ;\
rm -rf $$TMP ;\
Eu consolidaram algumas dicas relacionadas aqui: https://stackoverflow.com/a/29085684/86967
Outra possibilidade é utilizar linhas separadas para configurar variáveis ??tornam quando uma regra de incêndios.
Por exemplo, aqui está um makefile com duas regras. Se uma regra incêndios, ele cria um dir temperatura e define TMP para o nome Temp dir.
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}
A execução do código produz o resultado esperado:
$ ls
Makefile
$ make ruleB
echo testruleB_Y4Ow
testruleB_Y4Ow
$ ls
Makefile testruleB_Y4Ow