【问题标题】:How do I write a smart makefile?如何编写智能makefile?
【发布时间】:2014-04-24 15:05:01
【问题描述】:

我是 linux 新手,也是 makefile 新手,所以在这一点上我有点难过。我已经盯着制作手册看了一个小时,我想我会问:

我想为一个相对较小的项目创建一个生成文件,其源文件位于proj/src/ 中,并且位于该位置的子目录中。我在proj/makefile 写了一个makefile,想用它来收集所有源文件,找到它们的依赖关系,并将结果编译成proj/build/。这是我写的:

# here are my files and directories (there are also header files that are not
# listed here, but these are referred to from within the .cpp files with
# respect to the proj/src directory)
# proj/makefile
# proj/src/
# proj/src/main.cpp
# proj/src/dir1/
# proj/src/dir1/source1.cpp
# proj/src/dir2/
# proj/src/dir2/source2.cpp
# proj/build/

srcDir = src/
buildDir = build/

# This is a list of all the object files (can I get this programatically?)
objects = main.o source1.o source2.o

all: prog

# Here I want to compile all source (.cpp) files from src/ and all of its subdirectories, and to find the dependencies I want to call g++ -MM to automatically generate the list:
%.o: %.cpp
        $(CXX) $(CXXFLAGS) -MM -I $(srcDir)

clean:
                rm -rf *o $(buildDir)/prog

这远非实用,但我想在问之前先给出它。运行它给出了

make: * 没有规则来制作目标main.o', needed byprog'。停下来。

所以我想自动写入目标文件的尝试失败了。如果有人能给我一些很好的方向,我希望你能在 cmets 和代码之间找出意图。

编辑:我现在尝试了以下方法:

SHELL := /bin/bash                                                              
srcDir = src                                                                    
buildDir = bin                                                                  
sources := $(shell find $(srcDir) -name *.cpp)                                  
objects := $(sources:%.cpp=%.o)                                                 

-include $(sources:%.cpp=%.d)                                                   

# This is a list of all the object files (can I get this programatically?)      
all: prog                                                                       

prog:   $(objects)                                                              
    g++ $(objects) -o $(buildDir)/prog                                          

# Here I want to compile all source (.cpp) files from src/ and all of its subdirectories, and to find the dependencies I want to call g++ -MM to automatically generate the list:
%.o: %.cpp                                                                      
    $(CXX) $(CXXFLAGS) -MMD -MP -c -I $(srcDir)                                    

clean:                                                                          
    rm -rf *o $(buildDir)/hello    

但是当我运行它时,我收到以下错误:

g++  -MMD -MP -I src
g++: fatal error: no input files
compilation terminated.
make: *** [src/core/Cell.o] Error 1

【问题讨论】:

  • 小心rm -rf
  • 查看 github.com/cdesjardins/makefiles 以获得简单的 makefile 框架。
  • main.o 的 .cpp 文件在哪里?如果它的 src/main.cpp 目标必须是 src/main.o ...看看 makefile 函数,如通配符等。
  • %.o: %.cpp 你有所有你想做的对象对应的.cpp吗?

标签: c++ makefile


【解决方案1】:

它想从main.cpp 构建main.o,但是顶层没有main.cpp。如果要与源文件一起构建,您可以指定目标文件的完整路径:

objects = $(srcDir)/main.o $(srcDir)/dir1/source1.o $(srcDir)/dir2/source2.o

我可以通过编程方式获得这个吗?

我使用 gnumake 的 shell 函数来做到这一点:

SHELL := /bin/bash
sources := $(shell find $(srcDir) -name *.cpp)
objects := $(sources:%.cpp=%.o)

找到我要调用g++ -MM自动生成列表的依赖

使用-MMD 生成依赖文件以及编译。在此处指定 -MP 也是一个好主意 - 这可以确保在删除标头时正确更新依赖项。给定上面定义的变量,您可以将依赖文件包含在

-include $(sources:%.cpp=%.d)

【讨论】:

  • 如何生成这些依赖文件?我会为每个文件调用$(CXX) -MMD 吗?这看起来如何?
  • @ArmanSchwarz:只需在您已有的构建规则中将-MM 替换为-MMD -MP。每次构建关联对象时都会重新生成依赖文件。
  • @ArmanSchwarz:另外,添加-c,以便它编译对象但不会尝试自行链接它。
  • 迈克,我尝试实施您的建议,但显然做错了。我已将我的新生成文件附加到 OP;请让我知道我可能做错了什么(我认为我的代码的 recipe 部分没有告诉g++ 要编译什么,但我不知道该怎么做)。
  • @ArmanSchwarz:添加$< 指定规则的第一个先决条件(即源文件)作为输入;和-o $@ 指定规则的目标(即目标文件)作为输出。这些和其他自动变量记录在here
猜你喜欢
  • 2015-07-03
  • 2013-12-22
  • 1970-01-01
  • 2020-06-23
  • 2016-06-09
  • 1970-01-01
  • 2014-08-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多