【问题标题】:Make file for larger directory structure为更大的目录结构制作文件
【发布时间】:2011-02-20 02:26:18
【问题描述】:

我有几个目录,其子目录包含 c 或 asm 文件,我希望它们全部编译/组装然后链接。我并不特别挑剔目标文件的去向(例如特殊的 bin 文件夹或 src 文件夹中),只要 make clean 将它们全部删除即可。

结构看起来像这样:

/src
    /dir1
        /dir1_1
            +file1_1.s
            +file1_2.s
        +file1.s
    /dir2
        +file2.c

我确信有一些简单的方法可以创建一个编译所有文件的 makefile,而无需我指定它的位置(编译一个目录中的所有文件可以使用通配符,但接下来呢?)。

【问题讨论】:

  • 你的问题有点不清楚。是否要编译/组装/链接/src 下的所有.c.s 文件,而不指定它们的位置?
  • 是的,这就是计划。在不明确指定文件夹结构的情况下编译所有文件。

标签: c assembly makefile


【解决方案1】:

在 Google 上搜索“递归使认为有害”。您会发现原始文章假设递归 make 过程是一种糟糕的做生意方式,并且您会发现一些链接到其他地方的链接,这些地方争论该命题的有效性。

基本上,有两种方法可以在目录层次结构中进行构建(使用make)。

  1. 递归make:每个目录都包含一个makefile,它在子目录中构建,然后在当前目录中构建。
  2. 非递归make:makefile包含所有依赖的makefile,为整个项目构建完整的依赖结构,只构建必要的软件。

我经常在一个产品上工作,其中主要构建序列由一个混合系统驱动,该系统使用一个 shell 脚本加上一个用于每个目录的 makefile。产品的一部分由“RMCH”makefile 管理;大多数不是。构建脚本处理构建的各个阶段,对目录进行排序,并在需要时在每个目录中运行make。 (源代码位于分布在多个目录中的 20k+ 个文件中 - 这是一个大项目/产品。)

我还转换了一个中小型项目(大约 20 个相关目录和大约 400 个源文件)以使用 RMCH(来自脚本 + 每个目录的 makefile 系统)。起初它有点令人兴奋,但现在它已经完成了。我是否做得正确还有待商榷;这主要是一个学习练习,尽管我也做了一些修改代码以使用现代 curses 库而不是用作代码一部分的古老 BSD 库的工作(古老的,如 1982-vintage - 代码是最后一次认真开发是在 1986 年左右)并普遍升级到现代(标准 C)标准。这也是一个与git 合作的机会——总而言之,这是一次非常丰富的学习经历。

如果您可以围绕 RMCH 进行思考,那么它就是一个很好的系统。如果正确完成,并具有完整和准确的依赖关系跟踪,它可以消除构建序列中的猜测工作,并且运行速度很快。然而,即使是一个中等规模的项目迁移到它也是相当艰巨的工作——在我工作的主要产品上进行迁移将是一项艰巨的任务,尽管系统可能会从中受益。

另一种方法是查看make 的其他替代方法,例如cmakerakesconsbrasimakeant 或其他任何你喜欢的东西。其中大部分都可以通过 Google 搜索轻松找到;最难的是bras,它基于Tcl(如在Tcl/Tk 中),但现在可能基本上已经死了。并且imake 被提及更多是为了完整性,而不是作为一个严肃的建议。您还可以查看 GNU Autotools。那些不放弃make;他们建立在make之上。

【讨论】:

  • “递归使被认为有害”文章有一些有趣的见解,我还将研究一些替代方案。谢谢。
【解决方案2】:

如果您的项目足够小,您可能会使用单个手工制作的 makefile 而不是更复杂的构建系统:查看manual page on transformation functions 看看有什么可能。

您的示例项目可以使用以下非递归 makefile 进行编译:

targets = $(patsubst %$(1),%$(2),$(foreach dir,$(3),$(wildcard $(dir)/*$(1))))

asmdirs := src/dir1 src/dir1/dir1_1
cdirs := src/dir2

asmobjects := $(call targets,.s,.o,$(asmdirs))
cobjects := $(call targets,.c,.o,$(cdirs))

.PHONY : all clean

all : $(asmobjects) $(cobjects)

clean :
    rm -f $(asmobjects) $(cobjects)

$(cobjects) : %.o : %.c
    gcc -o $@ -c $<

$(asmobjects) : %.o : %.s
    gcc -o $@ -c $<

但是,因为make 可以访问shell,您也可以使用标准的unix 工具,例如find,而不是一些有限的内置函数,例如

asmsources := $(shell find src -name '*.s')
csources := $(shell find src -name '*.c')

asmobjects := $(asmsources:.s=.o)
cobjects := $(csources:.c=.o)

【讨论】:

  • 对于我相对较小的项目(大约 200 个 src 文件),这似乎是最简单的解决方案,所以现在这应该足够好,这样我就可以更多地担心代码了。如果它变得更复杂,我仍然可以研究更复杂的解决方案。
  • 您忘记将$CFLAGS 传递给 gcc。 Make 已经有从.c.s 构建.o 的隐式规则,你确定你还需要这些模式规则吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
  • 2010-10-11
  • 2013-09-04
相关资源
最近更新 更多