让 Make 递归所有子目录
最近同事提了一个需求,想方便的调用一个工具校验所有的 xml 文件(包括子目录下的)。我想了一下,最简单的方法是用 Make 来辅助完成这件事情。
问题在于,怎样让 Make 递归的处理所有子目录。因为 GNU Make 默认的 wildcard 只能枚举出当前目录的文件,而不能递归下去。
求助于 Shell 指令当然是一种方法,如果只考虑 unix 环境,我会用 shell 去做。在 Windows 下也有 for 语句可以使用。但我不想处理复杂的平台差异。所以就在 Make 内置的函数里想办法了。
一开始我认为 GNU Make 是个图灵完备的语言,有 call 和 eval 做函数模板和调用。if 函数可以用于递归终止。理论上能写递归就能解决别的语言解决的问题了。
后来试着在 makefile 里写了个简单的递归程序,结果让我很失望。Make (至少是 mingw32 的 make) 被我的小程序整挂了。输出了错误信息:
make: Interrupt/Exception caught (code = 0xc00000fd, addr = 0x7c92e8e7)
迫不得已,我使用了开子进程的方式。(这种方式在 Windows 下效率很低)
下面列出今天写的一段小程序,功能是递归遍历当前目录下的所有子目录。
.PHONY : all all: echo I'm in $(CURRENT_DIR) CURRENT_DIR ?= . FILES = $(wildcard $(CURRENT_DIR)/*) define DIR_temp .PHONY : $(1) all: $(1) $(1) : $$(MAKE) CURRENT_DIR=$$(CURRENT_DIR)/$(strip $(1)) endef $(foreach e, $(FILES), \ $(if $(wildcard $(e)/*), \ $(eval $(call DIR_temp, $(notdir $(e))))))
7 月 8 日补充:
前几天的递归程序是我写错了导致,如果正确的编写是可以成功遍历子目录下的所有文件的。代码如下:
.PHONY : all # arg1 dir define EXPAND_temp FILES := $(wildcard $(1)*) DIRS := $$(foreach e, $$(FILES), $$(if $$(wildcard $$(e)/*), $$(eval DIRS := $$(DIRS) $$(e)))) FILES := $$(filter-out $$(DIRS),$$(FILES)) ALLFILES := $$(ALLFILES) $$(FILES) $$(foreach e,$$(DIRS),$$(eval $$(call EXPAND_temp,$$(e)/))) endef $(eval $(call EXPAND_temp)) all : echo $(ALLFILES)
Comments
Posted by: netawater | (14) April 16, 2013 09:52 PM
Posted by: Scan | (13) December 4, 2011 02:17 AM
Posted by: Scan | (12) December 4, 2011 02:17 AM
Posted by: lj | (11) August 18, 2011 02:08 PM
Posted by: nil | (10) July 8, 2009 12:18 PM
Posted by: Anonymous | (9) June 28, 2009 01:24 PM
Posted by: Anonymous | (8) June 27, 2009 08:25 PM
Posted by: 天下 | (7) June 27, 2009 02:21 PM
Posted by: david | (6) June 27, 2009 12:12 AM
Posted by: cloud | (5) June 26, 2009 07:02 PM
Posted by: arnan | (4) June 26, 2009 06:56 PM
Posted by: 北京兼职网 | (3) June 26, 2009 06:11 PM
Posted by: viho | (2) June 26, 2009 05:47 PM
Posted by: viho | (1) June 26, 2009 05:45 PM