2
votes

If I run the following makefile under GNU Make 3.81 / RHEL5:

all: A1B/C A1B/D A2B/C A2B/D

A%B/C A%B/D: E.%
        @echo "Creating '$@' from '$^' with stem '$*'"

E.1 E.2:
        @echo "Generate '$@'"

I get the following output:

Generate 'E.1'
Creating 'A1B/C' from 'E.1' with stem '1'
Generate 'E.2'
Creating 'A2B/C' from 'E.2' with stem '2'

Why are files A1B/D and A2B/D not generated? (files with such names do not exist in my testcase)

If I specify the targets via the command line make states "Nothing to be done":

make A1B/C A1B/D A2B/C A2B/D
Generate 'E.1'
Creating 'A1B/C' from 'E.1' with stem '1'
make: Nothing to be done for `A1B/D'.
Generate 'E.2'
Creating 'A2B/C' from 'E.2' with stem '2'
make: Nothing to be done for `A2B/D'.

If I duplicate the implicit rule into their targets it works:

all: A1B/C A1B/D A2B/C A2B/D

A%B/C: E.%
        @echo "Creating '$@' from '$^' with stem '$*'"

A%B/D: E.%
        @echo "Creating '$@' from '$^' with stem '$*'"

E.1 E.2:
        @echo "Generate '$@'"
Generate 'E.1'
Creating 'A1B/C' from 'E.1' with stem '1'
Creating 'A1B/D' from 'E.1' with stem '1'
Generate 'E.2'
Creating 'A2B/C' from 'E.2' with stem '2'
Creating 'A2B/D' from 'E.2' with stem '2'

According to the documentation this should not make a difference.

Thanks in advance.

Michael

1

1 Answers

2
votes

You're not quite right about the documentation saying there's no difference. If you have a pattern rule with multiple targets (and you do), make assumes both will be made in a single execution of the recipe.

From the GNU make manual:

Pattern rules may have more than one target. Unlike normal rules, this does not act as many different rules with the same prerequisites and recipe. If a pattern rule has multiple targets, make knows that the rule's recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets.

You can confirm this behaviour for your case:

$ make -r -d
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-apple-darwin11.3.0
Reading makefiles...
Reading makefile `Makefile'...
Updating makefiles....
 Considering target file `Makefile'.
  Looking for an implicit rule for `Makefile'.
  No implicit rule found for `Makefile'.
  Finished prerequisites of target file `Makefile'.
 No need to remake target `Makefile'.
Updating goal targets....
Considering target file `all'.
 File `all' does not exist.
 Looking for an implicit rule for `all'.
 No implicit rule found for `all'.
  Considering target file `A1B/C'.
   File `A1B/C' does not exist.
   Looking for an implicit rule for `A1B/C'.
   Trying pattern rule with stem `1'.
   Trying implicit prerequisite `E.1'.
   Found an implicit rule for `A1B/C'.
    Considering target file `E.1'.
     File `E.1' does not exist.
     Finished prerequisites of target file `E.1'.
    Must remake target `E.1'.
Putting child 0x7fcad3c08440 (E.1) PID 34127 on the chain.
Live child 0x7fcad3c08440 (E.1) PID 34127 
Generate 'E.1'
Reaping winning child 0x7fcad3c08440 PID 34127 
Removing child 0x7fcad3c08440 PID 34127 from chain.
    Successfully remade target file `E.1'.
   Finished prerequisites of target file `A1B/C'.
  Must remake target `A1B/C'.
Putting child 0x7fcad3c08710 (A1B/C) PID 34128 on the chain.
Live child 0x7fcad3c08710 (A1B/C) PID 34128 
Creating 'A1B/C' from 'E.1' with stem '1'
Reaping winning child 0x7fcad3c08710 PID 34128 
Removing child 0x7fcad3c08710 PID 34128 from chain.
  Successfully remade target file `A1B/C'.
  Considering target file `A1B/D'.
  File `A1B/D' was considered already.
  Considering target file `A2B/C'.
   File `A2B/C' does not exist.
   Looking for an implicit rule for `A2B/C'.
   Trying pattern rule with stem `2'.
   Trying implicit prerequisite `E.2'.
   Found an implicit rule for `A2B/C'.
    Considering target file `E.2'.
     File `E.2' does not exist.
     Finished prerequisites of target file `E.2'.
    Must remake target `E.2'.
Putting child 0x7fcad3c08cd0 (E.2) PID 34129 on the chain.
Live child 0x7fcad3c08cd0 (E.2) PID 34129 
Generate 'E.2'
Reaping winning child 0x7fcad3c08cd0 PID 34129 
Removing child 0x7fcad3c08cd0 PID 34129 from chain.
    Successfully remade target file `E.2'.
   Finished prerequisites of target file `A2B/C'.
  Must remake target `A2B/C'.
Putting child 0x7fcad3c08cd0 (A2B/C) PID 34130 on the chain.
Live child 0x7fcad3c08cd0 (A2B/C) PID 34130 
Creating 'A2B/C' from 'E.2' with stem '2'
Reaping winning child 0x7fcad3c08cd0 PID 34130 
Removing child 0x7fcad3c08cd0 PID 34130 from chain.
  Successfully remade target file `A2B/C'.
  Considering target file `A2B/D'.
  File `A2B/D' was considered already.
 Finished prerequisites of target file `all'.
Must remake target `all'.
Successfully remade target file `all'.

Notice these lines:

File `A1B/D' was considered already.
File `A2B/D' was considered already.