make的自动依赖项生成.d文件,但不读取它们 我试图为我的C++程序编写一个生成文件,它将生成自动依赖性。我审查了GNU make手册,并且一直在审查该手册。make似乎正在生成my.d文件,但没有读取它们,或者它读取了它们,但出于某种原因不会使用它们

make的自动依赖项生成.d文件,但不读取它们 我试图为我的C++程序编写一个生成文件,它将生成自动依赖性。我审查了GNU make手册,并且一直在审查该手册。make似乎正在生成my.d文件,但没有读取它们,或者它读取了它们,但出于某种原因不会使用它们,c++,makefile,C++,Makefile,我的项目包含以下目录: .cpp文件的src 包括.hpp文件的 为.d文件生成deps .o文件的对象 用于最终可执行文件的bin 这是我的makefile: BIN=BIN SRC=SRC INC=包括 DEP=makedeps OBJ=对象 #源代码类似于'src/main.cpp' sources=$(通配符$(SRC)/*.cpp) #对象类似于“objects/main.o” objects=$(subst$(SRC),$(OBJ),$(sources:.cpp=.o)) #依赖

我的项目包含以下目录:

  • .cpp文件的src
  • 包括.hpp文件的
  • 为.d文件生成deps
  • .o文件的对象
  • 用于最终可执行文件的bin
这是我的makefile:

BIN=BIN
SRC=SRC
INC=包括
DEP=makedeps
OBJ=对象
#源代码类似于'src/main.cpp'
sources=$(通配符$(SRC)/*.cpp)
#对象类似于“objects/main.o”
objects=$(subst$(SRC),$(OBJ),$(sources:.cpp=.o))
#依赖项类似于“makedeps/main.d”
deps=$(subst$(SRC),$(DEP),$(来源:.cpp=.d))
GPP=g++
CPPFLAGS=-std=c++11
LINKARGS=-L/usr/lib/x86_64-linux-gnu
#由依赖项文件使用的隐式规则使用:
CXX=$(GPP)
$(BIN)/app.exe:$(对象)
$(GPP)$(CPPFLAGS)$(LINKARGS)$(对象)-lcurl-o$(BIN)/app.exe
#在第一次通过时,这应该失败,但它应该发现如何失败
#来构建这些依赖项,然后构建并加载它们。
#加载后,它应该知道如何构建对象文件。
-包括美元(deps)
#这将生成依赖项文件,sed命令将放置目录前缀
#在文件之前
$(DEP)/%.d:$(SRC)/%.cpp
@set-e;rm-f$@\
$(GPP)-I$(INC)-MM$(CPPFLAGS)$<>$@.$$$\
sed's,\($*\)\.o[:]*,$(OBJ)/\1.o:,g'<$@.$$>$@\
rm-f$@$$$$
.假冒:干净
清洁:
rm-f$(OBJ)/*.o
rm-f$(DEP)/*.d
rm-f$(银行标识代码)/*
当我运行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手册的隐式规则文档中发现了这一点:

<编译> C++程序:<代码> N.O.<代码>是自动从<代码> N.cc,<代码> N.CPP < /代码>,或<代码> N.C.<代码>,以表格“代码> $(CXX)$(CPPFLAGS)$(CXXFLAGS)-C < /C> > /P> 这就是我在上面设置CXX=$(GPP)的原因

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

mike@ubuntu:~/NetBeansProjects/cppu应用程序\u 1$make-f mk.mk clean
rm-f objects/*.o
rm-f makedeps/*.d
rm-f垃圾箱/*
mike@ubuntu:~/NetBeansProjects/cppu应用程序\u 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++:错误:objects/DownloadBuffer.o:没有这样的文件或目录
g++:错误:objects/Downloader.o:没有这样的文件或目录
g++:错误:objects/main.o:没有这样的文件或目录
生成:**[bin/app.exe]错误1
请注意,先删除了.d文件,我确认它们是在运行make时创建的。仔细阅读后,我的印象是make应该在创建这些.d文件之后(再次)尝试将其包括在内


有人能解释一下为什么没有生成对象文件吗?

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

$(objects):
    $(GPP) $(CPPFLAGS) $(CXXFLAGS) -c $^ -o $@
这就是说,GCC已经有了更好的依赖项生成,但看起来文档还没有跟上。您可以使用
-MMD
生成依赖项作为编译的副作用,这意味着您可以删除所有
sed
crud(
-MP
为头添加虚拟目标,以避免删除时出现问题)

您的Makefile看起来像这样

BIN:=BIN
SRC:=SRC
INC:=包括
对象:=对象
app:=$(BIN)/app.exe
来源:=$(通配符$(SRC)/*.cpp)
对象:=$(subst$(SRC),$(OBJ),$(源:.cpp=.o))
deps:=$(对象:.o=.d)
CXX:=g++
CPPFLAGS:=-I$(INC)-MMD-MP
CXXFLAGS:=-std=c++11
LDFLAGS:=-L/usr/lib/x86_64-linux-gnu
LDLIBS:=-lcurl
$(应用程序):$(对象)
$(CXX)$(LDFLAGS)$^$(LDLIBS)-o$@
$(OBJ)/%.o:$(SRC)/%.cpp
$(CXX)$(CPPFLAGS)$(CXXFLAGS)-c$^-o$@
.假冒:干净
清洁:$(RM)$(对象)$(deps)$(应用程序)
-包括美元(deps)
您可以从文件中看到其他一些注释

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

如果你真的想使用隐式规则,你需要做一些事情,比如从你的对象文件中删除路径并事先更改为对象目录。

我很困惑,你说我应该有一个创建我的对象文件的明确方法,但是.d文件应该创建这个方法,多余的规则不会相互冲突吗?我也不知道CPPFLAGS只用于预处理(我想你的意思是编译,对吧?)。我用它来保存-std=c++11,从你的解决方案来看,我想链接器不需要知道标准。所以我认为make会为同一个目标合并不同的规则,我是在解释这个r吗