依赖的依赖
dependency of dependency
从我在网上看到的你可以说: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
最后一次编译后被更改,则应该编译。但这并没有发生。
我是否完全误解了,它完全不像我描述的那样工作?如果有,目标应该是什么?看起来像?我是否需要遍历文件包含的所有头文件并使其依赖于所有这些?
编辑:
正如Sam Miller所说,即使b.hpp
被更改,a.hpp
的时间戳也不会更改,因为没有更新a.hpp
的命令。山姆·米勒建议使用touch
命令。但是由于我使用的是windows,无法找到一个简单的等效程序,所以我编写了一个名为WinTouch
的小程序。它工作得很好,谢谢大家。
EDIT2
Chnossos告诉我,在制作文件时,我还有很多东西要学。我尝试了他提出的makefile示例,它工作得很好,似乎它将使我将来的生活更轻松。
我是否完全误解了,它完全不像我描述的那样工作?
你几乎完全得到了,@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)
如果您有任何问题。
如果目标a.hpp
依赖于b.hpp
,则需要指示a.hpp
已更改:
a.hpp: b.hpp
touch $@
这将更新a.hpp的时间戳,触发main.o
目标被重建。
是不是我完全误解了,事情并不是我想的那样描述过吗?
目标有依赖关系。当任何依赖文件更改时,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大师,我总是使用它,因为我发现它。我确实花了一些时间在我希望依赖和目标文件驻留的地方(相对于src目录)。
- 如何从C++中的依赖类型中获得它所依赖的类型
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 将依赖名称显式标记为类型名和模板的奇怪之处
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- C++GTKMM gui循环依赖关系
- 通过ccmake在cmake中缓存依赖选项
- 当基类是依赖类型时,这是一个缺陷吗
- 从不同的附加依赖项中识别等同命名的函数
- 如何在 CMake 中对目标依赖项进行分组?
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 为什么构建目录中新构建的共享库与安装目录中的副本具有不同的依赖项集?
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 通过依赖类型使用非类型模板参数的单类型模板参数类模板的部分专用化
- 为什么内存屏障依赖于变量?
- node-gyp 的先有鸡还是先有蛋的问题:指向依赖项中的头文件
- 反转依赖于 end() 的迭代器
- GCC,CMake,预编译标头和维护依赖项
- 使用 'typename' 关键字将非类型视为依赖上下文中的类型
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 为什么依赖模板类型在部分专用化中不可推导?