Search code examples
makefilenmake

jom/nmake rule that creats tow files


I am migrating a Makefile from omake.exe (from ClearCase) to jom.exe/nmake.exe.

A simplified Makefile example:

all: bin1 bin2

rule1 rule2: rule3
    @echo creating rule1 and rule2
    @touch rule1 rule2

rule3:
    @echo creating rule3
    @touch rule3

bin1: rule1
    @echo creating bin1
    @touch bin1

bin2: rule2
    @echo creating bin2
    @touch bin2

touch simply creates a file or if it already exists it updates the timestamp.

The output with jom/namke is:

creating rule3
creating rule1 and rule2
creating rule1 and rule2
creating bin1
creating bin2

creating rule1 and rule2 is executed twice.

With omake the rule was executed only once with the meaning to create the files rule1 and rule2 in one command (here with touch).

What do I have to change that the command that creates rule1 and rule2 at the same time only is called once?

Thanks Teddy


Solution

  • I don't know anything about either omake or nmake. But I can give you info about standard (POSIX) make and to the extent that those instances of make adhere to the standard, it may be useful.

    In standard make, this rule:

    rule1 rule2: rule3
             @echo creating rule1 and rule2
             @touch rule1 rule2
    

    never means "one invocation of the recipe builds both targets". It is interpreted to be exactly the same as if you'd written:

    rule1: rule3
             @echo creating rule1 and rule2
             @touch rule1 rule2
    rule2: rule3
             @echo creating rule1 and rule2
             @touch rule1 rule2
    

    So, in one sense the behavior you see from nmake could be expected. Except, it never works like that in POSIX make, because POSIX make always runs one rule at a time. So, first it tries to build rule1 and that actually builds both rule1 and rule2. So then when make investigates whether it needs to build rule2, it sees it is already up to date and doesn't do anything.

    So even though make interprets this rule as two different targets, it has the same effect as only one rule: running the recipe one time updates both targets and make only runs the recipe one time.

    If you use GNU make, or some other make, which supports parallel builds, then this behavior no longer works because make might detect that rule2 is out of date before the recipe for rule1 has a chance to update it. But, that's not POSIX.

    I can't explain why nmake doesn't work like this... it's a pretty odd, and limited, implementation of make.

    The traditional way to handle this in POSIX is by introducing a "sentinel file" that collects these multiple targets into one, like this:

    rule1 rule2 : sentinel ;
    
    sentinel: rule3
             @echo creating rule1 and rule2
             @touch rule1 rule2
             @touch $@
    

    I have no idea if something like that will work in nmake.

    If you use GNU make, it will work or if you use the current release (4.3) you can explicitly declare grouped targets, like this:

    rule1 rule2 &: rule3
             @echo creating rule1 and rule2
             @touch rule1 rule2