这两个目标之间有什么区别:
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $@
和
$(OBJ) : $(SRC)
$(CXX) -c $(CXXFLAGS) $< -o $@
如果我们假设SRC
包含目录中存在的所有.cpp文件并且OBJ = $(SRC:.cpp=.o)
答案 0 :(得分:1)
第一个指定每个目标文件依赖于其对应的源文件,并定义一个合理合理的规则来从源文件($@
创建目标文件($^
,第一个目标),所有依赖项)。它应该使用$<
,只是第一个依赖项,因为通常会有其他依赖项 - 源文件包含的标头。你通常可以完全放弃这条规则;有一个implicit rule用于编译单个C ++文件。
第二个指定所有目标文件都依赖于所有源文件,并定义了一个不能编译任何东西的功能失调的规则。例如,定义SRC = a.cpp b.cpp
,这会扩展为
g++ -c a.cpp b.cpp -o a.o
失败,因为-c
仅编译单个源文件:
g++: fatal error: cannot specify -o with -c, -S or -E with multiple files
答案 1 :(得分:0)
$(SRC)
未包含所有源文件!它包含一个规则,如何从目标文件名构建源文件名。
如果$(SRC)
包含所有源文件,如a.c和b.c,而$(OBJ)包含a.o和b.o,则规则扩展为:
a.o b.o: a.c b.c
无效!
区别:
$(OBJ)
通常包含所需对象的列表。因此规则知道必须构建哪些对象。 Make将为所有源文件调用编译器并构建对象。
第一条规则只是一条规则,在没有任何其他trigger
的情况下实际上什么都不做。
如果您完成示例:
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $^ -o $@
do: x.o y.o
$(CXX) -o do x.o y.o
make知道do
需要x.o和y.o.所以他寻找一条规则来建立它们并抓住你的第一条规则。
但是你的第一条规则不能手动定义,它通常已经存在。对于所有隐式规则,请查看: https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html