GNU Make:在单个命令调用中批量处理多个目标
GNU Make: Batching multiple targets in single command invocation
考虑以下设置:
$ touch 1.src 2.src 3.src
$ cat Makefile
%.dst: %.src
@convert -o "$@" "$<"
我们可以通过 运行ning make 1.dst 2.dst 3.dst
调用 convert
(只是一个占位符)工具三次将我们的 .src
文件编译成 .dst
文件.
如果调用 convert
的开销很小,则此设置很好。但是,就我而言,每次调用都有几秒钟的启动时间。幸运的是,该工具可以在一次调用中转换多个文件,而只需支付一次启动惩罚,即 convert -o '{}.dst' 1.src 2.src 3.src
.
GNU make 中有没有一种方法可以指定多个 src 文件应该被批处理到对 convert
的单个调用中?
编辑:更准确地说,我正在寻找什么功能:假设 1.dst
已经比 1.src
更新,因此不需要重新编译。如果我 运行 make 1.dst 2.dst 3.dst
,我希望 GNU make 执行 convert -o '{}.dst' 2.src 3.src
.
一种快速而肮脏的方法是创建一个 .PHONY
规则,该规则仅将所有 src 文件转换为 dst 文件,但这样我每次都会转换每个 src 文件。此外,也不再可能将 dst 文件指定为其他规则中的先决条件。
提前致谢!
Is there a way in GNU make to specify that multiple src files should be batched into a single call to convert
?
可以,但很麻烦,为生成多个目标的构建步骤编写 make
规则,使用单个 运行 配方,这样如果有任何一个配方只执行一次目标需要更新。但是,您澄清
[if] 1.dst
is already newer than 1.src
[, and] I run make 1.dst 2.dst 3.dst
, I would like GNU make to execute convert -o '{}.dst' 2.src 3.src
.
。这是一个稍微不同的问题。您可以在配方中使用 $?
自动变量来获取比规则目标更新的先决条件,但为了达到目的,您需要一个带有 single[=31= 的规则] 目标。
这里有一个稍微复杂的方法来让它工作:
DST_FILES = 1.dst 2.dst 3.dst
SRC_FILES = $(DST_FILES:.dst=.src)
$(DST_FILES): dst.a
ar x $< $@
dst.a: $(SRC_FILES)
convert -o '{}.dst' $?
x='$?'; ar cr $@ $${x//src/dst}
dst.a
存档作为一个目标,以所有.src文件为前提,为$?
的使用提供基础。此外,它还针对以下问题提供了一种解决方法,即无论何时更新该目标,它都会变得比所有当时存在的 .dst 文件更新:.dst 文件相对于存档已过时,但相对于相应的 .dst 文件则不是。 src 文件是从存档中提取的,而不是从头开始重建的。
如果你有 GNU make 4.3 或更高版本,你可以这样使用 grouped targets:
DST_FILES = 1.dst 2.dst 3.dst
SRC_FILES = $(_DST_FILES:.dst=.src)
all: $(DST_FILES)
$(DST_FILES) &: $(SRC_FILES)
convert -o '{}.dst' $?
@touch $(DST_FILES)
如果您的 convert
只更新了一些目标,那么您需要显式 touch
来更新其余目标。
这是一种通过在命令行上传递可能有效的目标来实现的方法;将 DST_FILES
更改为:
DST_FILES := $(or $(filter %.dst,$(MAKECMDGOALS)),1.dst 2.dst 3.dst)
考虑以下设置:
$ touch 1.src 2.src 3.src
$ cat Makefile
%.dst: %.src
@convert -o "$@" "$<"
我们可以通过 运行ning make 1.dst 2.dst 3.dst
调用 convert
(只是一个占位符)工具三次将我们的 .src
文件编译成 .dst
文件.
如果调用 convert
的开销很小,则此设置很好。但是,就我而言,每次调用都有几秒钟的启动时间。幸运的是,该工具可以在一次调用中转换多个文件,而只需支付一次启动惩罚,即 convert -o '{}.dst' 1.src 2.src 3.src
.
GNU make 中有没有一种方法可以指定多个 src 文件应该被批处理到对 convert
的单个调用中?
编辑:更准确地说,我正在寻找什么功能:假设 1.dst
已经比 1.src
更新,因此不需要重新编译。如果我 运行 make 1.dst 2.dst 3.dst
,我希望 GNU make 执行 convert -o '{}.dst' 2.src 3.src
.
一种快速而肮脏的方法是创建一个 .PHONY
规则,该规则仅将所有 src 文件转换为 dst 文件,但这样我每次都会转换每个 src 文件。此外,也不再可能将 dst 文件指定为其他规则中的先决条件。
提前致谢!
Is there a way in GNU make to specify that multiple src files should be batched into a single call to
convert
?
可以,但很麻烦,为生成多个目标的构建步骤编写 make
规则,使用单个 运行 配方,这样如果有任何一个配方只执行一次目标需要更新。但是,您澄清
[if]
1.dst
is already newer than1.src
[, and] I runmake 1.dst 2.dst 3.dst
, I would like GNU make to executeconvert -o '{}.dst' 2.src 3.src
.
。这是一个稍微不同的问题。您可以在配方中使用 $?
自动变量来获取比规则目标更新的先决条件,但为了达到目的,您需要一个带有 single[=31= 的规则] 目标。
这里有一个稍微复杂的方法来让它工作:
DST_FILES = 1.dst 2.dst 3.dst
SRC_FILES = $(DST_FILES:.dst=.src)
$(DST_FILES): dst.a
ar x $< $@
dst.a: $(SRC_FILES)
convert -o '{}.dst' $?
x='$?'; ar cr $@ $${x//src/dst}
dst.a
存档作为一个目标,以所有.src文件为前提,为$?
的使用提供基础。此外,它还针对以下问题提供了一种解决方法,即无论何时更新该目标,它都会变得比所有当时存在的 .dst 文件更新:.dst 文件相对于存档已过时,但相对于相应的 .dst 文件则不是。 src 文件是从存档中提取的,而不是从头开始重建的。
如果你有 GNU make 4.3 或更高版本,你可以这样使用 grouped targets:
DST_FILES = 1.dst 2.dst 3.dst
SRC_FILES = $(_DST_FILES:.dst=.src)
all: $(DST_FILES)
$(DST_FILES) &: $(SRC_FILES)
convert -o '{}.dst' $?
@touch $(DST_FILES)
如果您的 convert
只更新了一些目标,那么您需要显式 touch
来更新其余目标。
这是一种通过在命令行上传递可能有效的目标来实现的方法;将 DST_FILES
更改为:
DST_FILES := $(or $(filter %.dst,$(MAKECMDGOALS)),1.dst 2.dst 3.dst)