我的目标中的某些文件依赖于其他目标。我可以通过添加像这样的显式规则来确保正确的构建:
static/app.mjs: js2/.legacy_app.built.mjs
static/admin_unit.mjs: js2/.legacy_admin.built.mjs
static/admin_source.mjs: js2/.legacy_admin.built.mjs
static/admin_module.mjs: js2/.legacy_admin.built.mjs
但这意味着每次我向项目中添加新的“ admin_X”源时都要更改Makefile。我想做的是制定一个全面的模式规则,例如:
static/app.mjs: js2/.legacy_app.built.mjs
static/admin_%.mjs: js2/.legacy_admin.built.mjs
但这不起作用,如https://stackoverflow.com/a/3734705/179583所述:
完全没有配方的模式规则被记录为含义完全不同的东西[...:],它们取消了任何预先存在的隐式规则
是否有一种干净的方法来指定“与特定模式匹配的任何目标”取决于某个特定的其他目标?
答案 0 :(得分:1)
如果所有这些文件已存在于文件系统中(即不应该由make从头开始构建),则可以使用$(wildcard ...)
:
$(wildcard static/admin_*.mjs): js2/.legacy_admin.built.mjs
答案 1 :(得分:0)
您知道,模式规则如下:
static/admin_%.mjs: js2/.legacy_admin.built.mjs
recipe...
不指定任何目标,仅用于发现的模板 您指定否则的目标的先决条件, 并附有根据前提条件制定这些目标的方法。
因此,您的makefile中必须有 else 来确定 目标是什么。假设它只是一个列表,如:
$ cat Makefile
MJS_STEMS := app admin_unit admin_source admin_module
MJS_FILES := $(addprefix static/,$(MJS_STEMS:%=%.mjs))
.PHONY: all clean
all: $(MJS_FILES)
$(MJS_FILES): js2/.legacy_admin.built.mjs
static/%.mjs: | static
@echo $< > $@
@echo "$@ depends on $<"
js2/.legacy_admin.built.mjs: | js2
touch $@
static js2:
mkdir -p $@
clean:
$(RM) $(MJS_FILES) js2/.legacy_admin.built.mjs
在这里
$(MJS_FILES): js2/.legacy_admin.built.mjs
说$(MJS_FILES)
中的每一个都取决于js2/.legacy_admin.built.mjs
。
这是没有模式规则的最简洁方法。 make运行如下:
$ make
mkdir -p static
mkdir -p js2
touch js2/.legacy_admin.built.mjs
static/app.mjs depends on js2/.legacy_admin.built.mjs
static/admin_unit.mjs depends on js2/.legacy_admin.built.mjs
static/admin_source.mjs depends on js2/.legacy_admin.built.mjs
static/admin_module.mjs depends on js2/.legacy_admin.built.mjs
如果需要,可以将MJS_STEMS
列表的维护移出
将makefile转换为另一个文件:
$ cat ./mjs_stems
app
admin_unit
admin_source
admin_module
$ cat Makefile
MJS_STEMS := $(shell cat ./mjs_stems)
MJS_FILES := $(addprefix static/,$(MJS_STEMS:%=%.mjs))
.PHONY: all clean
all: $(MJS_FILES)
$(MJS_FILES): js2/.legacy_admin.built.mjs
static/%.mjs: | static
@echo $< > $@
@echo "$@ depends on $<"
js2/.legacy_admin.built.mjs: | js2
touch $@
static js2:
mkdir -p $@
clean:
$(RM) $(MJS_FILES) js2/.legacy_admin.built.mjs
$ make clean
rm -f static/app.mjs static/admin_unit.mjs static/admin_source.mjs static/admin_module.mjs js2/.legacy_admin.built.mjs
$ echo "admin_foobar" >> mjs_stems
$ make
touch js2/.legacy_admin.built.mjs
static/app.mjs depends on js2/.legacy_admin.built.mjs
static/admin_unit.mjs depends on js2/.legacy_admin.built.mjs
static/admin_source.mjs depends on js2/.legacy_admin.built.mjs
static/admin_module.mjs depends on js2/.legacy_admin.built.mjs
static/admin_foobar.mjs depends on js2/.legacy_admin.built.mjs
或者您也可以从环境中获取MJS_STEMS
列表:
$ cat Makefile
MJS_STEMS := $(strip $(MJS_STEMS))
MJS_FILES := $(addprefix static/,$(MJS_STEMS:%=%.mjs))
.PHONY: all clean
all: $(MJS_FILES)
$(MJS_FILES): js2/.legacy_admin.built.mjs
static/%.mjs: | static
@echo $< > $@
@echo "$@ depends on $<"
js2/.legacy_admin.built.mjs: | js2
touch $@
static js2:
mkdir -p $@
clean:
$(RM) $(MJS_FILES) js2/.legacy_admin.built.mjs
$ make clean
rm -f static/app.mjs static/admin_unit.mjs static/admin_source.mjs static/admin_module.mjs static/admin_foobar.mjs js2/.legacy_admin.built.mjs
$ export MJS_STEMS=$(cat ./mjs_stems)
$ make
touch js2/.legacy_admin.built.mjs
static/app.mjs depends on js2/.legacy_admin.built.mjs
static/admin_unit.mjs depends on js2/.legacy_admin.built.mjs
static/admin_source.mjs depends on js2/.legacy_admin.built.mjs
static/admin_module.mjs depends on js2/.legacy_admin.built.mjs
static/admin_foobar.mjs depends on js2/.legacy_admin.built.mjs
$ make clean
rm -f static/app.mjs static/admin_unit.mjs static/admin_source.mjs static/admin_module.mjs static/admin_foobar.mjs js2/.legacy_admin.built.mjs
$ export MJS_STEMS="aa bb cc"
$ make
touch js2/.legacy_admin.built.mjs
static/aa.mjs depends on js2/.legacy_admin.built.mjs
static/bb.mjs depends on js2/.legacy_admin.built.mjs
static/cc.mjs depends on js2/.legacy_admin.built.mjs
$ make clean
rm -f static/aa.mjs static/bb.mjs static/cc.mjs js2/.legacy_admin.built.mjs
但是在某处,您必须指定目标列表,并且 要添加新目标,您必须进行更新。
答案 2 :(得分:0)
在所有相关文件都是通过自己的特定配方构建的特殊情况下,我发现了另一种技巧。即在通常情况下,此操作无效不起作用,除非您已拆分或可以为所讨论的目标重复单独的配方。
当然,通过虚假目标绑定公共依赖关系很简单。此ADMIN
目标取决于共享的中间文件,然后依次将其指定为模式匹配配方的先决条件:
.PHONY: ADMIN
ADMIN: js2/.legacy_admin.built.mjs
static/admin_%.mjs static/admin_%.mjs.map: js2/admin_%.build.mjs ADMIN FORCE
node_modules/.bin/rollup --config rollup.config.js $< --format esm --sourcemap -o $@
# …also contains recipe to build "js2/.legacy_admin.built.mjs" itself
现在在构建任何 static/admin_%.mjs
文件之前,请确保已创建公共js2/.legacy_admin.built.mjs
帮助文件。
(请参见when multiple pattern rules match a target,了解Make的各种版本如何选择要使用的食谱。)