我有这样一个makefile:
program:
a/a.o
b/b.o
$(CXX) $(CXXFLAGS) -o program
a/a.o
b/b.o
a.o:
a/a.cpp
a/a.h
$(CXX) $(CXXFLAGS) -c a/a.cpp
b.o:
b/b.cpp
b/b.h
$(CXX) $(CXXFLAGS) -c b/b.cpp
在makefile的目录中,我有两个子目录a和b分别包含a.h, a.p p和b.h, b.p p。问题是,如果我修改一个.cpp文件,发出make命令会重新构建目标程序但是如果我修改一个。h文件,make不会重建任何东西,只会说
make: `program' is up to date.
我不明白为什么,因为。h文件在先决条件行与.cpp文件一起。有趣的是,如果我在object文件目标上执行make命令,比如
$ make a.o
,对a/a.h的修改被检测到,目标a/a。O是重建。问题在哪里?
您稍后添加到问题中的子目录确实导致了这个问题。目标program
依赖于a/a.o
和b/b.o
,但是没有明确的规则将它们变成.o
文件——只有目标a.o
和b.o
存在,但它们不在子目录中。
make
将寻找隐式规则来构建a/a.o
和b/b.o
。该规则确实存在,您将在运行make -d
时看到它被找到。这个隐式规则只依赖于a/file_a.cpp
,而不是a/file_a.h
。因此,根据隐式规则,更改a/file_a.cpp
将使a/a.o
过时,而a/file_a.h
不会。
make用户手册中有一节"隐式规则目录"供您参考。这也解释了为什么可以使用参数--no-builtin-rules
来避免这种隐式行为。如果你使用它,你会看到make
找不到任何规则来创建a/a.o
和b/b.o
。
最后,运行make a.o
将运行在makefile中定义的目标a.o
的配方。该目标确实将a/a.h
作为其先决条件,因此对该文件的任何更改都将导致重新编译。但从本质上讲,这与目标program
无关,后者具有不同的先决条件。