[Cook] include-cooked-warning

Peter Miller millerp at canb.auug.org.au
Wed Apr 24 22:41:58 EST 2002


Mihai Preda <Mihai.Preda at xyleme.com> writes:
> I have read many times the small paragraph from the Cook User Guide
> "Dependencies on Derived Files" (section 5.6, page 15).
> 
> In that paragraph is explained the reason for a warning like this:
> 
> cook: warning: the ``boo: foo.h;'' recipe only appears in the derived
>	"lex.c.d" file
> cook: If the relationship between a target and a derived ingredient
>	appears only in a derived cookbook, it is likely that a clean
>	build (solely from primary source files) will fail.  It is
>	recommended that relationships such as this be placed in a
>	primary source cookbook.


> Yet I fail to understand what is the problem: Why (how?) could a clean
> build fail in such a situation? 

Say you had a small calculateor project with 3 files: main.c, lex.c
and gram.y.  You build gram.gen.c and gram.gen.h from gram.y (normal
yacc grammar usage).  Also lex.c includes gram.gen.h, so it knows the
token numbers to pass to the parser.

Cook does not initially know *any* include dependencies, so there are
12 build orders Cook *thinks* could be valid, and one of them will be
chosen essentially at random (according to the information Cook has,
they are all valid, so which one doesn't matter).

A: cc -c main.c, then cc -c lex.c, then yacc gram.y, then cc -c gram.gen.c
B: cc -c main.c, then yacc gram.y, then cc -c lex.c, then cc -c gram.gen.c
C: yacc gram.y, then cc -c main.c, then cc -c lex.c, then cc -c gram.gen.c
D: cc -c main.c, then yacc gram.y, then cc -c gram.gen.c, then cc -c lex.c
E: yacc gram.y, then cc -c main.c, then cc -c gram.gen.c, then cc -c lex.c
F: cc -c lex.c, then cc -c main.c, then yacc gram.y, then cc -c gram.gen.c
G: cc -c lex.c, then yacc gram.y, then cc -c main.c, then cc -c gram.gen.c
H: yacc gram.y, then cc -c lex.c, then cc -c main.c, then cc -c gram.gen.c
I: cc -c lex.c, then yacc gram.y, then cc -c gram.gen.c, then cc -c main.c
J: yacc gram.y, then cc -c lex.c, then cc -c gram.gen.c, then cc -c main.c
K: yacc gram.y, then cc -c gram.gen.c, then cc -c lex.c, then cc -c main.c
L: yacc gram.y, then cc -c gram.gen.c, then cc -c main.c, then cc -c lex.c

You will notice that only 8 of the 12 (B,C,D,E,H,J,K,L) will work.
The use of .d files improves things, but not perfectly.

If you generate .d files from .c files, there are 12 orders Cook could
use to build the include depenencies.

A: c_incl main.c, then c_incl lex.c, then yacc gram.y, then c_incl gram.gen.c
B: c_incl main.c, then yacc gram.y, then c_incl lex.c, then c_incl gram.gen.c
C: yacc gram.y, then c_incl main.c, then c_incl lex.c, then c_incl gram.gen.c
D: c_incl main.c, then yacc gram.y, then c_incl gram.gen.c, then c_incl lex.c
E: yacc gram.y, then c_incl main.c, then c_incl gram.gen.c, then c_incl lex.c
F: c_incl lex.c, then c_incl main.c, then yacc gram.y, then c_incl gram.gen.c
G: c_incl lex.c, then yacc gram.y, then c_incl main.c, then c_incl gram.gen.c
H: yacc gram.y, then c_incl lex.c, then c_incl main.c, then c_incl gram.gen.c
I: c_incl lex.c, then yacc gram.y, then c_incl gram.gen.c, then c_incl main.c
J: yacc gram.y, then c_incl lex.c, then c_incl gram.gen.c, then c_incl main.c
K: yacc gram.y, then c_incl gram.gen.c, then c_incl lex.c, then c_incl main.c
L: yacc gram.y, then c_incl gram.gen.c, then c_incl main.c, then c_incl lex.c

Note that only 8 of the 12 alternatives run yacc gram.y before c_incl
lex.c is run.  In these cases c_incl will find the gram.gen.h file and
list it as an include dependency.  In the other 4 cases, the gram.gen.h
file will not be there for a >>clean<< build, and c_incl *wont* find it.

(This is only a little example, and it's "obvious" that gram.gen.h is to
be generated in the current directory.  But think of larger projects, with
long lists of -I options: the generated file could be in any one of
those -I directories, and c_incl can't possibly work out which one,
so it either errors or ignores (depends on command line options) files
it can't find.)

All of this discussion leads to the error message:

cook: warning: the ``lex.o: gram.gen.h;'' recipe only appears in the derived
	"lex.c.d" file
cook: If the relationship between a target and a derived ingredient
	appears only in a derived cookbook, it is likely that a clean
	build (solely from primary source files) will fail.  It is
	recommended that relationships such as this be placed in a
	primary source cookbook.

That "appears only in a derived cookbook" phrase means it's only in the
derived lex.c.d file... a file which is transient... a file which is *not*
*there* for a clean build.  Oops.

The fix is to explicitly say

	cascade lex.c = gram.gen.h;

in the main Cookbook, which gives Cook enough information to discard
the 4 inappropriate alternatives when building the .d files.

Regards
Peter Miller   E-Mail: millerp at canb.auug.org.au
/\/\*          WWW:    http://www.canb.auug.org.au/~millerp/
Disclaimer:  The views expressed here are personal and do not necessarily
        reflect the view of my employer or the views of my colleagues.



More information about the Cook-users mailing list