makefile - 依赖的依赖

时间:2014-08-02 18:57:21

标签: c++ makefile

从我在互联网上阅读的内容中你可以说: 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,它运行得非常好,看起来它将来会让我的生活变得更轻松。

3 个答案:

答案 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)

如果您有任何疑问。