Makefile GNU Make:在单个命令调用中批处理多个目标

Makefile GNU Make:在单个命令调用中批处理多个目标,makefile,build,gnu,Makefile,Build,Gnu,请考虑以下设置: $ touch 1.src 2.src 3.src $ cat Makefile %.dst: %.src @convert -o "$@" "$<" 我们可以通过运行make 1.dst 2.dst 3.dst将.src文件编译成.dst文件,它三次调用convert just a placeholder工具 如果调用convert的开销很小,那么这个设置就可以了。然而,在我的例子中,每次调用都有几秒钟的启动惩罚。幸运

请考虑以下设置:

$ touch 1.src 2.src 3.src
$ cat Makefile
%.dst: %.src
    @convert -o "$@" "$<" 
我们可以通过运行make 1.dst 2.dst 3.dst将.src文件编译成.dst文件,它三次调用convert just a placeholder工具

如果调用convert的开销很小,那么这个设置就可以了。然而,在我的例子中,每次调用都有几秒钟的启动惩罚。幸运的是,该工具可以在一次调用中转换多个文件,同时只需支付一次启动罚款,即convert-o'{}.dst'1.src 2.src 3.src

GNU make中有没有一种方法可以指定将多个src文件批处理为一个转换调用? 编辑:更准确地说,我想要什么功能:假设1.dst已经比1.src更新,所以不需要重新编译。如果我运行make1.dst2.dst3.dst,我希望gnumake执行convert-o'{}.dst'2.src3.src

一个快速而肮脏的方法是创建一个.PHONY规则,简单地将所有src文件转换为dst文件,但这样我每次都会转换每个src文件。此外,在其他规则中将dst文件指定为先决条件也不再可能

提前谢谢

GNU make中有没有一种方法可以指定将多个src文件批处理为一个转换调用

为生成多个目标的构建步骤编写make规则是可能的,但很麻烦,这样,如果任何目标需要更新,那么该配方只执行一次。然而,你澄清了这一点

[如果]1.dst已经比1.src[更新,并且]我运行make 1.dst 2.dst 3.dst,我希望GNU make执行convert-o'{}.dst'2.src 3.src

。这是一个稍微不同的问题。您可以使用$?配方中的自动变量,以获取比规则目标更新的先决条件,但为了达到此目的,您需要具有单个目标的规则

这里有一个稍微复杂的方法来实现它:

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文件都要新:。对于归档文件而言过期但相对于相应的.src文件而言不过期的dst文件将从归档文件中提取,而不是从头重建

GNU make中有没有一种方法可以指定将多个src文件批处理为一个转换调用

为生成多个目标的构建步骤编写make规则是可能的,但很麻烦,这样,如果任何目标需要更新,那么该配方只执行一次。然而,你澄清了这一点

[如果]1.dst已经比1.src[更新,并且]我运行make 1.dst 2.dst 3.dst,我希望GNU make执行convert-o'{}.dst'2.src 3.src

。这是一个稍微不同的问题。您可以使用$?配方中的自动变量,以获取比规则目标更新的先决条件,但为了达到此目的,您需要具有单个目标的规则

这里有一个稍微复杂的方法来实现它:

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文件都要新:。相对于存档文件过期但相对于相应的.src文件不过期的dst文件将从存档文件中提取,而不是从头开始重建。

如果您有GNU make 4.3或更高版本,您可以这样使用:

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仅更新部分目标,则需要显式触摸来更新其余目标

这里有一种方法,通过在命令行上传递一个可能有效的目标;将DST_文件更改为:


如果您有GNU make 4.3或更高版本,您可以这样使用:

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仅更新部分目标,则需要显式触摸来更新其余目标

这里有一种方法,通过在命令行上传递一个可能有效的目标;将DST_文件更改为:


注意$${x//src/dst}是一个不可移植的bash ism:如果你想使用它,你需要将SHELL=/bin/bash添加到你的makefile中。为什么不将配方从ar x$<$@更改为只需触摸$@并将dst.a更改为.sentinel或其他东西来隐藏它呢?谢谢您的回答!看起来,当只生成目标文件的一个子集(例如make 2.dst)时,它仍然会编译所有源文件,对吗?有没有办法解决这个问题?注意$${x//src/dst}是一个不可移植的bash ism:如果你想使用它,你需要将SHELL=/bin/bash添加到你的makefile中。我并不认为有必要使用ar。为什么不呢?
只需将配方从ar x$<$@更改为只需触摸$@并将dst.a更改为.sentinel或其他东西来隐藏它?谢谢您的回答!看起来,当只生成目标文件的一个子集(例如make 2.dst)时,它仍然会编译所有源文件,对吗?有办法吗?谢谢,看起来很干净!有一件事让我不安:如果我运行make 2.dst,它将编译所有比相应的dst文件更新的src文件,尽管我只要求make编译2.dst。这是可修复的吗?你确定你有GNU make 4.3吗?我不能重现那种行为。我会加上一个我所做的例子。哦,我明白你的意思,你带着一个目标跑。是的,你是对的,它将始终构建所有目标,这就是分组目标的含义。如果您不希望出现这种行为,则不能使用此解决方案。当然,你没有在你的问题中把这列为一项要求:没错,我没有明确说明这一点。这不是一个很大的问题,但是你知道这个问题的简单解决方案吗?嗯,也许,这取决于你的makefile还需要做什么。我将编辑我的答案。谢谢,看起来很干净!有一件事让我不安:如果我运行make 2.dst,它将编译所有比相应的dst文件更新的src文件,尽管我只要求make编译2.dst。这是可修复的吗?你确定你有GNU make 4.3吗?我不能重现那种行为。我会加上一个我所做的例子。哦,我明白你的意思,你带着一个目标跑。是的,你是对的,它将始终构建所有目标,这就是分组目标的含义。如果您不希望出现这种行为,则不能使用此解决方案。当然,你没有在你的问题中把这列为一项要求:没错,我没有明确说明这一点。这不是一个很大的问题,但是你知道这个问题的简单解决方案吗?嗯,也许,这取决于你的makefile还需要做什么。我会编辑我的答案。我不会这样做的。当一个文件来自另一个文件时,使用make-j可以有效地并行运行。从建议的答案中可以看出,一步从多个文件中生成多个目标非常笨拙,Makefile变得更复杂,更难维护,并且可能会遇到不同的情况,在这些情况下,它将以不同的方式成为瓶颈。我会考虑降低启动开销是否值得将来的维护。也许一个简单的并行make就足够了?实际上我正在尽可能地使用make-j。convert工具的问题是,启动大约需要3秒钟,编译源代码不到一秒钟。即使我并行运行它,它也会一次又一次地在相同的启动过程中花费大量时间。我不确定是否有可能减少启动开销。该工具是用python编写的,可能会在解释器中花费启动时间。我不会这样做。当一个文件来自另一个文件时,使用make-j可以有效地并行运行。从建议的答案中可以看出,一步从多个文件中生成多个目标非常笨拙,Makefile变得更复杂,更难维护,并且可能会遇到不同的情况,在这些情况下,它将以不同的方式成为瓶颈。我会考虑降低启动开销是否值得将来的维护。也许一个简单的并行make就足够了?实际上我正在尽可能地使用make-j。convert工具的问题是,启动大约需要3秒钟,编译源代码不到一秒钟。即使我并行运行它,它也会一次又一次地在相同的启动过程中花费大量时间。我不确定是否有可能减少启动开销。该工具是用python编写的,可能会在解释器中花费启动时间。