Define make variable at rule execution time

W moim GNUmakefile chciałbym mieć regułę, która używa katalogu tymczasowego. Na przykład:

out.tar: TMP := $(shell mktemp -d)
        echo hi $(TMP)/hi.txt
        tar -C $(TMP) cf $@ .
        rm -rf $(TMP)

Zgodnie z zapisem powyższa reguła tworzy katalog tymczasowy w czasie, gdy reguła jest przetwarzana . To oznacza, że nawet ja się nie całuję.tar cały czas tworzy się wiele katalogów tymczasowych. Chciałbym, aby mój /tmp nie był zaśmiecony nieużywanymi katalogami tymczasowymi.

Czy istnieje sposób, aby zmienna była zdefiniowana tylko wtedy, gdy reguła jest wywołana, w przeciwieństwie do ilekroć jest zdefiniowana?

Moją główną myślą jest wrzucenie mktemp i tar do skryptu powłoki, ale wydaje się to nieco nieestetyczne.

Author: Emil Sit, 2009-12-15

3 answers

W twoim przykładzie zmienna TMP jest ustawiana (i tworzony jest katalog tymczasowy) za każdym razem, gdy oceniane są reguły dla out.tar. Aby utworzyć katalog tylko wtedy, gdy out.tar jest rzeczywiście zwolniony, musisz przenieść tworzenie katalogu w dół do kroków:

out.tar : 
    $(eval TMP := $(shell mktemp -d))
    @echo hi $(TMP)/hi.txt
    tar -C $(TMP) cf $@ .
    rm -rf $(TMP)

Funkcja eval ocenia łańcuch znaków tak, jakby został wpisany do pliku makefile ręcznie. W tym przypadku ustawia zmienną TMP na wynik funkcji shell sprawdzam.

Edit (w odpowiedzi na komentarze):

Aby utworzyć unikalną zmienną, możesz wykonać następujące czynności:

out.tar : 
    $(eval $@_TMP := $(shell mktemp -d))
    @echo hi $($@_TMP)/hi.txt
    tar -C $($@_TMP) cf $@ .
    rm -rf $($@_TMP)

To będzie poprzedzać nazwę celu (out.tar, w tym przypadku) do zmiennej, tworząc zmienną o nazwie out.tar_TMP. Miejmy nadzieję, że to wystarczy, aby zapobiec konfliktom.

 232
Author: e.James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-15 22:18:59

Stosunkowo łatwym sposobem na to jest napisanie całej sekwencji jako skryptu powłoki.

out.tar:
   set -e ;\
   TMP=$$(mktemp -d) ;\
   echo hi $$TMP/hi.txt ;\
   tar -C $$TMP cf $@ . ;\
   rm -rf $$TMP ;\

Zebrałem kilka powiązanych porad tutaj: https://stackoverflow.com/a/29085684/86967

 37
Author: nobar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:43

Inną możliwością jest użycie osobnych linii do Ustawienia zmiennych Make, gdy reguła zostanie wywołana.

Na przykład, oto plik makefile z dwiema zasadami. Jeśli reguła zostanie wywołana, utworzy katalog temp i ustawi tmp na nazwę katalogu temp.

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}

Uruchomienie kodu daje oczekiwany wynik:

$ ls
Makefile
$ make ruleB
echo testruleB_Y4Ow
testruleB_Y4Ow
$ ls
Makefile  testruleB_Y4Ow
 23
Author: user3124434,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-21 01:32:21