2

私はこのMakefileを持っています(これは単なる例であり、実際には意味がありません)

all: foobar.intermediate foobar.a

define RECIPE_THROUGH_INTERMEDIATE
    cp $< $@.intermediate
    mv $@.intermediate $@
endef 

define RECIPE_DIRECT
    cp $< $@
endef

%.a: %.c
    $(RECIPE_THROUGH_INTERMEDIATE)

%.a: %.intermediate
    $(RECIPE_DIRECT)

%.intermediate: %.c
    $(RECIPE_DIRECT)

Makeをできるだけ「高速」にして、次のように更新したい:

>make foobar.a

から中間までレシピを実行foobar.cするfoobar.a

しかし

>make

~から直接レシピを実行foobar.cするfoobar.intermediate

~から直接レシピを実行foobar.intermediateするfoobar.a

つまり、これは、foobar.aソース ( ) からターゲット ( ) を作成するfoobar.cために内部で中間を経由する必要がある一般的な状況であり、ソースから中間へ、または中間からターゲットへのいずれかを単独で移動するよりも時間がかかりますが、明示的に(内部的にではなく)中間を通過する場合、これら2つを合わせたよりも時間がかかりません。

もちろん、Make はレシピにかかる時間を知りません。

だから私は、正しいパスを作ることを示唆したい:

  • ターゲットだけが必要な場合は、ソースからターゲットへの直接レシピを取得します
  • ターゲットと中間の両方が必要な場合は、中間を作成し、そこからターゲットを作成します。

私は少なくとも 3.82 の GNU Make を持っていますが、パターン ステムの長さを制御することはできません。

上記の Makefile を変更して目的の動作を実現する方法はありますか?

4

3 に答える 3

0

GNU Make 3.81 を使用して動作を再現できません。

明らかに、それは存在しないコマンドを呼び出すため、実際の Makefile ではfromありません。コマンドを . でコメントアウトして変更しました#。私のディレクトリには、メイクファイルとfoobar.c.

$ make foobar.a
#from .c to .a

$ make foobar.b
#from .c to .b

パターン ルールをコメント アウトした場合にのみ、次の%.a : %.cようになります。

$ make foobar.a
#from .c to .b
#from .b to .a

だから、何か他のことが起こっています。3.82 でのリグレッションかもしれませんし、実際の makefile が何らかのバグを引き起こしているのかもしれませんし、私の場合はフルークによって短いパスが選択されているのかもしれません。

作成を要求foobar.aすると、Make はそのパターン ルールを検索して、foobar.a作成できる前提条件を推測する必要があることは明らかです。これは幅優先の検索である必要が%.a: %.cあります。パターン ルール間で遭遇し、foobar.cファイルがあることを確認する必要があります。行こう! この最初のラウンドが失敗した場合にのみ、グラフ クロージャを拡張して、前提条件を 1 ステップ削除するなどを含める必要があります。それは実際には巧妙な最適化の問題ですらあります。グラフの走査順序の問題です!

于 2013-10-29T05:30:30.690 に答える