GNU Make 3.82下能否动态生成规则及实现Shell补全匹配?
问题与解答
场景说明
现有Makefile内容如下:
items=Excelsior Shibboleth AbraCadabra ceremony@%: foo bar biz baz $* ritual@%: ding ring bing bong $* ceremonies: $(foreach item,$(items),ceremony@$(item)) rituals: $(foreach item,$(items),ritual@$(item)) all: ceremonies | rituals
由于ceremonies和rituals下的子目标执行耗时,且希望Makefile保持简洁、支持命令自动补全提升易用性,期望实现:
- 为预定义的
items动态生成形如$(item)@ritual的目标(伪代码如下,但GNU Make 3.82下无法运行):
# 伪代码——GNU Make 3.82下不生效 $(foreach item,$(items),$(item)@ritual: ritual@$(item))
要求实现后触发tab补全时能显示这些分项命令,同时避免Makefile过于冗长。
核心问题
上述动态生成目标的需求是否可行?
衍生问题
若使用通配符规则,能否在zsh/bash的tab补全中生成匹配规则的结果?
解答
1. 动态生成目标的可行方案(兼容GNU Make 3.82)
GNU Make 3.82支持通过eval函数实现动态规则生成,这是实现需求的关键。修改后的代码如下:
items=Excelsior Shibboleth AbraCadabra ceremony@%: foo bar biz baz $* ritual@%: ding ring bing bong $* # 动态生成反向依赖目标 $(foreach item,$(items),\ $(eval $(item)@ceremony: ceremony@$(item))\ $(eval $(item)@ritual: ritual@$(item))\ ) ceremonies: $(foreach item,$(items),ceremony@$(item)) rituals: $(foreach item,$(items),ritual@$(item)) all: ceremonies | rituals
eval函数会将参数内容作为Makefile代码执行,因此可以在循环中动态创建Excelsior@ritual、Shibboleth@ceremony这类目标,每个目标都依赖对应的ritual@%或ceremony@%规则。- 这些动态生成的目标会被Make的自动补全机制识别(只要shell的make补全脚本支持解析动态生成的目标),tab补全时会显示所有
$(item)@ceremony和$(item)@ritual形式的命令。
2. 通配符规则与shell补全的兼容性
默认情况下,zsh/bash的make补全脚本不会自动解析通配符规则生成补全候选。因为补全脚本通常只会扫描Makefile中显式定义的目标,而通配符规则是隐式的,无法提前枚举所有可能的匹配项。
如果要让通配符规则支持补全,需要自定义shell补全脚本:
- 针对bash:可以扩展
_make补全函数,提取Makefile中的通配符规则模板,结合预定义的items列表生成补全候选。 - 针对zsh:可以修改
_make补全逻辑,类似bash的思路,从Makefile中读取items变量,再结合通配符规则生成对应的目标候选。
但这种方式需要额外编写shell补全脚本,复杂度较高,不如直接用eval动态生成显式目标来得直接。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

