从我在互联网上阅读的内容中你可以说: A 取决于 B 而 B 取决于 C - > A 取决于 C
所以如果我们有一个看起来像这样的makefile:
CC=g++
OUTPUT=app.exe
SOURCES=$(wildcard *.cpp)
OBJECTS=$(patsubst %.cpp, %.o, $(SOURCES))
$(OUTPUT): $(OBJECTS)
$(CC) -o $(OUTPUT) $(OBJECTS)
main.o: main.cpp a.hpp
$(CC) -c main.cpp
a.hpp: b.hpp
我希望main.o
依赖于b.hpp
,因此如果在b.hpp
上次编译后main.o
被更改,则应编译。但这不会发生。
我是否完全被误解了,它根本不是我所描述的方式?如果是这样,main.o的目标应该是什么样的?我是否必须浏览文件包含的所有标题,并使其依赖所有标题?
编辑:
正如Sam Miller所说,即使a.hpp
已被更改,b.hpp
的时间戳也不会改变,因为没有更新a.hpp
的命令。
Sam Miller提出了touch
命令。但由于我在Windows上并且无法找到一个简单的等价物,我写了一个名为WinTouch
的小程序。它非常好用,谢谢大家。
EDIT2
Chnossos向我展示了我在制作文件时需要学习的东西。我尝试了他提出的示例makefile,它运行得非常好,看起来它将来会让我的生活变得更轻松。
答案 0 :(得分:2)
如果目标a.hpp
取决于b.hpp
,则需要指明a.hpp
已更改:
a.hpp: b.hpp
touch $@
这将更新a.hpp的时间戳,触发要重建的main.o
目标。
答案 1 :(得分:1)
我是否完全被误解了,而且我的工作方式并不像我一样 完全描述了吗?
目标有依赖关系。当任何依赖项文件更改时,make将触发make文件中标识的操作。
在您的文件中,目标main不依赖于b.hpp,因此当b.hpp更改时不会发生任何操作。
在你的文件中,目标a.hpp确实依赖于b.hpp,你所拥有的是允许的,但你没有提供任何动作来导致a.hpp或main.cpp都不会被更新。
你有没有理由不使用?
main.o: main.cpp a.hpp b.hpp
$(CC) -c main.cpp
我是否必须浏览文件包含的所有标题并进行编辑 依赖于所有这些?
您似乎缺少的是依赖项文件。
g ++编译器和sed脚本可以为您生成并保持最新版本。
我找到了以下目标并且发现了许多地方,但是根据自己的喜好安排文件和目录需要花费一些精力。 (例如,我不喜欢用.o或.d文件混淆我的src目录,因此DEPPATH)
$(DEPPATH)/%.d : %.cpp
@echo
@echo R22 : $<
rm -f $(addprefix ../i686o/, $(addsuffix .o, $(basename $(@F))))
g++ -M $(CC_FLAGS) $< > $@.$$$$; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm $@.$$$$
了解这个sed脚本和g ++的-M选项应该可以帮到你。
嗯,也许就是按原样使用sed就足够了。我承认我不是一个sed guru,我总是在我发现它时使用它。我确实花了时间在我希望依赖项和目标文件驻留的位置(相对于src目录)。
答案 2 :(得分:1)
我是否完全被误解了,而且根本没有按照我描述的方式工作?
你几乎完全得到了它,@ Sam Miller的answer解释了你的尝试中遗漏了什么。您需要告诉make a.hpp
也已更改。
我想解决这个问题:
我是否必须浏览文件包含的所有标题,并使其依赖所有标题?
GCC或clang现在可以自动为您处理:
让我们构建一个简单的工作示例
EXE := app.exe
SRC := $(wildcard *.cpp)
OBJ := $(SRC:.cpp=.o)
DEP := $(OBJ:.o=.d)
CPPFLAGS += -MMD -MP # built-in variable meant for preprocessor flags, like -I
$(EXE): $(OBJ)
# Linker phase
# LDFLAGS is a built-in variable meant for linker flags such as -L
# LDLIBS is a built-in variable meant for linker flags such as -l
# Their order in the next line IS IMPORTANT to avoid undefined references
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@
# Makefile include command, litteraly copy and paste its arguments' content into
# the makefile. The dash in the beginning prevent outputting an error if a file
# cannot be found.
-include $(DEP)
这就是你所需要的。现在,对于文件夹中的给定.cpp
文件,您将拥有相应的.o
文件和.d
文件,以便跟踪您的标头依赖关系。
如果要将这些额外文件隐藏在文件夹中,请按以下步骤操作:
EXE := app.exe
SRC := $(wildcard *.cpp)
DIR := build
OBJ := $(SRC:%.cpp=$(DIR)/%.o) # toto.cpp => build/toto.o
DEP := $(OBJ:.o=.d) # build/toto.o => build/toto.d
CPPFLAGS += -MMD -MP # built-in variable meant for preprocessor flags, like -I
$(EXE): $(OBJ)
# Linker phase
# LDFLAGS is a built-in variable meant for linker flags such as -L
# LDLIBS is a built-in variable meant for linker flags such as -l
# Their order in the next line IS IMPORTANT to avoid undefined references
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@
# We need to override the implicit rule for .o files since we want a special
# destination. The right side of the pipe will only be evaluated once, it is
# called "order-only prerequisite".
$(DIR)/%.o: %.cpp | $(DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<
$(DIR):
@mkdir $@
# Makefile include command, litteraly copy and paste its arguments' content into
# the makefile. The dash in the beginning prevent outputting an error if a file
# cannot be found.
-include $(DEP)
如果您有任何疑问。