繁体   English   中英

makefile - 依赖的依赖

[英]makefile - dependency of dependency

根据我在互联网上读到的内容,您可以说: A取决于BB取决于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 所说,即使b.hpp已更改, a.hpp的时间戳也不会更改,因为没有更新a.hpp命令。 Sam Miller 建议了touch命令。 但是由于我使用的是 Windows 并且无法找到一个简单的等效程序,因此我编写了一个名为WinTouch的小程序。 效果很好,谢谢大家。



编辑2
Chnossos 向我展示了在 makefile 方面我有很多东西要学习。 我尝试了他提出的示例 makefile,它工作得很好,似乎它会让我将来的生活更轻松。

如果目标a.hpp依赖于b.hpp ,则需要表明a.hpp已更改:

a.hpp: b.hpp                                                                                                              
    touch $@

这将更新 a.hpp 的时间戳,触发重新构建main.o目标。

我是否完全误解了,它根本不像我描述的那样工作?

你几乎完全明白了,@Sam Miller 的回答解释了你的尝试中遗漏了什么。 你需要告诉 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 -p $@

# 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)

如果你有任何问题。

我是否完全误解了,它根本不像我描述的那样工作?

目标具有依赖性。 当任何依赖文件更改时,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 脚本可以为您生成并保持它们是最新的。

我找到了以下目标并 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 大师,我一直在使用它。 我确实花时间在我希望依赖项和目标文件所在的位置(相对于 src 目录)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM