258

GNUmakefile で、一時ディレクトリを使用するルールを作成したいと考えています。例えば:

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

書かれているように、上記のルールは、ルールが解析されるときに一時ディレクトリを作成します。これは、常に out.tar を作成していなくても、多くの一時ディレクトリが作成されることを意味します。/tmp に未使用の一時ディレクトリが散らばるのを避けたいと思います。

変数が定義されるたびにではなく、ルールが起動されたときにのみ変数が定義されるようにする方法はありますか?

私の主な考えは、mktemp と tar をシェル スクリプトにダンプすることですが、それはやや見苦しく思えます。

4

4 に答える 4

399

あなたの例では、ルールが評価さTMPれるたびに変数が設定されます(および一時ディレクトリが作成されます) 。が実際に起動されたときにのみディレクトリを作成するには、ディレクトリの作成を次の手順に移動する必要があります。out.tarout.tar

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

eval関数は、文字列が makefile に手動で入力されたかのように評価します。この場合、TMP変数をshell関数呼び出しの結果に設定します。

編集(コメントに応じて):

一意の変数を作成するには、次のようにします。

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

これにより、ターゲットの名前 (この場合は out.tar) が変数の先頭に追加され、名前の変数が生成されますout.tar_TMP。うまくいけば、それは衝突を防ぐのに十分です。

于 2009-12-15T18:23:45.540 に答える
91

これを行う比較的簡単な方法は、シーケンス全体をシェル スクリプトとして記述することです。

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

于 2015-03-16T19:53:29.817 に答える
39

もう 1 つの可能性は、ルールの実行時に別の行を使用して Make 変数を設定することです。

たとえば、次の makefile には 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
于 2013-12-21T01:32:21.323 に答える