.\"
.\"     cook - file construction tool
.\"     Copyright (C) 1993-1995, 1997, 1998, 2000-2002, 2007, 2008 Peter Miller
.\"
.\"     This program is free software; you can redistribute it and/or modify
.\"     it under the terms of the GNU General Public License as published by
.\"     the Free Software Foundation; either version 3 of the License, or
.\"     (at your option) any later version.
.\"
.\"     This program is distributed in the hope that it will be useful,
.\"     but WITHOUT ANY WARRANTY; without even the implied warranty of
.\"     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
.\"     GNU General Public License for more details.
.\"
.\"     You should have received a copy of the GNU General Public License
.\"     along with this program. If not, see
.\"     <http://www.gnu.org/licenses/>.
.\"
.H 1 "Actions when Cooking"
This section describes what
.B cook
does when you ask it to cook something.
.P
.B Cook
performs the following actions in the order stated.
.H 2 "Scan the COOK Environment Variable"
The
.B COOK
environment variable is looked for.
If it is found,
it is treated as if it consisted of
.B cook
command line arguments.
Only the
.B -Help
option is illegal.
This could result is very strange behavior if used incorrectly.
.P
This feature is supplied to override
.BR cook 's
default with your own preferences.
.H 2 "Scan the Command Line"
The command line is scanned
as defined in chapter 3.
.H 2 "Locate the Cookbook"
The current directory is scanned for the cookbook.
Names which a cookbook may have include
.TS
center, tab(;);
c c c.
howto.cook;Howto.cook;.howto.cook
how.to.cook;How.to.cook;.how.to.cook
cookfile;Cookfile;.cookrc
cook.file;Cook.file;.cook.rc
.TE
The first so named file found in the current directory
will be used.
The order of search is not defined.
You are strongly advised to have just
.I one
of these name forms in any directory.
The name
.I Howto.cook
is the preferred form.
.H 2 "Form the Listing Filename"
The listing file,
if not explicitly named in the environment variable or on the command line,
will be the name of the cookbook,
with any suffix removed and '\f(CW.list\fP' appended.
.H 2 "Create the Listing file"
The listing file is created.
If
.B cook
is executing in the background,
or the
.B -NoTTy
option has been specified,
.I stdout
and
.I stderr
will be redirected into the listing file.
If
.B cook
is executing in the foreground,
and the
.B -NoTTy
option has not been specified,
.I stdout
and
.I stderr
will be redirected into
a pipe to a
.IR tee (1)
command;
which will, in turn, copy the output into the named file.
.P
A heading line with the name of the file and the date,
is generated.
.H 2 "Scan the Cookbook"
When
.B cook
reads the cookbook it evaluates all of the statements it
finds in it.
Usually these statements instantiate recipes,
although other things are possible.
.P
Recipes contain statements that are not evaluated immediately,
but which are remembered for later execution when cooking a target.
The meaning of a cookbook is defined in chapter X.
.H 2 "Determine targets to cook"
If no target files are named on the command line,
the targets of the first defined explicit or ingredients recipe.
It is an error if this is none.
.H 2 "Cooking a Target"
A derivation graph is formed using all of the targets given.  Once the
derivation graph is formed, it will be walked, looking for files which
are out of date.
.P
To build the derivation graph for a target,
each the following steps is performed in the order given:
.AL
.LI
.B Cook
exploits knowledge of the derivation graph that the user may provide to it:
.BL
.LI
If the \fIgraph_exterior_file\fP variable is set, and the file name is
listed in it, the file is not a leaf, and the derivation will backtrack
and try another alternative.
.LI
If the \fIgraph_exterior_pattern\fP variable is set, and the file name
matches one of the patterns listed in it, the file is not a leaf, and
the derivation will backtrack and try another alternative.
.LI
If the \fIgraph_leaf_file\fP variable is set, and the file name is
listed in it, the file is a leaf file of the derivation.  There is no
need to attempt to apply any recipes.  It will be an error if the file
does not exist.
.LI
If the \fIgraph_leaf_pattern\fP variable is set, and the file name
matches one of the patterns listed in it, the file is a leaf file of
the derivation.  There is no need to attempt to apply any recipes.
It will be an error if the file does not exist.
.LE
These optimizations require an accurate source file manifest,
but can result is substantial performance improvements.
.LI
.B Cook
scans through the instantiated ingredients recipes
in the order they were defined.
All ingredients recipes with the target in their target list are used.
.P
If a recipe is used,
then any ingredients also have their derivation graph constructed.
When walking the graph,
if any of the ingredients are younger than the target,
all other explicit or implicit recipes with the same target will
be deemed to be out of date.\*F
.FS
A target which does not exist yet is considered to be infinitely ancient,
and thus everything is younger than it.
.FE
.LI
.B Cook
then scans through the instantiated explicit recipes
in the order they were defined.
All explicit recipes with the target in their target list are used.
.P
If a recipe is a used,
the ingredients also have their derivation graph constructed.
When walking the graph,
if any ingredients are out of date
or the target does not yet exist
(or the "forced" flag is set in the recipe's \fIset\fP clause)
the recipe body will be performed.
If a recipe has no ingredients,
it will not be performed,
unless the target does not yet exist, or it is forced.
.LI
If the target was not in the target list of any explicit recipe,
.B cook
then scans the instantiated implicit recipes in the order they were
defined, in two passes.  Implicit recipes which not not have pattern
elements in the basename of the targets are scanned before implicit
recipes which do have patterns in the basename.  Usually this has
no significant effect, however in heavily heterogeneous builds this
method is often used in constructing the dependency files, so that all
architectures may use the one implicit dependency recipe, rather than
stating every architecture explicitly.  Within each pass, the order of
scan is the order of definition.
.P
Implicit recipe targets and ingredients may contain a wildcard
character (\fB%\fP),
which is why they are implicit.
When expressions are evaluated into word lists in an implicit recipe,
any word containing the wildcard character (\fB%\fP) will be expanded
out by the current wildcard expansion.
.P
If the target matches a pattern in the targets of an implicit recipe,
it is a candidate.
Each ingredient of a candidate recipe is recursively cooked.
If any ingredient cannot be cooked,
then the implicit recipe is not used.
If all ingredients can be cooked,
then the implicit recipe is used.
.P
If an implicit recipe is a used,
the forced ingredients also have their derivation graph constructed.
It is an error if a forced ingredient cannot be constructed.
.P
Only the first implicit recipe to get to this point is used.
The scan stops at this point.
.LI
If the target is not the subject of any ingredients or explicit recipe,
and no implicit recipes can be applied, then several derivations are
attempted, in the order specified:
.BL
.LI
If the \fIgraph_interior_file\fP variable is set, and the file name is
listed in it, the file is a not leaf file of the derivation.  Cook will
backtrack and try another alternative.
.LI
If the \fIgraph_interior_pattern\fP variable is set, and the file name
matches one of the patterns listed in it, the file is a not leaf file
of the derivation.  Cook will backtrack and try another alternative.
.LI
If the \fIgraph_leaf_file\fP variable is set, and the file name is
listed in it, the file is a leaf file of the derivation.  It will be an
error if the file does not exist.
.LI
If the \fIgraph_leaf_pattern\fP variable is set, and the file name
matches one of the patterns listed in it, the file is a leaf file of
the derivation.  It will be an error if the file does not exist.
.LI
If either of the \fIgraph_leaf_file\fP or \fIgraph_leaf_pattern\fP
variables are set, then the file is not a leaf, and the derivation will
backtrack and try another alternative.
.LI
If the file exists, then it is up to date, and the file is a leaf file
of the derivation.
.LI
If the file does not exist then \fBCook\fP doesn't know how, and the
derivation will backtrack and try another alternative.
.LE
.LE
.P
If a command in the body of any recipe fail,
.B cook
will not that body any further,
and will not perform the body of any recipe for which the target
of the failed actions was an ingredient,
directly or indirectly.
.P
.B Cook
will trap recursive looping of targets.
.BL
.LI
If the file exists, the it is up to date, or
.LI
If the file does not exist then
.B cook
doesn't know how.
.LE
.H 2 "The Dependency Graph"
The above section describes how Cook derives the dependency graph.
Once the dependency graph has been derived, it is then walked.
The next section describes a little about how Cook walks the dependency graph.
.P
Cook is a simple kind of expert system.  You give it a set of of recipes
for how to construct things, and a target to be constructed.  The
recipes can be decomposed into pair-wise ordered dependencies between
files.
.P
Cook determines how to build the target by constructing a \fIdirected
acyclic graph\fP.  The vertexes of this graph are the files in the
system, the edges in this graph are the inter-file dependencies.  The
edges of the graph are directed because the pair-wise dependencies are
ordered resulting in a \fIacyclic\fP graph \- things which look like
loops are resolved by the direction of the edges.
.P
For example, if you have a simple cookbook (with the recipe bodies
omitted for simplicity) like this:
.eB
program: one.o two.o;
one.o: one.c one.h;
two.o: two.c two.h one.h;
.eE
here is the corresponding directed acyclic graph.
.PS
E1: ellipse "one.c"
E2: ellipse "one.h" with .w at E1.e+(0.25,0)
E3: ellipse "two.c" with .w at E2.e+(0.25,0)
E4: ellipse "two.h" with .w at E3.e+(0.25,0)
E5: ellipse "one.o" with .s at 1/2<E1.n,E2.n>+(0,0.25)
E6: ellipse "two.o" with .s at 1/2<E3.n,E4.n>+(0,0.25)
E7: ellipse "program" with .s at 1/2<E5.n,E6.n>+(0,0.25)
arrow from E1.n to E5.sw
arrow from E2.n to E5.se
arrow from E3.n to E6.sw
arrow from E4.n to E6.se
arrow from E5.n to E7.sw
arrow from E6.n to E7.se
arrow from E2.ne to E6.w
.PE
.P
There are several things that can be done with the graph once it has
been derived:
.br
.if n *
.if t \(bu
It can be walked to verify and regenerate the referential integrity of
the files (the usual case), or
.br
.if n *
.if t \(bu
it can walked to print the pair-wise dependencies (the \f[CW]-pairs\fP
option), or
.br
.if n *
.if t \(bu
it can be walked to generate a shell script
(the \f[CW]-script\fP option)
which does something very similar to the first option.
.H 3 "Edge Types"
Each of the arrows in the above graph have a specific type.
.VL 0.6i
.LI \fIstrict\fP
edges mean that Cook will decide that a target is out-of-date if its
time stamp is not strictly younger than all of the ingredients.  This is
almost always what you want.
.LI \fIweak\fP
edges mean that Cook will decide that a target is out-of-date if its
time stamp is older than any of the ingredients.  This means that the
times stamps of the target and ingredients may be equal - this is useful
for hard links and symbolic links.
You specify edges of this type by appending the ``\f[CW](weak)\fP''
string to the name of the ingredient.
.LI \fIexists\fP
edges mean that Cook will arrange for the ingredient to be cooked
before the recipe is run, but the time stamp \fIis not consulted\fP.
The ingredient cannot ever make the target out-of-date.  This is useful
form coping with version stamps which change often, but you don't want
to re-link unless something else changes.
You specify edges of this type by appending the ``\f[CW](exists)\fP''
string to the name of the ingredient.
.LE
The default edge type is ``\fIstrict\fP''.
You can use the "time-adjust" setting (see the "set" command)
to make this simpler on very fast machines.
.H 2 "File Status"
.B Cook
determines the time a file was last modified by asking the operating system.
Because this operation tends to be performed frequently,
.B cook
maintains a cache of this information,
rather than make redundant calls to the operating system.
Because this information is cached,
it is possible for
.BR cook "'s"
memory of a file's last-modified time
to become inconsistent with the file's actual last-modified time.
In particular,
.B cook
doe \fInot\fP ask the operating system for the "new" last-modified time
of a recipe target once a recipe body is completed.
Careful use of the \f(CWset clearstat\fP clause
will generally prevent this.
For example,
the following recipe needs to create a directory
when writing its output:
.eB
bin/%: [%_obj]
{
        if [not [exists bin]] then
                mkdir bin;
        [cc] -o [target] [need];
}
.eE
If there were several programs being cooked,
e.g. \fIbin/foo\fP and \fIbin/bar\fP,
the second time \fBcook\fP performed the recipe,
it would erroneously attempt to make the \fIbin\fP directory
a second time - contrary to the test.
This is because \fI[exists bin]\fP used the cache,
and nothing tells \fBcook\fP that the cache is now wrong.
The recipe should have been written
.eB
bin/%: [%_obj]
{
        if [not [exists bin]] then
                mkdir bin
                        set clearstat;
        [cc] -o [target] [need];
}
.eE
which tells \fBcook\fP that it should remove any files
named in the \fImkdir\fP command from the cache.
.P
An alternative way of performing the above example
is to set the \fImkdir\fP recipe flag:
.eB
bin/%: [%_obj]
        set mkdir
{
        [cc] -o [target] [need];
}
.eE
This flag instructs \fBcook\fP to create the directory for the target
before running the
recipe body.
There is a similar \fIunlink\fP flag, which unlinks the targets of the recipe
before running the recipe body.
These two flags take care of most, but not all,
uses of the \fIclearstat\fP flag.
.P
A second mechanism used by
.B cook
to determine the last-modified times of files is
a file
.IR fingerprint .
This is a cryptographically strong hash of the contents of a file.
The chances of two different files having the same fingerprint
is less than 1 in 2**200.
If \fBcook\fP notices that a file has changed,
because its last-modified time has changed,
a fingerprint is taken of the file
and compared with the remembered fingerprint.
If the fingerprints differ,
the file is considered to be different.
If the fingerprints match,
the file is considered not to have changed.
.P
This description of fingerprints is somewhat simplified,
the actual mechanics depends on remembering two
different last-modified times,
as well as the fingerprint,
in a file called
.I \&.cook.fp
in the current directory.
.P
Fingerprinting can cause some surprises.
For example,
when you use the
.IR touch (1)
command,
.B cook
will often fail to do anything,
and report instead that everything is up-to-date.
This is because the fingerprint has not changed.
In this situation,
either remove the
.I \&.cook.fp
file,
or use the
.B -No_FingerPrint
command line option.