使用多个作业时,Makefile执行相同的配方两次 [英] Makefile executes the same recipe twice when using multiple jobs

查看:269
本文介绍了使用多个作业时,Makefile执行相同的配方两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找以下玩具Makefile来跟踪错误:

I'm looking at the following toy Makefile to track a bug:

all: hey bye

hey bye: hi
    cat hi
    touch hey bye

在这种情况下,我已经预先创建了hi文件.

In this scenario, I've created the hi file beforehand.

然后运行make -j 2 all并获得以下输出:

I then run make -j 2 all and get the following output:

cat hi
cat hi
hey
touch hey bye
hey
touch hey bye

如果我使用make -j 1 all运行它,则命令仅执行一次.调试输出非常冗长,但是据我了解,它执行了两次,因为它试图用两个不同的工作来满足heybye.

Whereas if I run it with make -j 1 all, the commands get executed only once. The debug output is pretty verbose, but from what I understand, it's executing it twice because it tried to satisfy hey and bye with two different jobs.

如何防止这种情况发生?这是正确的行为吗?为什么认为一次运行两次命令会使命令执行起来更快?

How can I prevent this from happening? Is this correct behaviour? Why does it think running a command twice at once will make it finish faster?

推荐答案

此行为是正确的,因为您误解了您在说的话.

The behavior is correct, because you're misunderstanding what you are telling make.

您可以在 GNU make手册<中阅读详细信息.

此规则:

hey bye: hi
        ...

告诉make一次调用配方将建立两个目标.相反,make的解释方式与您编写时完全相同:

Does not tell make that one invocation of the recipe will build both targets. Instead, make interprets it exactly the same way as if you'd written:

hey: hi
        ...
bye: hi
        ...

也就是说,您已经声明了两个完全不同的目标,其中每个目标将通过分别调用...来创建.

That is, you've declared two completely different targets where each one would be created by a separate invocation of ....

在不使用-j的情况下运行make时,会看到hey已过时并运行配方.然后查看bye,现在(由于以前的配方刚刚对其进行了更新),它是最新的,因此似乎可以使用.

When you run make without -j it sees that hey is out of date and runs the recipe. Then it looks at bye, and now (since the previous recipe just updated it) it's up to date so it seems to work.

但是,如果您使用-j2运行,则会看到hey已过期并开始该作业,然后寻找更多工作.现在,当它检查bye时,hey的配方尚未更新,因此请使它仍然过时,并启动该配方的另一个实例.

But if you run with -j2, make sees hey is out of date and starts that job, then looks for more work. Now when it checks bye, the recipe for hey didn't update it yet so make thinks it's still out of date and starts another instance of the recipe.

解决此问题的最佳方法取决于您未提供的实际使用情况的详细信息.

The best way to fix this depends on the details of your actual usage, which you haven't given.

如果输入和输出与目标名称和前提条件相关,则可以编写模式规则.与显式规则不同,多个目标模式告诉我们一次调用配方就可以构建所有目标:

If your inputs and outputs are related by the names of the targets and prerequisite, you can write a pattern rule. Unlike explicit rules, multiple target patterns tell make that one invocation of the recipe builds all the targets:

%.x %.y : %.z
        ...

如果这行不通,并且您希望将构建限制为使用GNU make 4.3或更高版本,则可以利用分组目标"功能:

If that won't work and you're willing to restrict your builds to using GNU make 4.3 or better you can take advantage of the "grouped targets" feature:

hey bye &: hi
        ...

如果这不可行,则必须使用前哨目标,例如:

If that isn't feasible, you'll have to use a sentinel target, something like:

all: hey bye

hey bye: .sentinel ;

.sentinel: hi
        ...
        @touch $@

这篇关于使用多个作业时,Makefile执行相同的配方两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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