我正在尝试编写一个 makefile,其中有一个 .asy 文件列表,每个文件都会生成 .png 或 .pdf。
我通过查看文件获得了正确的扩展名,因此我有它们生成的源和对象的列表:
asy_to_ext = $(shell sed -n \
's#^settings.outformat *= *"\([a-z]*\)" *;#\1#p' \
$(file) | tail -1)
ASY_SRC := $(wildcard *.asy)
ASY_EXT := $(foreach file,$(ASY_SRC),$(asy_to_ext))
ASY_OBJ := $(ASY_SRC:.asy=.$(ASY_EXT))
我的问题是:现在,如何告诉 make 每个对象都依赖于相应的源?使用单个扩展,静态模式规则就可以了:
$(ASY_OBJ) : %.png: %.asy
asy -noView -nointeractiveView $<
但我在手册中找不到任何类似于带有通配符的模式规则的内容,例如$(ASY_OBJ) : %.*: %.asy
或使用我喜欢的源列表
$(ASY_OBJ) : $(ASY_SRC)
。
我也尝试过双冒号规则,但它们只处理第一个对象,直到其中一个规则不匹配为止,而且理想情况下,我正在寻找即使 ASY_OBJ 最终具有与 .pdf 或 . .png
$(ASY_OBJ) :: %.png: %.asy
asy -noView -nointeractiveView $<
$(ASY_OBJ) :: %.pdf: %.asy
asy -noView -nointeractiveView $<
答案1
自从我最终找到方法以来,我要回答自己:解决方案是二次扩张,它允许在先决条件列表中使用自动变量。这样,无论目标的扩展名最终是什么,都可以将其剥离并替换为 .asy。
我还没有意识到我获取 ASY_EXT 的函数无法正常工作,这是通过使用中给出的映射函数解决的手册。
# function returning the extension of the generated file
asy_to_ext = $(shell sed -n \
's#^settings.outformat *= *"\([a-z]*\)" *;#\1#p' \
$(1) | tail -1)
map = $(foreach a,$(2),$(call $(1),$(a)))
ASY_SRC := $(wildcard *.asy)
ASY_EXT := $(call map,asy_to_ext,$(ASY_SRC))
# build the target list by adding the computed extension to the basename of the sources
ASY_OBJ := $(join $(basename $(ASY_SRC)),$(addprefix .,$(ASY_EXT)))
.PHONY: asy
asy : $(ASY_OBJ)
# compute the prerequisite by adding .asy to the basename of the target
.SECONDEXPANSION:
$(ASY_OBJ) : $$(addsuffix .asy,$$(basename $$@))
asy -noView -nointeractiveView $<