通过两步依赖关系计算了解Makefile 我想建立一些C++代码。我已经有了一个可以自动计算依赖项的Makefile,但是我想把对象文件保存在单独的目录中。所以结构看起来像: 生成文件 来源/a/ 来源/b/ 资料来源/c/ obj/
我能够运行Makefile,使用obj/prefix将源代码转换为对象,但当我想将依赖项计算后传时,事情变得一团糟 问题在于,几乎所有Makefile示例都是一步完成的,即从.cpp(通过两步依赖关系计算了解Makefile 我想建立一些C++代码。我已经有了一个可以自动计算依赖项的Makefile,但是我想把对象文件保存在单独的目录中。所以结构看起来像: 生成文件 来源/a/ 来源/b/ 资料来源/c/ obj/,makefile,build-automation,gnu,gnu-make,building,Makefile,Build Automation,Gnu,Gnu Make,Building,我能够运行Makefile,使用obj/prefix将源代码转换为对象,但当我想将依赖项计算后传时,事情变得一团糟 问题在于,几乎所有Makefile示例都是一步完成的,即从.cpp(%.d:%.cpp)创建.d。我花了一些时间试图理解Makefile,并通过尝试和错误修复它。最后,我有了一个工作脚本: DIRS := a b c SOURCES := $(foreach dir,$(DIRS),$(wildcard source/$(dir)/*.cpp)) OBJECTS := $(pats
%.d:%.cpp
)创建.d。我花了一些时间试图理解Makefile,并通过尝试和错误修复它。最后,我有了一个工作脚本:
DIRS := a b c
SOURCES := $(foreach dir,$(DIRS),$(wildcard source/$(dir)/*.cpp))
OBJECTS := $(patsubst %.cpp,obj/%.o,$(SOURCES))
obj/%.d: %.cpp
@mkdir -p $(@D)
@$(CXX) -E $(CXXFLAGS) -MM -MP -MF $@ -MQ $(@:.d=.o) -MQ $@ $<
obj/%.o: %.cpp obj/%.d
@$(CXX) $(CXXFLAGS) -o $@ -c $<
project: $(OBJECTS)
...
-include $(OBJECTS:.o=.d)
DIRS:=a b c
源代码:=$(foreach dir,$(DIRS),$(通配符源代码/$(dir)/*.cpp))
对象:=$(patsubst%.cpp,obj/%.o,$(源))
obj/%.d:%.cpp
@mkdir-p$(@D)
@$(CXX)-E$(CXXFLAGS)-MM-MP-MF$@-MQ$(@:.d=.o)-MQ$@$<
obj/%.o:%.cpp obj/%.d
@$(CXX)$(CXXFLAGS)-o$@-c$<
项目:$(对象)
...
-包括$(对象:.o=.d)
但是我仍然不知道为什么我需要为cpp->d和cpp&d->o分别设置步骤(或者我理解-但是我不知道为什么大多数示例不需要这些步骤)。假设源文件是
foo.cpp
和bar.cpp
,标题是foo.h
和bar.h
,使foo.cpp
包括foo.h
和bar.h
,bar.cpp
包括bar.h
您可以有一个完全不涉及依赖项文件的简单makefile:
project: $(OBJECTS)
...
%.o: %.cpp
...
现在,如果修改foo.cpp
,Make将重建foo.o
(和project
)。如果修改bar.cpp
,Make将重建bar.o
(和项目
)。如果修改标题,Make将什么也不做,因为Make不知道对象以任何方式依赖于标题
您可以为依赖项文件设置规则:
project: $(OBJECTS)
...
%.o: %.cpp
...
%.d:
...
-include *.d
现在Make将构建并使用依赖项文件——如果您记得告诉它的话。如果您这样做,Make将知道,当您修改foo.h
时,它必须重建foo.o
,当您修改bar.h
时,它必须重建foo.o
和bar.o
记住重建依赖文件是一件痛苦的事情。最好让Make来做。什么时候必须重建foo.d
?那么,当foo.cpp
被修改时,当然:
project: $(OBJECTS)
...
%.o: %.cpp
...
%.d: %.cpp
...
-include *.d
但是当foo.o
的任何其他先决条件(即foo.h
或bar.h
)被修改时,也必须重新生成foo.d
。我还没有详细说明规则中的命令(我对%.d
规则中的命令也不太理解),但是一个简单的规则将构建一个foo.d
如下所示:
foo.o: foo.cpp foo.h bar.h
foo.o: foo.cpp foo.h bar.h
foo.d: foo.cpp foo.h bar.h
可以编写一个命令,生成如下所示的foo.d
:
foo.o: foo.cpp foo.h bar.h
foo.o: foo.cpp foo.h bar.h
foo.d: foo.cpp foo.h bar.h
有更复杂的方法,但这对于今天来说已经足够了
至于为什么许多示例makefiles共享某个次优特性,这是因为人们在不严格检查或理解每个特性的情况下复制彼此的makefiles。不需要单独的步骤。你可以把它们结合起来。这回答了你的问题吗?@Beta:我不明白为什么所有示例都显示转换
%.d:%.cpp
。目标二进制文件依赖于对象文件(.o),而不是依赖文件,但在Makefile中,除非存在某些依赖文件,否则没有对象文件的规则。