我有几个包含c或asm文件的子目录的目录,我希望它们全部编译/汇编然后链接。我不是特别挑剔目标文件的位置(例如特殊的bin文件夹或src文件夹中),只要make clean将它们全部删除。
结构看起来像这样:
/src
/dir1
/dir1_1
+file1_1.s
+file1_2.s
+file1.s
/dir2
+file2.c
我确信有一些简单的方法来创建一个编译所有文件的makefile,而不必指定它应该看的位置(编译一个目录中的所有文件都可以使用通配符,但那么呢?)。
答案 0 :(得分:5)
Google搜索“递归会被视为有害”。你会发现原始的文章假设递归制作程序是一种糟糕的做生意的方式,你会发现一些链接到其他地方辩论命题的有效性。
基本上,有两种方法可以在目录层次结构中进行构建(使用make
)。
我经常在一个产品上工作,其中主构建序列由混合系统驱动,该系统使用shell脚本和每个目录的一个makefile。产品的一部分由'RMCH'makefile管理;大部分都不是。构建脚本处理构建的各个阶段,并对目录进行排序,并在需要时在每个目录中运行make
。 (源代码是20k +文件,分布在众多目录中 - 这是一个很大的项目/产品。)
我还转换了一个中小项目(大约20个相关目录,大约400个源文件)来处理RMCH(来自脚本+ makefile-per-directory系统)。起初它有点令人兴奋,但现在已经完成了。我是否正确地做了它是开放的辩论;它主要是一个学习练习,虽然我也做了一些工作修改代码,以使用现代curses库而不是作为代码的一部分使用的古老BSD库(古老的,如1982年复古 - 代码是最后在1986年左右开发并且通常升级到现代(标准C)标准。这也是与git
合作的机会 - 总而言之,这是一次非常广泛的学习经历。
如果你可以将你的大脑包裹在RMCH周围,那么这是一个很好的系统。如果正确完成,通过完整和准确的依赖关系跟踪,它会从构建序列中删除猜测,并且运行速度很快。然而,将中等规模的项目迁移到它是相当困难的工作 - 在我工作的主要产品上进行这项工作将是一项艰巨的任务,尽管系统可能会从中受益。
另一种方法是查看make
的其他替代方法,例如cmake
,rake
,scons
,bras
,imake
,或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)