c++ - make 的自动依赖性生成 .d 文件但不读取它们

标签 c++ makefile

我正在尝试为我的 C++ 程序编写一个生成自动依赖项的 makefile。我评论了this tutorial并且还一直在审查 GNU make 手册。看起来 make 正在生成我的 .d 文件但没有读取它们,或者它读取了它们但由于某种原因不会使用它们。

我的项目由这些目录组成:

  • .cpp 文件的 src
  • 包含 .hpp 文件
  • .d 文件的 makedeps
  • .o 文件对象
  • 最终可执行文件的bin

这是我的生成文件:

BIN=bin
SRC=src
INC=include
DEP=makedeps
OBJ=objects
# sources are like 'src/main.cpp'
sources=$(wildcard $(SRC)/*.cpp)
# objects are like 'objects/main.o'
objects=$(subst $(SRC),$(OBJ),$(sources:.cpp=.o))
# dependencies are like 'makedeps/main.d'
deps=$(subst $(SRC),$(DEP),$(sources:.cpp=.d))
GPP=g++
CPPFLAGS=-std=c++11
LINKARGS=-L/usr/lib/x86_64-linux-gnu

# used by the implicit rules that the dependency files use:
CXX=$(GPP)

$(BIN)/app.exe : $(objects)
    $(GPP) $(CPPFLAGS) $(LINKARGS) $(objects) -lcurl -o $(BIN)/app.exe

# on the first pass this should fail, but it should discover how 
# to build these dependencies and then build them and load them in.
# once they are loaded in, it should know how to build the object files.
-include $(deps)

# this produces the dependency files, the sed command puts directory prefixes
# before the files
$(DEP)/%.d : $(SRC)/%.cpp
    @set -e; rm -f $@; \
    $(GPP) -I$(INC) -MM $(CPPFLAGS) $< > $@.$$$$; \
    sed 's,\($*\)\.o[ :]*,$(OBJ)/\1.o : ,g' < $@.$$$$ > $@; \
    rm -f $@.$$$$

.PHONY:clean
clean:
    rm -f $(OBJ)/*.o
    rm -f $(DEP)/*.d
    rm -f $(BIN)/*

当我运行 make 时,它​​会在“makedeps”目录下生成所有依赖文件,这是它们的串联输出:

objects/DownloadBuffer.o : src/DownloadBuffer.cpp include/DownloadBuffer.hpp
objects/Downloader.o : src/Downloader.cpp include/Downloader.hpp \
 include/DownloadBuffer.hpp
objects/main.o : src/main.cpp include/Downloader.hpp

我在 GNU make 关于隐式规则的手册文档中找到了这个:

Compiling C++ programs: n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form ‘$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c

这就是我在上面设置 CXX=$(GPP) 的原因。

但是,没有生成目标文件。这是 make 的输出:

mike@ubuntu:~/NetBeansProjects/CppApplication_1$ make -f mk.mk clean
rm -f objects/*.o
rm -f makedeps/*.d
rm -f bin/*
mike@ubuntu:~/NetBeansProjects/CppApplication_1$ make -f mk.mk 
g++ -std=c++11 -L/usr/lib/x86_64-linux-gnu objects/DownloadBuffer.o objects/Downloader.o objects/main.o -lcurl -o bin/app.exe
g++: error: objects/DownloadBuffer.o: No such file or directory
g++: error: objects/Downloader.o: No such file or directory
g++: error: objects/main.o: No such file or directory
make: *** [bin/app.exe] Error 1

请注意,首先删除了 .d 文件,并且我确认它们是在 make 运行时创建的。仔细阅读后this section on include directives ,我的印象是 make 应该在创建这些 .d 文件后尝试(再次)包含它们。

谁能解释一下为什么没有生成目标文件?

最佳答案

如果您的目标由于隐式规则查找的工作方式而具有路径分隔符,则您不能依赖隐式规则,解决问题的最直接方法是在 $(BIN)/app. exe

$(objects):
    $(GPP) $(CPPFLAGS) $(CXXFLAGS) -c $^ -o $@

也就是说,GCC 已经有一段时间更好的依赖生成了,但看起来文档还没有跟上。您可以使用 -MMD 生成依赖项作为编译的副作用,这意味着您可以摆脱所有 sed crud(-MP 添加 header 的虚拟目标以避免在删除它们时出现问题)。

你的 Makefile 看起来像这样

BIN := bin
SRC := src
INC := include
OBJ := objects

app     := $(BIN)/app.exe
sources := $(wildcard $(SRC)/*.cpp)
objects := $(subst $(SRC),$(OBJ),$(sources:.cpp=.o))
deps    := $(objects:.o=.d)

CXX      := g++
CPPFLAGS := -I $(INC) -MMD -MP
CXXFLAGS := -std=c++11
LDFLAGS  := -L /usr/lib/x86_64-linux-gnu
LDLIBS   := -lcurl

$(app) : $(objects)
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

$(OBJ)/%.o: $(SRC)/%.cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $^ -o $@

.PHONY: clean
clean: ; $(RM) $(objects) $(deps) $(app)

-include $(deps)

您可以从文件中看到的其他一些注释

  • 使用 := 而不是 = 除非你需要后者
  • 如果您的 header 位于单独的文件夹中,则需要添加路径
  • 使用 GCC 的自动依赖生成器时,在与对象相同的目录中输出依赖会更简单。如有必要,您可以使用 -MF 更改输出文件。
  • 您不需要在链接时提供 CPPFLAGS,它不执行任何预处理。
  • 您可能应该坚持使用默认的链接器配方和变量(以及 CXX)。
  • 尽可能在食谱中使用自动变量($@ 等)。

如果你真的想使用隐式规则,你需要做一些事情,比如从你的目标文件中剥离路径并事先更改到目标目录。

关于c++ - make 的自动依赖性生成 .d 文件但不读取它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25966411/

相关文章:

c++ - int 到字符串的转换

c++ - 预编译头如何减少编译时间

makefile - Make 不喜欢 $(addprefix a,b)

r - 具有多个输入和输出的 Makefile

linux - 为什么 linux 内核的 Makefile 中的变量不起作用?

c++ - 需要有关在 C++ 中有效操作内存的建议吗?

c++ - 使用opencv将视频写入文件时遇到问题

java - 为多个 .java 文件创建 java makefile (ubuntu)

makefile - 使 [1] : *** read jobs pipe: Resource temporarily unavailable. 停止

c++ - HDF5 中的奇怪异常