在父目录上编写具有前提条件的递归制作配方 [英] writing a recursive make recipe with prerequisite on parent directory
问题描述
我正在尝试编写一个递归的make配方.在此配方中,每个目标都依赖于在父目录上具有相同名称的文件.一个最小的(无效的)示例:
I am trying to write a recursive make recipe. In this recipe, each target is dependent on a file with an equal name on the parent directory. A minimal (non-working) example:
foo/.dirstamp:
mkdir $(dir $@)
touch $@
.SECONDEXPANSION:
%/.dirstamp: $$(dir $$*).dirstamp
mkdir $(dir $@)
touch $@
在此示例中,我希望make foo/bar/qux/lol/.dirstamp
生成整个目录树(如果它不存在),并一路触摸所有.dirstamp
文件.但是,它不起作用:
With this example, I would expect make foo/bar/qux/lol/.dirstamp
to generate the whole directory tree (if it does not exist), touching all .dirstamp
files along the way. However, it does not work:
$ 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
可以正常工作.
It works fine as long as the recursive recipe only needs to be expanded twice, e.g., make foo/bar/.dirstamp
works fine.
如何在任意数量的级别上使用?如何处理目标名称和先决条件名称的递归扩展?
How can this work for an arbitrary number of levels? How can I handle a recursive expansion for the target and prerequisites names?
注意:我的真正问题是我的食谱的先决条件在根中
目录不同于目标目录,因此我使用上面的配方来复制目录树.我知道mkdir -p
在GNU系统中似乎工作正常.我仍然很想知道如何解决任意级别的递归问题.不再起作用,因为团队的一部分正在使用Mac并将该目录安装在smb上.
Note: my real problem is that the prerequisites of my recipes are in a root
directory different from the target so I am using the recipe above to duplicate the directory tree. I know about mkdir -p
which seems to work fine in GNU systems. I am still interested on knowing how I would solve the recursion problem for arbitrary levels. which no longer works because part of the team is using Mac and mounting this directories over smb.
有关实际问题的更多详细信息:先决条件在data/x/y/z
中,而目标进入results/x/y/z
中.但是,results
目录树不存在,需要根据需要创建.为了解决这个问题,我将创建父目录作为仅顺序的先决条件(通过上面的最小示例中的.dirstamp
文件).
More details on the actual problem: prerequisites are in data/x/y/z
while targets go into results/x/y/z
. However, the results
directory tree does not exist and needs to be created as needed. To solve this, I made the creation of parent directories an order-only prerequisite (via the .dirstamp
files on my minimal example above).
- 无法将
data
复制到results
,这是几TB的数据; - 无法在
data
中创建目标,这是只读的; - 不能使用
mkdir -p
,因为results
目录将不是本地目录,而是通过smb挂载,其他目录可能使用非GNU系统;
- can't copy
data
intoresults
, that's several TB of data; - can't have the targets created in
data
, that's read-only; - can't use
mkdir -p
because theresults
directory will not be local, mounted over smb, and others may use non-GNU systems;
推荐答案
@EtanReisner对这个问题的提示后:
After an hint from @EtanReisner on the question:
make不会多次应用规则.这是一个内置的(有意的)限制.如果不通过手动递归或手动构建目标集并使用静态模式规则来解决(我不确定这可能会或可能不会实际工作),那么您将无能为力.
make won't apply a rule more than once. That's a built-in (intentional) limitation. Without working around that with manual recursion or manually building the set of targets and using a static pattern rule (which may or may not actually work I'm not sure) there's not much you can do about this.
我制定了此解决方案:
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 $@
它将复制results
中的data
目录树,因为需要dirstamp文件.通过使它们成为其他配方的先决条件(请注意|
使其成为仅订购的先决条件)来实现它们:
It will duplicate the data
directory tree in results
as the dirstamp files are required. They are required by making them prerequisites of the other recipes (note the |
which makes them order-only prerequisites):
results/%/foo.analysis: data/%/foo.data | results/%/.dirstamp
$(SOME_ANALYSIS_PROGRAM) $^ > $@
这篇关于在父目录上编写具有前提条件的递归制作配方的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!