Makefile: 修改模式规则中的源文件名

3

我有一些文件存储在名为datahelpers的目录中,我想使用它们来创建位于result目录中的目标文件。

目录结构如下:

data
 + A
 | + file1
 | + file2
 | + ...
 + B
 | + file1
 ...
helpers
 + file1
 + file2
 ...
< p > 在< code > result < /code >中的目录结构与< code > data < /code >相同。因此,我想写出以下规则:< /p >
result/%: data/% helpers/% script
    script $@ $(word 1,$^) $(word 2,$^)

这个问题在于helpers目录下的file1file2等文件不在子目录中。
现在我有以下几个选项:
  • (不切实际,有20个子目录)为每个子目录编写单独的规则
  • 使用 foreach 包含每个子目录以创建规则(那么我如何访问前提条件列表?)
然而,我更愿意写以下之一:
result/%: data/% helpers/$(basename %) # this doesn't work
result/%: data/% helpers/$(basename $*) # this doesn't work either

有没有办法通过修改规则中匹配的词干来修改规则声明中的模式?
1个回答

3
你想要实现的唯一方法是在你的makefile中启用第二扩展
示例:

Note that the directory prefix (D), as described in Implicit Rule Search Algorithm, is appended (after expansion) to all the patterns in the prerequisites list. As an example:

.SECONDEXPANSION:

/tmp/foo.o:

%.o: $$(addsuffix /%.c,foo bar) foo.h
        @echo $^

The prerequisite list printed, after the secondary expansion and directory prefix reconstruction, will be /tmp/foo/foo.c /tmp/bar/foo.c foo.h. If you are not interested in this reconstruction, you can use $$* instead of % in the prerequisites list.

因此,类似这样的代码应该可以工作(未经测试):

.SECONDEXPANSION:
result/%: data/% helpers/$$(notdir %)

“make”的“basename”与shell的“basename”不同(这经常让我困扰)。
如果要使用$(foreach),则应该使用以下内容(未经测试):
define dirrule
result/$1/%: data/$1/% helpers/%
        @echo cmd 1
        @echo cmd 2
endef

$(foreach dir,subdir1 subdir2 ... subdir20,$(eval $(call dirrule,$(dir))))

我还不确定我是否完全理解了“次级扩展”。为了实现上述示例中我想要做的事情,它们应该是什么样子的呢?对于$(foreach ...),我如何添加实际规则(语法似乎不支持换行符)? - Michael Schubert
编辑,附带两种用法的示例。 - Etan Reisner
是的,这个可以工作。不知道之前我做错了什么。谢谢! - Michael Schubert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接