Makefile executes the same recipe twice when using multiple jobs

徘徊边缘 提交于 2020-06-01 05:12:07

问题


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

all: hey bye

hey bye: hi
    cat hi
    touch hey bye

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

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

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

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?


回答1:


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

You can read the details in the GNU make manual.

This rule:

hey bye: hi
        ...

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 ....

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.

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
        ...

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 $@


来源:https://stackoverflow.com/questions/61937812/makefile-executes-the-same-recipe-twice-when-using-multiple-jobs

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!