1

I have a makefile and want to make sure that all the rules are executed sequentially, that is, that no parallel execution is performed.

I believe I have three ways of achieving this:

  • With .NOTPARALLEL target,
  • By calling make using make -j 1,
  • By setting the flag directly in the makefile, e.g., MAKEFLAGS := -j 1

Is there a "best practice" between those three, and which one is the more robust?

For instance, is it an overkill to do

MAKEFLAGS := --jobs=1

.NOTPARALLEL:
all:foo bar

.NOTPARALLEL:
foo:bar

.NOTPARALLEL:
bar:
    @echo "test" 

?

1 Answer 1

2

Yes, this is overkill.

As far as the three options go:

  • You should never set MAKEFLAGS, for two reasons: it will cause issues with any flags passed on the command-line, and MAKEFLAGS doesn’t work in a way that can be robustly modified externally. To see both of these problems in action, add an @echo $(MAKEFLAGS) rule to your bar recipe, and run make -n bar.

  • make -j 1 has the effect you’re after, but it is most appropriate when you want to temporarily run everything serially. This is useful if you want to limit the resources used, or if you’re debugging a parallel execution issue. It is also the default, at least in GNU Make: Make only runs one task at a time by default.

  • .NOTPARALLEL: only needs to be specified once, also has the effect you’re after, and is appropriate when the serialisation requirement is a property of the Makefile, i.e. all executions should be serial without possible external influence.

If your build is going to be used at lot however, it’s best in my opinion to spend the time needed to figure out why parallel execution of rules causes problems, and add the appropriate dependencies. GNU Make supports order-only prerequisites which can be used to enforce ordering without enforcing a “newness” dependency; these are often helpful in such circumstances. See this answer to the question you found on SO.

2
  • Thanks a lot. That particular makefile is used for benchmarking purposes, so being entirely sequential is important. Could you clarify "NOTPARALLEL: only needs to be specified once": is it redundant to have it 3 times like in my example? Is it enough to place it once before any rule for it to apply to all the rules?
    – Clément
    Commented May 7, 2022 at 19:09
  • 1
    .NOTPARALLEL doesn’t come before a rule; it’s a separate target. It doesn’t mean “the following rule mustn’t run in parallel”; it means “this whole Makefile mustn’t run in parallel”. It is therefore redundant to have it three times. Commented May 7, 2022 at 21:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .