【问题标题】:How to have a generic make file with subfolders?如何拥有带有子文件夹的通用 make 文件?
【发布时间】:2016-01-26 14:25:48
【问题描述】:

这个问题肯定已经被问过很多次了,但我找不到正确的答案,所以我问。

我的项目结构如下:

/root
 | obj
 | Makefile
 | src/
 | | dir1/
 | |  | 1.cpp
 | | dir2/
 | |  | 2.cpp
 | |  | dir3/
 | |  |  | 3.cpp
 | |  |  | 4.cpp
 | | main.cpp

我可以有一个通用的 makefile 来编译任何子文件夹中的所有 cpp 文件,并具有任何深度的 src 文件夹,它将生成目标文件到 obj 目录中?

注意此项目正在使用 Eclipse CDT 开发,我希望现在能够提供源代码,而无需用户安装 Eclipse 来构建它

【问题讨论】:

  • 哇,make 2016 年用上了! :-)
  • @AmiTavory 我只是在寻找解决这个问题的最简单方法
  • make 并不是为此而设计的。您可能需要编写脚本来动态构建 Makefile。或者切换到另一个构建系统,例如 scons。
  • @AmiTavory,嗯?制作有什么问题? CMake 只不过是一个 make 文件生成器,所以它仍然使用 make。我个人在 configure + make 方面的经验要好得多,而不是 cmake。
  • @SergeyA 我真的没有和你争论。我想这与我们必须做的特定类型的构建的特性有关。我的猜测是,就像市面上任何大量使用的工具一样,一个对某些人来说更适合某些任务,而另一些对某些人来说更适合其他任务。 :-)

标签: c++ makefile


【解决方案1】:

要实现“无限”递归,您可以使用带有扩展模式的通配符:

CPPFILES := $(wildcard src/**/*.cpp)

然后您可以将它们转换为.o 文件的列表:

OBJFILES := $(patsubst src/%.cpp,obj/%.o,$(CPPFILES))

现在我们有了构建目标:

.PHONY: all
all: $(OBJFILES)

编译规则:

obj/%.o: src/%.cpp
    mkdir -p "$(@D)"
    $(CC) -c $< -o $@

如果带有扩展模式的通配符不起作用,那么您可以使用:

CPPFILES := $(shell find src -name '*.cpp')

【讨论】:

  • OP 不清楚他们是否想要 obj 中的镜像目录或只是一个 obj 目录,所以这可能不是所要求的,但做得很好(并且很容易修复单个obj 目录)。
  • 如果你碰巧有两个同名的文件,只是在不同的目录中,那么在这种情况下单个 obj 目录就会中断。
  • 另请参阅我的答案 here 以获得内部递归通配符函数(以及我找到它的源链接)。
  • 我完全同意,但人们似乎经常要求它。
  • 除了mkdir -p被执行了很多次之外,它工作得很好。有没有可能避免这种情况?
【解决方案2】:

好吧,我不打算回答这个问题(这个答案与make 本身无关),但是:

  1. OP 表示他没有专门针对make,只是最简单的解决方案。

  2. 目前还没有make 特定的答案。

所以,下面是cmakeSCons 中的操作方法。 请注意我的目的不是贬低make,而是提倡以下两种中的任何一种(不过,我必须说 - 我的印象是当今的两种主流 C++ 构建系统) 等。

CMake

在 CMake basic tutorial 中,您将使用如下内容:

file(GLOB_RECURSE variable [RELATIVE path] 
[FOLLOW_SYMLINKS] [globbing expressions]...)

(有关详细信息,请参阅this question。)

Scons

在 Scons basic tutorial 中,你会使用这样的东西:

def getSubdirs(abs_path_dir):  
    lst = [ name for name in os.listdir(abs_path_dir) if os.path.isdir(os.path.join(abs_path_dir, name)) and name[0] != '.' ]    
    lst.sort()
    return lst

(请参阅this question 了解更多信息。)

【讨论】:

  • 可能值得一提,正如链接的 SO 问题中提到的,CMake 缓存找到的文件,因此如果您添加、删除或重命名文件,则需要删除并重新生成 cmake 文件.我没有用过 Scons,所以我不知道它是否有相同的行为。
猜你喜欢
  • 1970-01-01
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多