GNU make 具有不同文件基名的模式规则
GNU make pattern rules with different file base names
我有一个数据处理工作,我想用 Make 自动完成。需要分几个步骤处理数百个文件。
不幸的是,至少有一个步骤的基本名称会发生变化,但是将这些依赖项写入一个单独的文件然后包含在内会很容易。
但是,我还想避免为所有这些文件单独编写构建说明(非常复杂)。
我的设想是这样的:
# automatically generated rules, included into make file
dir1/test.bb: dir2/test_other_name.aa
# (many more rules like the above, linking xxx.bb to yyy.aa)
# pattern rule
%.bb: %.aa
# build step using $@ $>
我想要的是提供规则的模式规则,以及定义依赖关系的显式规则。这样的东西能实现吗?
当make的noddy模式不切芥末时,
只需明确写出规则即可。
(这具有不使用模式规则的快乐副作用。)
假设您有一个函数 src-to-target
,它将生成目标文件名(即 $(call src-to-target,dir2/test_other_name.aa)
扩展为 dir1/test.bb
。
此外,您在 ${srcs}
中有一个源列表,${recipe}
是一个使用 $@
、$<
等的 shell 命令列表。
define src-to-target = ... # :source
define recipe =
echo Building $@ from $<
⋮
endef
define generate-rule = # :source
target := $(call src-to-taget,)
targets += $${target}
$${target}: ; $${recipe}
endef
$(foreach _,${srcs},$(eval $(call generate-rule,$_)))
.PHONY: all
all: ${targets} ; : $@ Success
$(foreach ...)
在这里完成所有工作。
所以,从痛苦的细节来看,
- 先展开
${srcs}
- 将
$_
设置为列表中的第一个(dir2/test_other_name.aa
说)
展开$(call generate-rule,$_)
- 展开
$(call generate-rule,dir2/test_other_name.aa)
</code> 设置为 <code>dir2/test_other_name.aa
,$(generate-rule)
的扩展紧随其后,导致此文本块
target := dir1/test.bb
targets += ${target}
${target}: dir2/test_other_name.aa ; ${recipe}
作为副作用,$(eval)
吞掉了上面的文字。 $(eval)
的扩展虽然是空的。
$_
设置为下一个源文件。
- 清洗、起泡沫、漂洗、重复
一旦 $(foreach)
完成,
${targets}
包含完整的目标列表。
并行安全。
有什么不喜欢的?
我有一个数据处理工作,我想用 Make 自动完成。需要分几个步骤处理数百个文件。 不幸的是,至少有一个步骤的基本名称会发生变化,但是将这些依赖项写入一个单独的文件然后包含在内会很容易。
但是,我还想避免为所有这些文件单独编写构建说明(非常复杂)。
我的设想是这样的:
# automatically generated rules, included into make file
dir1/test.bb: dir2/test_other_name.aa
# (many more rules like the above, linking xxx.bb to yyy.aa)
# pattern rule
%.bb: %.aa
# build step using $@ $>
我想要的是提供规则的模式规则,以及定义依赖关系的显式规则。这样的东西能实现吗?
当make的noddy模式不切芥末时, 只需明确写出规则即可。 (这具有不使用模式规则的快乐副作用。)
假设您有一个函数 src-to-target
,它将生成目标文件名(即 $(call src-to-target,dir2/test_other_name.aa)
扩展为 dir1/test.bb
。
此外,您在 ${srcs}
中有一个源列表,${recipe}
是一个使用 $@
、$<
等的 shell 命令列表。
define src-to-target = ... # :source
define recipe =
echo Building $@ from $<
⋮
endef
define generate-rule = # :source
target := $(call src-to-taget,)
targets += $${target}
$${target}: ; $${recipe}
endef
$(foreach _,${srcs},$(eval $(call generate-rule,$_)))
.PHONY: all
all: ${targets} ; : $@ Success
$(foreach ...)
在这里完成所有工作。
所以,从痛苦的细节来看,
- 先展开
${srcs}
- 将
$_
设置为列表中的第一个(dir2/test_other_name.aa
说) 展开
$(call generate-rule,$_)
- 展开
$(call generate-rule,dir2/test_other_name.aa)
</code> 设置为 <code>dir2/test_other_name.aa
,$(generate-rule)
的扩展紧随其后,导致此文本块
target := dir1/test.bb
targets += ${target}
${target}: dir2/test_other_name.aa ; ${recipe}
- 展开
作为副作用,
$(eval)
吞掉了上面的文字。$(eval)
的扩展虽然是空的。$_
设置为下一个源文件。- 清洗、起泡沫、漂洗、重复
一旦 $(foreach)
完成,
${targets}
包含完整的目标列表。
并行安全。 有什么不喜欢的?