为更大的目录结构创建文件

时间:2011-02-20 02:26:18

标签: c assembly makefile

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

结构看起来像这样:

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

我确信有一些简单的方法来创建一个编译所有文件的makefile,而不必指定它应该看的位置(编译一个目录中的所有文件都可以使用通配符,但那么呢?)。

2 个答案:

答案 0 :(得分:5)

Google搜索“递归会被视为有害”。你会发现原始的文章假设递归制作程序是一种糟糕的做生意的方式,你会发现一些链接到其他地方辩论命题的有效性。

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

  1. 递归make:每个目录都包含一个makefile,它构建在子目录中,然后构建在当前目录中。
  2. 非递归make:makefile包含所有依赖的makefile,并为整个项目构建完整的依赖关系结构,并且只构建必需的软件。
  3. 我经常在一个产品上工作,其中主构建序列由混合系统驱动,该系统使用shell脚本和每个目录的一个makefile。产品的一部分由'RMCH'makefile管理;大部分都不是。构建脚本处理构建的各个阶段,并对目录进行排序,并在需要时在每个目录中运行make。 (源代码是20k +文件,分布在众多目录中 - 这是一个很大的项目/产品。)

    我还转换了一个中小项目(大约20个相关目录,大约400个源文件)来处理RMCH(来自脚本+ makefile-per-directory系统)。起初它有点令人兴奋,但现在已经完成了。我是否正确地做了它是开放的辩论;它主要是一个学习练习,虽然我也做了一些工作修改代码,以使用现代curses库而不是作为代码的一部分使用的古老BSD库(古老的,如1982年复古 - 代码是最后在1986年左右开发并且通常升级到现代(标准C)标准。这也是与git合作的机会 - 总而言之,这是一次非常广泛的学习经历。

    如果你可以将你的大脑包裹在RMCH周围,那么这是一个很好的系统。如果正确完成,通过完整和准确的依赖关系跟踪,它会从构建序列中删除猜测,并且运行速度很快。然而,将中等规模的项目迁移到它是相当困难的工作 - 在我工作的主要产品上进行这项工作将是一项艰巨的任务,尽管系统可能会从中受益。

    另一种方法是查看make的其他替代方法,例如cmakerakesconsbrasimake,或ant或其他任何您喜欢的东西。其中大部分都可以通过谷歌搜索轻松发现;困难的是bras,它基于Tcl(如在Tcl / Tk中),但现在可能基本上已经死了。并且imake更完整,而非严肃的建议。你也可以看一下GNU Autotools。那些不放弃make;他们建立在make之上。

答案 1 :(得分:4)

如果您的项目足够小,您可能会使用单个手工制作的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)