私のGNUmakefileには、一時ディレクトリを使用するルールが必要です。例えば:
out.tar: TMP := $(Shell mktemp -d)
echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
書かれているように、上記のルールは、ルールが解析済みのときに一時ディレクトリを作成します。これは、out.tarを常に作成しなくても、多くの一時ディレクトリが作成されることを意味します。/tmpに未使用の一時ディレクトリが散らばらないようにしたいと思います。
ルールが定義されているときではなく、ルールが起動されたときにのみ変数を定義する方法はありますか?
私の主な考えは、mktempとtarをシェルスクリプトにダンプすることですが、それはやや見苦しいようです。
この例では、out.tar
のrulesが評価されるたびに、TMP
変数が設定されます(および一時ディレクトリが作成されます)。 out.tar
が実際に起動されたときにのみディレクトリを作成するには、ディレクトリの作成をステップに移動する必要があります。
out.tar :
$(eval TMP := $(Shell mktemp -d))
@echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
eval 関数は、makefileに手動で入力されたかのように文字列を評価します。この場合、TMP
変数をShell
関数呼び出しの結果に設定します。
edit(コメントへの応答):
一意の変数を作成するには、次を実行できます。
out.tar :
$(eval $@_TMP := $(Shell mktemp -d))
@echo hi $($@_TMP)/hi.txt
tar -C $($@_TMP) cf $@ .
rm -rf $($@_TMP)
これにより、ターゲット名(この場合はout.tar)が変数に追加され、out.tar_TMP
という名前の変数が生成されます。うまくいけば、競合を防ぐのに十分です。
これを行う比較的簡単な方法は、シーケンス全体をシェルスクリプトとして記述することです。
out.tar:
set -e ;\
TMP=$$(mktemp -d) ;\
echo hi $$TMP/hi.txt ;\
tar -C $$TMP cf $@ . ;\
rm -rf $$TMP ;\
関連するヒントをここにまとめました: https://stackoverflow.com/a/29085684/86967
別の可能性は、ルールが実行されるときにMake変数を設定するために別々の行を使用することです。
たとえば、次の2つのルールを持つメイクファイルです。ルールが実行されると、一時ディレクトリが作成され、TMPが一時ディレクトリ名に設定されます。
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}
コードを実行すると、予想される結果が生成されます。
$ ls
Makefile
$ make ruleB
echo testruleB_Y4Ow
testruleB_Y4Ow
$ ls
Makefile testruleB_Y4Ow