gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:42:52 26 4
gpt4 key购买 nike

我正在尝试为我的 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com