在 makefile 的通配符中使用匹配词干
Use match stem in wildcard in makefile
像这样的 Makefile
list-%: $(wildcard src/modules/%/*.ts)
echo '?' $? - '@' $@ - '%' $% - '<' $< - '^' $^ - '+' $+ - '|' $| - '*' $*
但是依赖项没有按预期工作。 make list-test
的输出是
echo '?' - '@' list-test - '%' - '<' - '^' - '+' - '|' - '*' test
? - @ list-test - % - < - ^ - + - | - * test
如果改为$(wildcard src/modules/test/*.ts)
,则输出变为
echo '?' src/modules/test/index.ts - '@' list-test - '%' - '<' src/modules/test/index.ts - '^' src/modules/test/index.ts - '+' src/modules/test/index.ts - '|' - '*' test
? src/modules/test/index.ts - @ list-test - % - < src/modules/test/index.ts - ^ src/modules/test/index.ts - + src/modules/test/index.ts - | - * test
我怎样才能让这个 $(wildcard src/modules/%/*.ts)
工作?
How can I make this $(wildcard src/modules/%/*.ts) work ?
遗憾的是,你不能。 %
仅在先决条件中以非常有限的方式工作。在所有 make
函数都已被求值之后,它被用作最后一个伪通配符,因此没有模式和函数的交互——我可能会想到一些递归构造,但这对于这样一个简单的任务。相反,您可以摆脱程序化的依赖关系:
MODULES := a b c
all: $(MODULES:%=list-%)
@echo DONE
# generate dependencies programmatically:
$(foreach m,$(MODULES),$(eval list-$(m): $(wildcard src/modules/$(m)/*.ts)))
list-%:
@echo $^
@echo $@
请注意,对于 vanilla 目标来说,将依赖项列表分布在多个 target:prerequisite 语句和另一个规则中的配方中是完全合法的。唯一需要注意的是,如果您的列表中有一个不存在的模块,那么它会在先决条件列表为空的情况下执行该模块,并失败并显示一条可能难以理解的错误消息。
有一种方法可以做到这一点,使用 Secondary Expansion。它允许在 %
匹配到字符串后 进行第二次扩展:
.SECONDEXPANSION:
list-%: $$(wildcard src/modules/%/*.ts)
echo '?' $? - '@' $@ - '%' $% - '<' $< - '^' $^ - '+' $+ - '|' $| - '*' $*
注意 $$
。 在读入阶段,$$(wildcard src/modules/%/*.ts)
扩展为 $(wildcard src/modules/%/*.ts)
。然后 Make 选择此模式规则作为构建 list-foo
的方式,并在第二次扩展中 $(wildcard src/modules/foo/*.ts)
扩展为文件名列表。
像这样的 Makefile
list-%: $(wildcard src/modules/%/*.ts)
echo '?' $? - '@' $@ - '%' $% - '<' $< - '^' $^ - '+' $+ - '|' $| - '*' $*
但是依赖项没有按预期工作。 make list-test
的输出是
echo '?' - '@' list-test - '%' - '<' - '^' - '+' - '|' - '*' test
? - @ list-test - % - < - ^ - + - | - * test
如果改为$(wildcard src/modules/test/*.ts)
,则输出变为
echo '?' src/modules/test/index.ts - '@' list-test - '%' - '<' src/modules/test/index.ts - '^' src/modules/test/index.ts - '+' src/modules/test/index.ts - '|' - '*' test
? src/modules/test/index.ts - @ list-test - % - < src/modules/test/index.ts - ^ src/modules/test/index.ts - + src/modules/test/index.ts - | - * test
我怎样才能让这个 $(wildcard src/modules/%/*.ts)
工作?
How can I make this $(wildcard src/modules/%/*.ts) work ?
遗憾的是,你不能。 %
仅在先决条件中以非常有限的方式工作。在所有 make
函数都已被求值之后,它被用作最后一个伪通配符,因此没有模式和函数的交互——我可能会想到一些递归构造,但这对于这样一个简单的任务。相反,您可以摆脱程序化的依赖关系:
MODULES := a b c
all: $(MODULES:%=list-%)
@echo DONE
# generate dependencies programmatically:
$(foreach m,$(MODULES),$(eval list-$(m): $(wildcard src/modules/$(m)/*.ts)))
list-%:
@echo $^
@echo $@
请注意,对于 vanilla 目标来说,将依赖项列表分布在多个 target:prerequisite 语句和另一个规则中的配方中是完全合法的。唯一需要注意的是,如果您的列表中有一个不存在的模块,那么它会在先决条件列表为空的情况下执行该模块,并失败并显示一条可能难以理解的错误消息。
有一种方法可以做到这一点,使用 Secondary Expansion。它允许在 %
匹配到字符串后 进行第二次扩展:
.SECONDEXPANSION:
list-%: $$(wildcard src/modules/%/*.ts)
echo '?' $? - '@' $@ - '%' $% - '<' $< - '^' $^ - '+' $+ - '|' $| - '*' $*
注意 $$
。 在读入阶段,$$(wildcard src/modules/%/*.ts)
扩展为 $(wildcard src/modules/%/*.ts)
。然后 Make 选择此模式规则作为构建 list-foo
的方式,并在第二次扩展中 $(wildcard src/modules/foo/*.ts)
扩展为文件名列表。