Subject: bug#12142: automake tries to compile a program when 'foo' and 'foo.cxx' exist (though the former is header)

From: Nick Bowler <[email-masked]>
Date: Tue, 14 Aug 2012 16:21:13 -0400

On 2012-08-07 18:12 +0200, Stefano Lattarini wrote:
> On 08/06/2012 11:20 AM, Michał Górny wrote:
> > On Mon, 06 Aug 2012 09:38:08 +0200
> > Stefano Lattarini <[email-masked]> wrote:
> > 
> >> On 08/05/2012 11:45 AM, Michał Górny wrote:
[...]
> >>> My library was structured like the following:
> >>>
> >>> - src/foo (the header file),
[...]
> >>> - src/foo.cxx (the code).
> >>>
> >>> These files assemble a library, let's call it libfoo.la.
> >>>
> >>> The problem is that every time I modify src/foo.cxx and call 'make',
> >>> automake
> >>>
> >> No, automake is doing nothing at this point.  It's make that does the
> >> building and compiling, using both the instructions given in the
> >> Automake-generated Makefile and its own built-in rules.  And it's one
> >> the latter that is wreaking havoc here.
> >>
> >>  first (correctly) compiles the library, and then mistakenly
> >>> tries to compile and link it into a program src/foo, either
> >>> effectively overwriting or removing my header file, or failing
> >>> early due to missing dependency file.
> >>>
> >> I guess this doesn't happen if you run make with the
> >> '--no-builtin-rules' option.  And in fact ...
> > 
> > You are right indeed. However, AFAICS it's not exactly that simple.
> > Automake-generated Makefile first clears the default suffix list, then
> > explicitly adds new suffixes. Is there a reason for that?
> >
> Portability to some vendor make I believe.
> 
> > Just removing the second '.SUFFIXES: ...' line helps indeed.
> >
> But that will cause the '.cxx.o' suffix rule to stop working with
> some make implementations.  That's not something I prepared to
> risk lightly.

The original test case URL no longer seems to be valid, so I can only
guess what's actually happening at this point (please, reporters, attach
test cases or post them inline to avoid link rot!)

>From the discussion, it sounds to me like the problem is GNU make's
built-in rule to link a binary from a single .o file, together with
Automake's .cxx.o suffix rule, so you end up with the implicit rule
chain

  foo.cxx -> foo.o -> foo

Moreover, because some source file presumably #includes foo, Automake's
automatic dependency tracking (or an explicit prerequisite in the Makefile)
is causing make to try and update foo.  Make sees that foo.cxx is newer
than foo, so it carries out the rules to update foo.

Fortunately, the workaround is simple in this case.  All you need to do
is add an explicit rule for foo, and implicit rule search will not be
performed.  Just putting

  foo: ;

in Makefile.am (which says that foo has no prerequisites and can be
updated by doing nothing) should fix it right up, without relying on
any GNU-make-specific features.

Cheers,
-- 
Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/)