Makefile:由字符串模式区分的多个目录和文件的规则
Makefile: Rules for multiple directories and files differentiated by a string pattern
我在构建各种中间和输出数据文件的 RStudio 项目中有一个 Makefile 规则。一些关键规则如下所示:
outdir/<location>/outdata_<location>.file: script.R datadir/<location>/indata_<location>.file
$(EXEC) $< <location>
其中 location
区分目录以及目标和先决条件的文件名,并且 同时作为参数传递 到 script.R
.
例如,先决条件目录的结构如图所示:
datadir
|- location1
| |- indata_location1.file
| |- ...
|
|- location2
| |- indata_location2.file
| |- ...
|
|- location3
这些目录中的每一个都有不同级别的数据文件,因此决定按位置组织它们。此外,随着时间的推移会添加更多的项目位置,因此需要隐式规则来最大限度地减少不断修改 Makefile 的需要。
我已经尝试使用 GNU Make 文档中描述的模式规则,但它说模式占位符只能在目标或先决条件中出现一次。我尝试使用字符串操作和 foreach
函数,但未能解决它,因为我对 GNU Make 的经验有限。
我在多个目录上看到过类似的 SO 问题,但 none 提到使用区分字符串作为配方中的参数。
如有任何帮助,我们将不胜感激。
您想使用几个非常相似的规则,而方差对于一个模式规则来说太复杂了。这看起来像是 a "canned recipe".
的工作
我们写一个模板:
define data-rule
outdir/$(1)/outdata_$(1).file: script.R datadir/$(1)/indata_$(1).file
$(EXEC) $$< $(1)
endef
(具体语法因不同版本的 Make 而异,因此您可能需要在 "define" 行末尾添加“=”。)
我们现在可以使用 call
:
生成 location1
规则的文本
$(call data-rule,location1)
并使用 eval
:
将文本解释为实际的 makefile 代码
$(eval $(call data-rule,location1))
一旦我们验证了这么多有效,我们就可以一条一条地生成规则:
$(eval $(call data-rule,location1))
$(eval $(call data-rule,location2))
$(eval $(call data-rule,location3))
或使用foreach
:
LOCATIONS := location1 location2 location3
$(foreach loc,$(LOCATIONS),$(eval $(call data-rule,$(loc))))
最后,您可能需要一个构建所有这些文件的目标:
all-locations: outdir/location1/outdata_location1.file outdir/location2/outdata_location2.file outdir/location3/outdata_location3.file
您也可以自动执行此构造:
$(foreach loc,$(LOCATIONS),$(eval all-locations: outdir/$(loc)/outdata_$(loc).file))
我在构建各种中间和输出数据文件的 RStudio 项目中有一个 Makefile 规则。一些关键规则如下所示:
outdir/<location>/outdata_<location>.file: script.R datadir/<location>/indata_<location>.file
$(EXEC) $< <location>
其中 location
区分目录以及目标和先决条件的文件名,并且 同时作为参数传递 到 script.R
.
例如,先决条件目录的结构如图所示:
datadir
|- location1
| |- indata_location1.file
| |- ...
|
|- location2
| |- indata_location2.file
| |- ...
|
|- location3
这些目录中的每一个都有不同级别的数据文件,因此决定按位置组织它们。此外,随着时间的推移会添加更多的项目位置,因此需要隐式规则来最大限度地减少不断修改 Makefile 的需要。
我已经尝试使用 GNU Make 文档中描述的模式规则,但它说模式占位符只能在目标或先决条件中出现一次。我尝试使用字符串操作和 foreach
函数,但未能解决它,因为我对 GNU Make 的经验有限。
我在多个目录上看到过类似的 SO 问题,但 none 提到使用区分字符串作为配方中的参数。
如有任何帮助,我们将不胜感激。
您想使用几个非常相似的规则,而方差对于一个模式规则来说太复杂了。这看起来像是 a "canned recipe".
的工作我们写一个模板:
define data-rule
outdir/$(1)/outdata_$(1).file: script.R datadir/$(1)/indata_$(1).file
$(EXEC) $$< $(1)
endef
(具体语法因不同版本的 Make 而异,因此您可能需要在 "define" 行末尾添加“=”。)
我们现在可以使用 call
:
location1
规则的文本
$(call data-rule,location1)
并使用 eval
:
$(eval $(call data-rule,location1))
一旦我们验证了这么多有效,我们就可以一条一条地生成规则:
$(eval $(call data-rule,location1))
$(eval $(call data-rule,location2))
$(eval $(call data-rule,location3))
或使用foreach
:
LOCATIONS := location1 location2 location3
$(foreach loc,$(LOCATIONS),$(eval $(call data-rule,$(loc))))
最后,您可能需要一个构建所有这些文件的目标:
all-locations: outdir/location1/outdata_location1.file outdir/location2/outdata_location2.file outdir/location3/outdata_location3.file
您也可以自动执行此构造:
$(foreach loc,$(LOCATIONS),$(eval all-locations: outdir/$(loc)/outdata_$(loc).file))