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} 包含完整的目标列表。

并行安全。 有什么不喜欢的?