[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug #19108] Pattern rules with multiple target patterns do not honor th

From: Christoph Schulz
Subject: [bug #19108] Pattern rules with multiple target patterns do not honor the dependencies of all targets correctly
Date: Tue, 20 Feb 2007 13:45:25 +0000
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv: Gecko/20061206 Firefox/


                 Summary: Pattern rules with multiple target patterns do not
honor the dependencies of all targets correctly
                 Project: make
            Submitted by: kristovschulz
            Submitted on: Dienstag 20.02.2007 um 14:45
                Severity: 3 - Normal
              Item Group: Bug
                  Status: None
                 Privacy: Public
             Assigned to: None
             Open/Closed: Open
         Discussion Lock: Any
       Component Version: 3.81
        Operating System: Any
           Fixed Release: None



[Tested on Windows with native (non-MSYS) MinGW build of GNU make 3.81, found
in http://prdownloads.sourceforge.net/mingw/mingw32-make-3.81-1.tar.gz, and on
Gentoo Linux with portage-compiled make 3.81.]


I think I've found a bug in GNU make. When a pattern rule with multiple
targets exists, and make determines that it needs that rule to built one
matching target, it uses this rule even if the other targets implicitly built
by this rule don't have their dependencies built yet.

As this is quite complicated to explain, I created a little example:

final: x
        @echo "making final"
        touch $@
x: x.tgt1 x.tgt2
        @echo "making x"
        touch $@
x.tgt2: dep
        @echo "making dep"
        sleep 5
        touch $@
%.tgt1 %.tgt2: %.src
        cp $< $(patsubst %.src,%.tgt1,$<)
        cp $< $(patsubst %.src,%.tgt2,$<)
        -rm -f final x dep x.tgt1 x.tgt2

(Note: To run this makefile successfully you have to create a file named
"x.src" at first, to cause the pattern rule to be applied.)

This Makefile has some unwanted properties. At first, building "final" does
not result in building "dep", although the dependency chain
"final-->x-->x.tgt2-->dep" exists. Make traverses the dependency tree from
left to right. It finds that x depends on x.tgt1 and that x.tgt1 can only be
built by the pattern rule. However, at build time, this rule also builds
x.tgt2. So x.tgt2's non-existent dependencies are ignored as it already

If you reverse the order of x's prerequisites, you encounter an even stranger
effect. Running make (after a proper "make clean", of course) seems to work.
However, if you use "make -j" you will see that the "dep" target will be
finished long after the "final" target. This is due to the fact that the
dependency x.tgt2-->dep is not properly tracked across the pattern rule.

Additionally, in both cases (Makefile with original order of x's
prerequisites and Makefile with reversed order and using "make -j"), one has
to run make a second time until everything is built.

I don't know whether this behaviour is by design. But I think that pattern
rules with multiple (pattern) targets must only be run if make determines
that all dependencies for *all* the targets the pattern rule would create are
already in place. Currently, make seems to perform the dependency check only
for that target that triggers the rule. This is not enough IMHO. In the
example above, make should be running the pattern rule only after the
dependencies of both x.tgt1 *and* x.tgt2 have been built successfully. This
would also help to get rid of the "reordering changes semantics" effect
described above.

The background: The real case was a system where the compiler (MSVC++) also
creates a precompiled header file for a special dummy source file. To account
for the fact that compiling all "normal" source files needs this precompiled
headers I built a pattern rule like the following one (the pattern rule was
necessary in order to tell "make" that the command build both files

OBJS := library-pchgen.obj <further library objects>
$(OBJS): library-pchgen.obj

%.pch %-pchgen.obj: %-pchgen.src
  <compiler call to compile the pchgen and pch files>

$(TARGET): $(OBJS) library.pch
  <linker call>

Because there were dependencies on other libraries, all the object files had
additional prerequisites:

$(OBJS): other_lib/other_lib.dll another_lib/another_lib.dll

However, this did not work when using "make -j", as library-pchgen.obj was
built before the other libraries were built. Stating explicitly that the pch
file (library.pch) also depends on the other libraries via:

$(OBJS) library.pch: other_lib/other_lib.dll another_lib/another_lib.dll

solved the problem, but - as I already said - I don't think this should be

  Christoph Schulz


File Attachments:

Date: Dienstag 20.02.2007 um 14:45  Name: Makefile  Size: 290B   By:


Reply to this item at:


  Nachricht geschickt von/durch Savannah

reply via email to

[Prev in Thread] Current Thread [Next in Thread]