通过一个配方并并行执行多个目标 [英] multiple targets from one recipe and parallel execution

查看:45
本文介绍了通过一个配方并并行执行多个目标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含代码生成器的项目,该生成器仅需调用一次代码生成器就可以从一个输入文件生成多个.c和.h文件.我有一个规则,其中将.c和.h文件作为多个目标,将输入文件作为前提,而配方是对代码生成器的调用.然后,我有了进一步的规则来编译和链接生成的.c文件.

I have a project which includes a code generator which generates several .c and .h files from one input file with just one invocation of the code generator. I have a rule which has the .c and .h files as multiple targets, the input file as the prerequisite, and the recipe is the invocation of the code generator. I then have further rules to compile and link the generated .c files.

在-j因子为1的情况下可以正常工作,但是如果增加j因子,则会发现我多次调用代码生成器,直到-j因子或预期目标文件的数量为止,以最小者为准.这很不好,因为多次生成代码会多次写入代码生成器,从而导致失败.

This works fine with a -j factor of 1, but if I increase the j factor, I find I get multiple invocations of the code generator, up to the -j factor or the number of expected target files, whichever is smallest. This is bad because multiple invocations of the code generator can cause failures due to the generated code being written multiple times.

我不会在这里发布实际的(大)代码,但是我已经能够构建一个小的示例,该示例似乎演示了相同的行为.

I'm not going to post my actual (large) code here, but I have been able to construct a small example which appears to demonstrate the same behavior.

Makefile看起来像这样:

The Makefile looks like this:


output.concat: output5 output4 output3 output2 output1
    cat $^ > $@

output1 output2 output3 output4 output5: input
    ./frob input

clean:
    rm -rf output*

在此示例中,我编写了一个简单的shell脚本frob,而不是代码生成器,该脚本从一个输入文件生成多个输出文件:

Instead of a code generator, for this example I have written a simple shell script, frob which generates multiple output files from one input file:


#!/bin/bash

for i in {1..5}; do
    {
    echo "This is output${i}, generated from ${1}. input was:"
    cat ${1}
    } > output${i}
done

当我使用非unity -j因素运行此Makefile时,得到以下输出:

When I run this Makefile with non-unity -j factors, I get the following output:


$ make -j2 
./frob input
./frob input
cat output5 output4 output3 output2 output1 > output.concat
$

我们看到./frob在这里被调用了两次,这很糟糕.有什么方法可以构造该规则,以便即使使用非统一的-j因子,配方也只能被调用一次?

We see ./frob here gets invoked twice, which is bad. Is there some way I can construct this rule such that the recipe only gets invoked once, even with a non-unity -j factor?

我已经考虑过更改规则,以便仅将一个预期输出文件作为目标,然后添加没有配方的另一条规则,使其目标成为剩余的预期输出文件,而前提条件是第一个预期输出文件.但是我不确定这是否行得通,因为我不知道是否可以保证文件的生成顺序,因此最终可能会产生循环依赖性.

I have considered changing the rule so that just one of the expected output files is the target, then adding another rule with no recipe such that its targets are the remaining expected output files, and the prerequisite is the first expected output file. But I'm not sure this would work, because I don't know if I can guarantee the order in which the files are generated, and thus may end up with circular dependencies.

推荐答案

这是定义make的工作方式.这样的规则:

This is how make is defined to work. A rule like this:

foo bar baz : boz ; $(BUILDIT)

完全等同于编写以下三个规则:

is exactly equivalent, to make, to writing these three rules:

foo : boz ; $(BUILDIT)
bar : boz ; $(BUILDIT)
baz : boz ; $(BUILDIT)

(在GNU make中)无法用您想要的特征来定义一个明确的规则.也就是说,一次调用配方将建立所有三个目标.

There is no way (in GNU make) to define an explicit rule with the characteristics you want; that is that one invocation of the recipe will build all three targets.

但是,如果您的输出文件和输入文件具有相同的基础,则可以编写如下的模式规则:

However, if your output files and your input file share a common base, you CAN write a pattern rule like this:

%.foo %.bar %.baz : %.boz ; $(BUILDIT)

奇怪的是,对于具有多个目标的隐式规则,GNU make假定对配方的一次调用将构建所有目标,并且其行为将完全符合您的期望.

Strangely, for implicit rules with multiple targets GNU make assumes that a single invocation of the recipe WILL build all the targets, and it will behave exactly as you want.

这篇关于通过一个配方并并行执行多个目标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆