tech-toolchain archive

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

Re: make: avoid breaking backwards compatability



On Wed, Sep 03, 2014 at 08:50:44PM +0300, Jarmo Jaakkola wrote:
 > > The other case I hit was where SRCS contains sub/file.c 
 > > sometimes adding the dir where sub/file.c lives to .PATH isn't an option
 > > because of other files present that are not the desired ones.
 > > 
 > > Until recently
 > > 
 > > foo.o: subdir/foo.c
 > > 
 > > worked, but now even after subdir/foo.c has been correctly found
 > > a search for foo.c is made and overrides the previous result - which can
 > > cause the wrong foo.c to be compiled.
 > > Sometimes this can all be sorted out by tweaking .PATH, but again only
 > > if you have access to the makefile that needs fixing.
 > 
 > No, this works exactly as suffix rules should work, in my opinion.  The
 > problem here is not that subdir/foo.c is overridden, it is that you're
 > expecting some random extra dependency to become the implied source in
 > a suffix rule.

I think you misunderstand the way .PATH and pattern rule searches are
supposed to work.

If I write a .c.o rule, and ask for a .o file, make is supposed to
find the corresponding .c file in some directory. So if I'm trying to
build foo.o, it's looking for foo.c. If "subdir/foo.c" is already on
the list of sources, that's not some random extra dependency; that's
the file named foo.c that it's looking for. So it's found it and it
doesn't need to search any further.

If there's more than one foo.c in the sources list, it takes the
first, the same as if there's more than one foo.c on .PATH. And it
does this before it searches .PATH at all, including the current
directory, as one would expect.

Or at least that's what it did before these changes. Now it seems to
be broken.

 > Because that is what you've written: you're asking make
 > to use suffix rules to make foo.o and merely told that the object file
 > also happens to depend on some other C file too.  This is no different
 > from "foo.o: subdir/bar.c" and nobody would expect subdir/bar.c to
 > become the implied source in that case.  In your example subdir/foo.c
 > just would be eligible to become the implied source with a proper value
 > of .PATH, but the fact that it is an explicit dependency would not have
 > any effect even in that case.

This is just wrong...

 > I do understand that before my changes the extra dependencies used
 > to affect the implied source selection for suffix rules.  This, however,
 > is IMO completely wrong and was listed in PR 49086 as issue 10.

Ok, now I at least see where this is coming from, even though issue 10
appears to be unrelated.

However, your analysis is incorrect for the same reason as described
above.

 > Let me turn the tables on your example.  Let us assume that make allows
 > the explicitly listed dependencies to become the implied source, instead
 > of the one found by regular suffix rule search.  Let us also assume that
 > the file subdir/foo.c contains something that is included by foo.c, so
 > foo.o naturally depends on it.  How will I then write the Makefile?
 > Exactly like you did, of course:
 > 
 >     foo.o: subdir/foo.c
 > 
 > Running make would compile foo.o from subdir/foo.c, which is obviously
 > incorrect and completely unexpected, because foo.c exists.  Therefore,
 > the extra dependencies should not affect the suffix rule selection.
 > (I'd like to add that the overriding behavior was not documented in any
 > way, I only found out about it after I read the source)

No, this is exactly what it used to do before it got broken, and this
is exactly what the makefile asked for. If you write

   foo.o: foo.c subdir/foo.c

it builds foo.o from foo.c; if you write

   foo.o: subdir/foo.c foo.c

it builds foo.o from subdir/foo.c. Even if one of the source files
includes the other, you will get the right result unless you
deliberately do something silly.

 > Now here is what I would do instead now that make makes $(<) be
 > the first dependency in explicit rules (assuming you cannot rename
 > either foo.c or subdir/foo.c):
 > 
 >     foo.o: subdir/foo.c
 >         $(CC) -o $(@) $(<)
 > 
 > Or if you have multiple files and assuming that .o is a known suffix:
 > 
 >     $(SRCS): subdir/$(*).c
 >         $(CC) -o $(@) $(<)

...basically you're saying that pattern rules no longer work for these
cases.

Note that I've been saying for years that .PATH and pattern rules for
non-local files are bad and that makefiles shouldn't be written in
this style; but that doesn't mean the feature should be arbitrarily
lobotomized.

This portion of the recent changes needs to be reverted.

-- 
David A. Holland
dholland%netbsd.org@localhost


Home | Main Index | Thread Index | Old Index