0

[name].c という形式のファイルのセットがあり、そのうちのいくつかは関連する [name].h ファイルを #include します。[name].c または [name].h が変更された場合に [name].o を再構築する makefile ターゲットが必要です。私は試した:

$(OBJDIR)/%.o : $(SRCDIR)/%.c $(SRCDIR)/%.h
        #Implementation of target omitted

ただし、関連付けられた .h ファイルを持たない .c ファイルの場合、make は上記のルールに違反します。私は試した:

$(OBJDIR)/%.o : $(SRCDIR)/%.c $(wildcard $(SRCDIR)/%.h)
        #Implementation of target omitted

これはビルドされますが、.h ファイルを変更しても再ビルドはトリガーされません。このように % を使用できない理由はありますか?

注: makedeps.pl または makefile 生成を使用するソリューションを回避しようとしています (実際には .c または .h ファイルを使用していないため)。

4

1 に答える 1

1

%makefile が読み込まれると、ターゲット リストまたは前提条件リストの一部として表示される変数と関数がすぐに展開されるため、この試みはうまくいきません。ターゲットを構築する方法を理解しようとしているため、実際に<srcdir>/%.hはおそらく存在しないリテラル文字列を展開しています。

1 つの答えは、前提条件を別のルールに移動することです。

$(OBJDIR)/foo.o : $(wildcard $(SRCDIR)/foo.h)
$(OBJDIR)/bar.o : $(wildcard $(SRCDIR)/bar.h)
$(OBJDIR)/baz.o : $(wildcard $(SRCDIR)/baz.h)

これを書き出す必要がない場合は、 eval を使用してそれを行うことができます: オブジェクトファイルをリストする変数があるとします:

OBJECTS = foo.o bar.o baz.o

$(foreach O,$(OBJECTS),$(eval $(OBJDIR)/$O : $(wildcard $(SRCDIR)/$(O:.o=.h))))

(それは正確ではないかもしれません)。

または、次のように有効.SECONDEXPANSIONにして書き込むこともできます。

.SECONDEXPANSION:
$(OBJDIR)/%.o : $(SRCDIR)/%.c $$(wildcard $(SRCDIR)/%.h)
        #Implementation of target omitted

$(ワイルドカード機能をエスケープする余分な点に注意してください)。

于 2013-07-10T12:37:49.027 に答える