bug-make
[Top][All Lists]
Advanced

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

Re: Quirk with rules producing multiple output files


From: Paul Smith
Subject: Re: Quirk with rules producing multiple output files
Date: Sun, 28 Apr 2013 02:16:27 -0400

On Fri, 2013-04-12 at 13:41 +0200, Reinier Post wrote:
> Hmm, indeed:
> 
> | /tmp % cat Makefile
> | %.1:; echo $*.1 for $@ > $@
> | %.e.1 %.f.1:; echo $*.1 for $@ > $@
> | %.c.1 %.d.1:; for f in $*.c.1 $*.d.1; do echo $$f for $@ > $$f; done
> | %.ab.2: %.a.1 %.b.1; cat $+ > $@
> | %.cd.2: %.c.1 %.d.1; cat $+ > $@
> | %.ef.2: %.e.1 %.f.1; cat $+ > $@
> | /tmp % make -rR stage.ab.2 stage.cd.2 stage.ef.2
> | echo stage.a.1 for stage.a.1 > stage.a.1
> | echo stage.b.1 for stage.b.1 > stage.b.1
> | cat stage.a.1 stage.b.1 > stage.ab.2
> | for f in stage.c.1 stage.d.1; do echo $f for stage.d.1 > $f; done
> | cat stage.c.1 stage.d.1 > stage.cd.2
> | echo stage.1 for stage.f.1 > stage.f.1
> | cat stage.e.1 stage.f.1 > stage.ef.2
> | cat: stage.e.1: No such file or directory
> | make: *** [stage.ef.2] Error 1
> | rm stage.a.1 stage.b.1 stage.c.1
> | /tmp % 

It would be faster/easier for me to read and respond if you stripped out
the non-essential parts.  The interesting make line is:

> %.e.1 %.f.1:; echo $*.1 for $@ > $@

And the error:

> > | echo stage.1 for stage.f.1 > stage.f.1
> > | cat: stage.e.1: No such file or directory
> > | make: *** [stage.ef.2] Error 1

> I didn't realise make would skip the creation of stage.e.1;
> yet this is documented very clearly:
> 
>   http://www.gnu.org/software/make/manual/html_node/Pattern-Intro.html
> 
> I thought this was just describing an optimization;
> I didn't realize it would actually affect the build process.

It's not an optimization: it's a fundamental difference in what rules
with multiple targets mean.  Explicit rules with multiple targets are
treated as if you'd defined the same rule once per target for that
target.  That is, this rule:

  foo bar : ; touch $@

is absolutely identical to this:

  foo : ; touch $@
  bar : ; touch $@ 

Pattern rules with multiple targets means that a single invocation of
the recipe will create all the targets.  That means for this rule:

  %.f %.b : ; ...recipe...

make will expect ...recipe... to build BOTH the two targets when it is
run ONE time.

> Why does it work this way?  What is a possible use case?

There are a large number of situations where a single invocation of a
rule builds multiple output files.  Consider the yacc (bison) tool for
example, where it outputs both a C source and header file.

> In any case, it may be useful to also be able to state that
> a multi-target pattern rule only makes its actual target.

Yes, just as being able to specify multiple targets from a single
invocation of an explicit rule would be useful, so might be being able
to specify multiple pattern rules in a single statement.




reply via email to

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