web-dev-qa-db-ja.com

GNU make:1つのルール内の複数のターゲット

可能性のある複製:
単一のソースファイルからいくつかのターゲットを生成するGNU Makefileルール

このようなMakefileルールがある場合:

a b c:
    echo "Creating a b c"
    touch a b c

output: a b c
    cat a b c > output

そして私はmake -j9 outputを実行します

makeは3つの依存関係(a、b、c)を確認し、それらを生成する方法を探します(上記の「a b c」ルール)。しかし、次に何が起こりますか? 「a b c」ルールは、3つのターゲットすべてを作成するために1回実行するだけでよいことを理解していないのですか?

これがmakeが実際に行うことです。

[pavel@orianna test]$ make -j9 output -n
echo "Creating a b c"
touch a b c
echo "Creating a b c"
touch a b c
echo "Creating a b c"
touch a b c                                                                                                                                                                                                                                                                    
cat a b c > output                                                                                                                                                                                                                                                             
[pavel@orianna test]$

同じ出力が3回実行され、依存関係ごとに1回、ルール「出力」が実行されます。

なぜそれがこのように振る舞うのか誰か知っていますか?

28
Pavel

君の a b c:ルールは、これがビルド方法であることをMakeに伝えます どれか 構築方法ではなく、これらのターゲットの すべて そのうちの。 Makeは、コマンドを分析し、一度ルールを実行すると3つすべてがビルドされると推測するほど賢くありません。 outputa、およびbを再構築する必要があることを(cルールから)知っておくと、そのようになります。最初のルールは、aに対して1回、bに対して1回、cに対して1回実行されます。

それらを個別に再構築する場合は、次のようにします。

a b c:
    echo "Creating $@"
    touch $@

それらを一度にすべて再構築したい場合は、次のようにします。

.PHONY: things
things:
    echo "Creating a b c"
    touch a b c

output: things
    cat a b c > output

またはより良い:

THINGS = a b c
.PHONY: things
things:
    echo "Creating $(THINGS)"
    touch $(THINGS)

output: things
    cat $(THINGS) > output
30
Beta

a b cは3つの異なる目標/ターゲットであり、前提条件はありません。つまり、要求されたときにターゲットを構築するということです。

a b c:
    echo "Creating a b c"
    touch a b c

前提条件としてb cを持つターゲットの名前付き出力をビルドするようにmakeに要求しています。したがって、ターゲットa b cが順次ビルドされ、最終的に出力がビルドされます。

さて、あなたのケースでは、いずれかが呼び出されたときにすべてのターゲットが常にビルドされます。したがって、冗長なビルドを回避するには、ターゲットa、b、cに前提条件を追加する必要があります。 「a」が存在しない場合にのみ、ターゲット「a」をビルドします。同様に「b」と「c」

a b c: $@
    echo "Creating a b c"
    touch a b c

ただし、これはお勧めできません。理想的には、Makefileターゲットは非常に具体的である必要があります。

9
Kamath