【问题标题】:Can I have one makefile to build a hierarchical project?我可以有一个 makefile 来构建一个分层项目吗?
【发布时间】:2011-01-28 17:06:18
【问题描述】:

我在非平面目录结构中有数百个文件。我的 Makefile 列出了每个源文件,考虑到项目的大小以及项目中有多个开发人员的事实,当我们忘记放入新文件或取出旧文件时,这些文件可能会产生烦恼。我想概括一下我的 Makefile,以便 make 可以简单地构建所有 .cpp 和 .h 文件,而不必指定所有文件名,给定不同类型文件的一些通用规则。

我的问题:鉴于目录中有大量文件,并且有很多子文件夹,我如何告诉 make 构建它们而不必将每个子文件夹都指定为路径的一部分?我如何做到这一点,以便我可以在根目录中只使用一个 Makefile 来做到这一点?

编辑:this 几乎回答了我的问题,但它要求您指定所有文件名:\

【问题讨论】:

  • 您不希望构建过程构建随机文件 - 正在编辑的文件的备份、临时文件等。您想要列出应该存在的文件建成。您可能还没有意识到 - 但您确实想列出要构建的内容。
  • 备份和临时文件不会有 .cpp 或 .h 扩展名,是吗?是否将 .cpp~ 解释为 .cpp?

标签: build makefile build-automation


【解决方案1】:

我确信纯 gmake 解决方案是可能的,但使用外部命令修改 makefile 或生成外部命令(您在 makefile 中的 include)可能要简单得多。

类似的东西:

all: myprog

find_sources:
    zsh -c 'for x in **/*.cpp; echo "myprog: ${x/.cpp/.o}" >> deps.mk'

include deps.mk

然后运行

make find_sources && make

注意:确切的 zsh 行可能需要一些转义才能在 make 文件中工作,例如$$ 而不是 $。也可以用 bash + find 代替。

【讨论】:

  • hm,所以我只需要运行一个小 shell 脚本作为我的目标之一?我正在考虑这样做,但我希望 make 中可能有一些我缺少的东西。
  • 虽然没有我想的那么干净,但这似乎是阻力最小的路径,直到我能找到一个基本上顶级的构建系统。谢谢!
  • 有一种更简洁的方法可以做到这一点。使用“deps.mk”作为目标,而不是“find_sources”。然后你就可以运行“make”了。
【解决方案2】:

一种独立于平台的方式(我的意思是独立于 Windows 或 Linux 中的 shell)是这样的:

DIRS = relative/path1\
       relative/path2

dd = absolute/path/to/subdirectories
all:
@$(foreach dir, $(DIRS), $(MAKE) -C $(dd)$(dir) build -f ../../Makefile ;)
build:
     ... build here

请注意,空格和分号在这里很重要,指定绝对路径也很重要,最后还要指定适当 Makefile 的路径(在这种情况下,我只在祖父文件夹中使用一个 Makefile)

但也有一种更好的方法涉及 PHONY 目标,它可以更好地显示进度和错误,并在一个文件夹出现问题时停止构建,而不是继续到其他目标:

.PHONY: subdirs $(DIRS)

subdirs: $(DIRS)

$(DIRS):
    $(MAKE) -C $@ build -f ../../Makefile
all : prepare subdirs
...
build :
... build here

我在这里只使用了一个应该适用于所有子项目的 Makefile。对于孙文件夹中的每个子项目,目标“构建”是使用根目录中的一个 Makefile 创建的。

【讨论】:

    【解决方案3】:

    我将从使用通配符函数的组合开始: http://www.gnu.org/software/make/manual/make.html#Wildcard-Function

    VPATH/vpath http://www.gnu.org/software/make/manual/make.html#Selective-Search

    和文件功能 http://www.gnu.org/software/make/manual/make.html#File-Name-Functions

    对于排除(即:备份,正如 Jonathan Leffler 提到的),使用不在 vpath 中的单独文件夹进行备份,并使用良好的隐式规则。

    您仍然需要定义要处理的文件夹,但不是其中的每个文件。

    【讨论】:

      【解决方案4】:

      我对此有两种看法。一方面,如果您的 Make 系统编译并链接它找到的所有内容,您会很快发现是否有人在源目录中留下了冲突的垃圾。另一方面,非冲突垃圾会激增,您将无法轻松将其与实时代码区分开来......

      我认为这取决于很多特定于您的商店的事情,例如源代码控制系统以及您是否打算拥有另一个具有重叠代码库的项目。也就是说,如果您真的想要编译给定目录下的每个源文件,然后将它们全部链接,我建议使用简单的递归:创建对象,在此处编译所有源文件,添加结果对象(带有完整路径)到顶部源目录中的列表,递归到这里的所有目录。要链接,请使用列表。

      【讨论】:

        猜你喜欢
        • 2012-07-26
        • 2017-05-30
        • 1970-01-01
        • 1970-01-01
        • 2017-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多