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

时间:2014-09-22 03:44:15

标签: c++ makefile

我正在尝试为我的C ++程序编写一个生成自动执行的makefile。我回顾了this tutorial,并一直在审查GNU制作手册。似乎make正在生成我的.d文件,但没有读取它们,或者它读取它们但由于某种原因不能使用它们。

我的项目包含以下目录:

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

这是我的makefile:

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时,它会生成&#39; makedeps&#39;下的所有依赖项文件。目录,这是它们的连接输出:

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 manual文档中找到了这个:

  

编译C ++程序:n.o是从n.ccn.cppn.C自动生成的,其形式为“$(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文件后加入这些文件。

有人请解释为什么没有生成目标文件吗?

1 个答案:

答案 0 :(得分:2)

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

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

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

你的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)

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

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

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