0
A/a A/b A/c ... A/n:
  ./do-something.sh # creates all n-files in one run

And:

all: A/a A/b A/c ... A/n

plays nice in a single threaded make, but when I run make -j 16, for example, sixteen independent runs of ./do-something.sh get spawned.

Is there a makish way to inhibit that, and tell make that the rule should be run one time?

Chris
  • 28,822
  • 27
  • 83
  • 158
  • Do you mean *14* independent runs get scheduled? Because that's what should happen, even in single-processing mode. Remember that `make` is *target*-centric, not *rule*-centric. Each target is built at most once, but if the same rule is applicable for building multiple targets then that rule may run more than once. – John Bollinger Sep 13 '20 at 21:41

2 Answers2

3

In GNU make if you can structure your rule as a pattern rule, then it behaves this way (one invocation creates all targets) automatically and always has.

If you can't structure your rule as a pattern rule (the targets don't have any common substrings) then you can either use a kludge such as mentioned by Christopher, except they forgot the touch command and that there should be a no-op command for the real targets:

craft-A:
       ./do-something.sh A
       @touch $@

A/a A/b A/... A/inf: craft-A ;

Or you can move to GNU make 4.3 which supports the &: grouped target capability, and write:

A/a A/b A/c ... A/n &:
        ./do-something.sh # creates all n-files in one run
MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • yes, this is what I am calling a "kludge", and have been doing things this way for years. My hope one day is that I don't have all this make dandruff lying around in my automation nodes. – Chris Sep 14 '20 at 14:03
  • 1
    See my final paragraph: "one day" is today... assuming you have a new-enough version of GNU make. – MadScientist Sep 14 '20 at 14:10
  • my bad. should have read it completely. was ready for a flaming. Here is a link to an explanation of the no-op command: https://stackoverflow.com/questions/31662514/what-is-noop-typically-used-for-in-makefile – Chris Sep 14 '20 at 14:37
1

Well, as always, make yields to some cleverness, and there is a reason this was not implemented:

craft-A:
  ./do-something.sh A
A/a A/b A/... A/inf: craft-A

all: A/... 

$: make -j 100 all

Works. But, the can is kicked down the road: the rule is not idempotent. So it is an answer, but it seems to be very hard to make it idempotent without a kludge.

Chris
  • 28,822
  • 27
  • 83
  • 158