我正在尝试编写递归制作配方。在此配方中,每个目标都依赖于父目录中具有相同名称的文件。最小(非工作)示例:
foo/.dirstamp:
mkdir $(dir $@)
touch $@
.SECONDEXPANSION:
%/.dirstamp: $$(dir $$*).dirstamp
mkdir $(dir $@)
touch $@
通过这个例子,我希望make foo/bar/qux/lol/.dirstamp
生成整个目录树(如果它不存在),触摸所有.dirstamp
文件。但是,它不起作用:
$ ls # note that there is nothing, make is meant to create the dir tree
Makefile
$ make --debug=v foo/bar/qux/lol/.dirstamp
GNU Make 4.0
[...]
Reading makefiles...
Reading makefile 'Makefile'...
Updating goal targets....
Considering target file 'foo/bar/qux/lol/.dirstamp'.
File 'foo/bar/qux/lol/.dirstamp' does not exist.
Finished prerequisites of target file 'foo/bar/qux/lol/.dirstamp'.
Must remake target 'foo/bar/qux/lol/.dirstamp'.
make: *** No rule to make target 'foo/bar/qux/lol/.dirstamp'. Stop.
只要递归配方只需要扩展两次就可以正常工作,例如,make foo/bar/.dirstamp
工作正常。
这对于任意数量的级别如何工作?如何处理目标和先决条件名称的递归扩展?
注意:我的真正问题是我的食谱的先决条件是在根目录中
目录与目标不同,所以我使用上面的配方来复制目录树。我知道mkdir -p
似乎在GNU系统中运行良好。我仍然有兴趣了解如何解决任意级别的递归问题。不再有效,因为部分团队正在使用Mac并将此目录安装在smb上。
有关实际问题的更多详细信息:先决条件位于data/x/y/z
,目标进入results/x/y/z
。但是,results
目录树不存在,需要根据需要创建。为了解决这个问题,我将父目录的创建设置为仅限订单的先决条件(通过上面最小例子中的.dirstamp
文件)。
data
复制到results
,即数TB的数据; data
中创建只读的目标; mkdir -p
因为results
目录不是本地的,挂载在smb上,而其他目录可能使用非GNU系统; 答案 0 :(得分:2)
在@EtanReisner提出问题后提示:
make不会多次应用规则。这是内置(故意)限制。如果不通过手动递归或手动构建目标集并使用静态模式规则(可能实际可能或可能不实际工作,我不确定),那么您无法做到这一点。
我编写了这个解决方案:
RESULT_DIRS := $(patsubst data/%, results/%, $(shell find data/* -type d -print))
DIRSTAMPS := $(addsuffix /.dirstamp, $(RESULT_DIRS))
results/.dirstamp:
mkdir $(dir $@)
touch $@
.SECONDEXPANSION:
$(DIRSTAMPS): $$(dir $$(patsubst %/.dirstamp, %, $$@)).dirstamp
mkdir $(dir $@)
touch $@
它将复制data
中的results
目录树,因为需要dirstamp文件。通过将它们作为其他配方的先决条件来要求它们(注意|
使它们成为仅限订单的先决条件):
results/%/foo.analysis: data/%/foo.data | results/%/.dirstamp
$(SOME_ANALYSIS_PROGRAM) $^ > $@