2 <TITLE>Jam - Make(
1) Redux
</TITLE>
5 <H1>Jam - Make(
1) Redux
</H1>
6 <P>The
<a href=
"http://gitorious.org/projects/kjam">K8Jam
</a> Executable
<BR>
7 Based on Perforce
<a href=
"http://www.perforce.com/jam/jam.html">Jam
</a>
12 <DT><P><H2>USAGE
</H2><DD>
14 jam [ -a ] [ -g ] [ -n ] [ -q ] [ -v ]
18 [ -o
<I>actionsfile
</I> ]
19 [ -s
<I>var
</I>=
<I>value
</I> ]
24 <DT><P><H2>DESCRIPTION
</H2><DD>
25 <P><B>Jam
</B> is a program construction tool, like
<B>make
</B>(
1).
</P>
26 <P><B>Jam
</B> recursively builds target files from source files,
27 using dependency information and updating actions expressed in
28 the Jambase file, which is written in
<B>jam
</B>'s own interpreted
29 language. The default Jambase is compiled into
<B>jam
</B> and
30 provides a boilerplate for common use, relying on a user-provide
31 file
"Jamfile" to enumerate actual targets and sources.
</P>
32 <P>The Jambase is described in the
<a href=
"Jambase.html">Jambase
33 Reference
</a> and the document
<a href=
"Jamfile.html">Using
34 Jamfiles and Jambase
</A>.
</P>
36 <DT><P><H2>OPTIONS
</H2><DD>
37 <P>If
<I>target
</I> is provided on the command line,
<B>jam
</B>
38 builds
<I>target;
</I> otherwise
<B>jam
</B> builds the target
41 <P><B>Jam
</b> may be invoked with the following options:
</P>
42 <P><TABLE WIDTH=
"85%" ALIGN=
"CENTER" BORDER=
"1" CELLPADDING=
"2">
43 <TR><TD VALIGN=
"TOP" WIDTH=
"20%"><CODE>-a
</CODE></TD>
44 <TD>Build all targets anyway, even if they are up-to-date.
</TD></TR>
46 <TR><TD VALIGN=
"TOP"><CODE>-d
<I>c
</I></CODE></TD>
47 <TD>Turn on display option
<I>c
</I> and off the default
48 display (summary info and actions):
51 <DT>a
<DD> Show summary info, actions, quiet actions, and the
52 use of temporary targets
53 <DT>c
<DD> Show the names of files that cause rebuilds, i.e.
54 new sources, missing targets, etc.
55 <DT>d
<DD> Display a dependency graph (in
<B>jam
</B> syntax).
56 <DT>m
<DD> Display the dependency analysis, and target/source
58 <DT>x
<DD> Show shell arguments
62 <TR><TD VALIGN=
"TOP"><CODE>-d
<I>n
</I></CODE></TD>
63 <TD> Enable cummulative debugging levels from
1 to
<I>n
</I>.
64 Interesting values are:
67 <DT>1<DD> Show actions and summary info (the default)
68 <DT>3<DD> Old name for -dm (described above)
69 <DT>5<DD> Show rule invocations and variable expansions
70 <DT>6<DD> Show directory/header file/archive scans
71 <DT>7<DD> Show variable settings
72 <DT>8<DD> Show variable fetches
73 <DT>9<DD> Show variable manipulation, scanner tokens
77 <TR><TD VALIGN=
"TOP"><CODE>-d +
<I>n
</I> </CODE></TD>
78 <TD>Enable debugging level
<I>n
</I>.
</TD></TR>
80 <TR><TD VALIGN=
"TOP"><CODE>-d
0</CODE></TD>
81 <TD>Turn off all debugging levels. Only errors are emitted.
</TD></TR>
83 <TR><TD VALIGN=
"TOP"><CODE>-f
<I>jambase
</I></CODE></TD>
84 <TD>Read
<I>jambase
</I> instead of using the built-in Jambase.
85 Multiple -f flags are permitted.
</TD></TR>
87 <TR><TD VALIGN=
"TOP"><CODE>-g
</CODE></TD>
88 <TD>Build targets with the newest sources first, rather than
89 in the order of appearance in the Jambase/Jamfiles.
</TD></TR>
91 <TR><TD VALIGN=
"TOP"><CODE>-j
<I>n
</I></CODE></TD>
92 <TD> Run up to
<I>n
</I> shell commands concurrently (UNIX
93 and NT only). The default is
1.
</TD></TR>
95 <TR><TD VALIGN=
"TOP"><CODE>-n
</CODE></TD>
96 <TD>Don't actually execute the updating actions, but do
97 everything else. This changes the debug level to -dax.
</TD></TR>
99 <TR><TD VALIGN=
"TOP"><CODE>-o
<I>file
</I></CODE></TD>
100 <TD>Write the updating actions to the specified file instead
101 of running them (or outputting them, as on the Mac).
</TD></TR>
103 <TR><TD VALIGN=
"TOP"><CODE>-q
</CODE></TD>
104 <TD>Quit quickly (as if an interrupt was received)
105 as soon as any target build fails.
</TD></TR>
107 <TR><TD VALIGN=
"TOP"><CODE>-s
<I>var
</I>=
<I>value
</I></CODE></TD>
108 <TD>Set the variable
<I>var
</I> to
<I>value
</I>, overriding
109 both internal variables and variables imported from the
110 environment.
</TD></TR>
112 <TR><TD VALIGN=
"TOP"><CODE>-t
<I>target
</I></CODE></TD>
113 <TD>Rebuild
<I>target
</I> and everything that depends on it,
114 even if it is up-to-date.
</TD></TR>
116 <TR><TD VALIGN=
"TOP"><CODE>-v
</CODE></TD>
117 <TD>Print the version of
<B>jam
</B> and exit.
</TD></TR>
120 <DT><P><H2>OPERATION
</H2><DD>
121 <P><b>Jam
</b> has four phases of operation: start-up, parsing,
122 binding, and updating.
</P>
124 <DT><P><H3>Start-up
</H3><DD>
125 <P>Upon start-up,
<b>jam
</b> imports environment variable settings
126 into
<b>jam
</b> variables. Environment variables are split at
127 blanks with each word becoming an element in the variable's list
128 of values. Environment variables whose names end in PATH are
129 split at $(SPLITPATH) characters (e.g.,
":" for Unix).
</P>
131 <P>To set a variable's value on the command line, overriding the
132 variable's environment value, use the -s option. If a command
133 line argument includes, but doesn't start with a
"=", it is
134 treated as an implicit
"-s" option. To see variable
135 assignments made during
<b>jam
</b>'s execution, use the -d+
7
138 <DT><P><H3>Parsing
</H3><DD>
139 <P>In the parsing phase,
<b>jam
</b> reads and executes the Jambase
140 file, by default the built-in one. It is written in the
<b>jam
</b>
141 language. See
<a href=
"#language">Language
</a> below. The
142 last action of the Jambase is to read (via the
"include" rule)
143 a user-provided file called
"Jamfile".
</P>
145 <P>Collectively, the purpose of the Jambase and the Jamfile is to
146 name built target and source files, construct the dependency
147 graph among them, and associate build actions with targets.
148 The Jambase defines boilerplate rules and variable assignments,
149 and the Jamfile uses these to specify the actual relationship
150 among the target and source files. See the
151 <a href=
"Jambase.html">Jambase Reference
</a> and the document
152 <a href=
"Jamfile.html">Using Jamfiles and Jambase
</a> for information.
</P>
155 <DT><P><H3>Binding
</H3><DD>
158 After parsing,
<B>jam
</B> recursively descends the dependency
159 graph and binds every file target with a location in the
162 <P><H5>Targets
</H5><DD>
163 Any string value in
<b>jam
</b> can represent a target, and it
164 does so if the DEPENDS or INCLUDES rules make it part of the
165 dependency graph. Build targets are files to be updated. Source
166 targets are the files used in updating build targets. Build
167 targets and source targets are collectively referred to as file
168 targets, and frequently build targets are source targets for
169 other build targets. Pseudotargets are symbols which represent
170 dependencies on other targets, but which are not themselves
171 associated with any real file.
</P>
173 <P>A file target's identifier is generally the file's name, which can
174 be absolutely rooted, relative to the directory of
<b>jam
</b>'s
175 invocation, or simply local (no directory). Most often it is the
176 last case, and the actual file path is bound using the $(SEARCH)
177 and $(LOCATE) special variables. See
178 <A HREF=
"#search">SEARCH and LOCATE Variables
</A> below. A local
179 filename is optionally qualified with
"grist," a string value used
180 to assure uniqueness. A file target with an identifier of the form
181 <I>file(member)
</I> is a library member (usually an ar(
1) archive
184 <P>The use of $(SEARCH) and $(LOCATE) allows
<b>jam
</b> to separate
185 the the location of files from their names, so that Jamfiles can
186 refer to files locally (i.e. relative to the Jamfile's directory),
187 yet still be usable when
<b>jam
</b> is invoked from a distant
188 directory. The use of grist allows files with the same name
189 to be identified uniquely, so that
<b>jam
</b> can read a whole
190 directory tree of Jamfiles and not mix up same-named targets.
</P>
192 <P><H5>Update Determination
</H5>
193 After binding each target,
<B>jam
</B> determines whether the
194 target needs updating, and if so marks the target for the updating
195 phase. A target is normally so marked if it is missing, it is
196 older than any of its sources, or any of its sources are marked
197 for updating. This behavior can be modified by the application
198 of special built-in rules. See
199 <A HREF=
"#bindingmods">Modifying Binding
</A> below.
</P>
201 <P><H5>Header File Scanning
</H5>
202 During the binding phase,
<b>jam
</b> also performs header file
203 scanning, where it looks inside source files for the implicit
204 dependencies on other files caused by C's #include syntax. This
205 is controlled by the special variables $(HDRSCAN) and $(HDRRULE).
206 The result of the scan is formed into a rule invocation, with
207 the scanned file as the target and the found included file names
208 as the sources. Note that this is the only case where rules
209 are invoked outside the parsing phase. See
210 <A HREF=
"#hdrscan">HDRSCAN and HDRRULE Variables
</A> below.
</P>
212 <DT><P><H3>Updating
</H3><DD>
213 <P>After binding,
<B>jam
</B> again recursively descends the dependency
214 graph, this time executing the update actions for each target
215 marked for update during the binding phase. If a target's
216 updating actions fail, then all other targets which depend on
217 that target are skipped.
</P>
219 <P>The -j flag instructs
<B>jam
</B> to build more than one target
220 at a time. If there are multiple actions on a single target,
221 they are run sequentially. The -g flag reorders builds so that
222 targets with newest sources are built first. Normally, they are
223 built in the order of appearance in the Jamfiles.
</P>
226 <DT><P><H2>LANGUAGE
</H2><DD>
228 <DT><P><H3>Overview
</H3><DD>
229 <B>Jam
</b> has a interpreted, procedural language with a few
230 select features to effect program construction. Statements in
231 <b>jam
</b> are rule (procedure) definitions, rule invocations,
232 updating action definitions, flow-of-control structures, variable
233 assignments, and sundry language support.
</P>
235 <DT><P><H3>Lexical Features
</H3></P><DD>
236 <P><B>Jam
</b> treats its input files as whitespace-separated tokens,
237 with two exceptions: double quotes (
") can enclose whitespace to
238 embed it into a token, and everything between the matching curly
239 braces ({}) in the definition of a updating actions is treated
240 as a single string. A backslash (\) can escape a double quote,
241 or any single whitespace character.</P>
243 <P><B>Jam</b> requires whitespace (blanks, tabs, or newlines) to
244 surround all tokens, <b>including the colon (:) and semicolon
247 <P><B>Jam</b> keywords (as mentioned in this document) are reserved
248 and generally must be quoted with double quotes (") to be used
249 as arbitrary tokens, such as variable or target names.
</P>
251 <DT><P><H3>Datatype
</H3></P><DD>
252 <P><B>Jam
</B>'s only data type is a one-dimensional list of arbitrary
253 strings. They arise as literal (whitespace-separated) tokens in
254 the Jambase or included files, as the result of variable expansion
255 of those tokens, or as the return value from a rule invocation.
</P>
257 <DT><P><H3>Rules
</H3></P><DD>
258 <P>The basic
<B>jam
</b> language entity is called a rule. A rule
259 is simply a procedure definition, with a body of
<b>jam
</b>
260 statements to be run when the rule is invoked. The syntax of
261 rule invocation make it possible to write Jamfiles that look
262 a bit like Makefiles.
</P>
264 <P>Rules take up to
9 arguments ($(
1) through $(
9), each a list)
265 and can have a return value (a single list). A rule's return
266 value can be expanded in a list by enclosing the rule invocation
267 with
<tt>[
</tt> and
<tt>]
</tt>.
</P>
269 <DT><P><H3>Updating Actions
</H3></P><DD>
270 <P>A rule may have updating actions associated with it, in which
271 case arguments $(
1) and $(
2) are treated as built targets and
272 sources, respectively. Updating actions are the OS shell commands
273 to execute when updating the built targets of the rule.
</P>
275 <P>When an rule with updating actions is invoked, those actions are
276 added to those associated with its built targets ($(
1)) before
277 the rule's procedure is run. Later, to build the targets in the
278 updating phase, the actions are passed to the OS command shell,
279 with $(
1) and $(
2) replaced by bound versions of the target names.
280 See
<A HREF=
"#binding">Binding
</A> above.
</P>
282 <DT><P><H3>Statements
</H3></P><DD>
283 <P><b>Jam
</b>'s langauge has the following statements:
</P>
284 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><DL>
286 <I>rulename field1
</I> :
<I>field2
</I> :
<I>...
</I> :
<I>fieldN
</I> ;
288 <P><DD>Invoke a rule. A rule is invoked with values in
289 <I>field1
</I> through
<I>fieldN
</I> (
9 max). They may be
290 referenced in the procedure's
<I>statements
</I> as $(
1)
291 through $(
<9>N
</I>). $(
<) and $(
>) are synonymous
292 with $(
1) and $(
2).
</P>
294 <P><i>rulename
</i> undergoes
<A HREF=
"#varexp"> variable
295 expansion
</A>. If the resulting list is more than one value,
296 each rule is invoked with the same arguments, and the result
297 of the invocation is the concatenation of all the results.
</P>
300 actions [
<I>modifiers
</I> ]
<I>rulename
</I> {
<I>commands
</I> }
302 <P><DD> Define a rule's updating actions, replacing any previous
303 definition. The first two arguments may be referenced in
304 the action's
<I>commands
</I> as $(
1) and $(
2) or $(
<)
307 <P>The following action
<i>modifiers
</i> are understood:
308 <P><TABLE BORDER=
"1">
309 <TR><TD WIDTH=
30%
><CODE>actions bind
<I>vars
</I></CODE></TD>
310 <TD>$(vars) will be replaced with bound values.
</TD>
312 <TR><TD><CODE>actions existing
</CODE></TD>
313 <TD>$(
>) includes only source targets currently existing.
</TD>
315 <TR><TD><CODE>actions ignore
</CODE></TD>
316 <TD>The return status of the
<I>commands
</I> is ignored.
</TD>
318 <TR><TD><CODE>actions piecemeal
</CODE></TD>
319 <TD><I>commands
</I> are repeatedly invoked with a subset
320 of $(
>) small enough to fit in the command buffer on this
323 <TR><TD><CODE>actions quietly
</CODE></TD>
324 <TD>The action is not echoed to the standard output.
</TD>
326 <TR><TD><CODE>actions together
</CODE></TD>
327 <TD>The $(
>) from multiple invocations of the same action
328 on the same built target are glommed together.
</TD>
330 <TR><TD><CODE>actions updated
</CODE></TD>
331 <TD>$(
>) includes only source targets themselves marked
336 <P><DT><CODE>break
</CODE></P>
337 <P><DD>Breaks out of the closest enclosing
<I>for
</I> or
<I>while
</I> loop.
</P>
339 <P><DT><CODE>continue
</CODE></P>
340 <P><DD>Jumps to the end of the closest enclosing
<I>for
</I> or
<I>while
</I> loop.
343 for
<I>var
</I> in
<I>list
</I> {
<I>statements
</I> }
345 <P><DD>Executes
<i>statements
</i> for each element in
346 <i>list
</i>, setting the variable
<i>var
</i> to the element value.
</P>
350 if
<I>cond
</I> {
<I>statements
</I> } [ else
<I>statement
</I> ]
352 <P><DD>Does the obvious; the else clause is optional.
<i>cond
</i> is built of:
354 <TR><TD WIDTH=
"25%"><CODE><I>a
</I></CODE></TD>
355 <TD>true if any
<I>a
</I> element is a non-zero-length string
</TD>
357 <TR><TD><CODE><I>a
</I> =
<I>b
</I></CODE></TD>
358 <TD>list
<I>a
</I> matches list
<I>b
</I> string-for-string
</TD>
360 <TR><TD><CODE><I>a
</I> !=
<I>b
</I></CODE></TD>
361 <TD>list
<I>a
</I> does not match list
<I>b
</I></TD>
363 <TR><TD><CODE><I>a
</I> < <I>b
</I></CODE></TD>
364 <TD><I>a[i]
</I> string is less than
<I>b[i]
</I> string, where
<i>i
</i> is first mismatched element
365 in lists
<I>a
</I> and
<I>b
</I></TD>
367 <TR><TD><CODE><I>a
</I> <=
<I>b
</I></CODE></TD>
368 <TD>every
<I>a
</I> string is less than or equal to its
<I>b
</I> counterpart
</TD>
370 <TR><TD><CODE><I>a
</I> > <I>b
</I></CODE></TD>
371 <TD><I>a[i]
</I> string is greater than
<I>b[i]
</I> string, where
<i>i
</i> is first mismatched element
</TD>
373 <TR><TD><CODE><I>a
</I> >=
<I>b
</I></CODE></TD>
374 <TD>every
<I>a
</I> string is greater than or equal to its
<I>b
</I> counterpart
</TD>
376 <TR><TD><CODE><I>a
</I> in
<I>b
</I></CODE></TD>
377 <TD>true if all elements of
<I>a
</I> can be found in
<I>b
</I>, or if
<I>a
</I> has no elements
</TD>
379 <TR><TD><CODE>!
<I>cond
</I></CODE></TD>
380 <TD>condition not true
</TD>
382 <TR><TD><CODE><I>cond
</I> &&
<I>cond
</I></CODE></TD>
385 <TR><TD> <CODE><I>cond
</I> ||
<I>cond
</I></CODE></TD>
388 <TR><TD><CODE>(
<I>cond
</I> )
</CODE></TD>
389 <TD>precedence grouping
</TD>
393 <P><DT><CODE>include
<I>file
</I> ;
</CODE></P>
394 <P><DD>Causes
<b>jam
</b> to read the named
<i>file
</i>.
395 The file is bound like a regular target (see
<A HREF=
"#binding">Binding
</A>
396 above) but unlike a regular target the include file cannot be built.
397 Marking an include file target with the
<b>NOCARE
</b> rule makes it optional:
398 if it is missing, it causes no error.
</P>
400 <P>The include file is inserted into the input stream during
401 the parsing phase. The primary input file and all the included
402 file(s) are treated as a single file; that is,
<b>jam
</b>
403 infers no scope boundaries from included files.
</P>
405 <P><DT><CODE>local
<i>vars
</I> [ =
<i>values
</i> ] ;
</CODE></P>
406 <P><DD>Creates new
<i>vars
</i> inside to the enclosing {}
407 block, obscuring any previous values they might have. The
408 previous values for
<i>vars
</i> are restored when the current
409 block ends. Any rule called or file included will see the
410 local and not the previous value (this is sometimes called
411 Dynamic Scoping). The local statement may appear anywhere,
412 even outside of a block (in which case the previous value
413 is restored when the input ends). The
<i>vars
</i> are
414 initialized to
<i>values
</i> if present, or left uninitialized
417 <P><DT><CODE>on
<I>target
</I> <I>statement
</I> ;
</CODE></P>
418 <P><DD>Run
<I>statement
</I> under the influence of
419 <I>target
</I>'s target-specific variables. These variables
420 become local copies during
<I>statement
</I>'s run, but they
421 may be updated as target-specific variables using the usual
422 "<I>variable</I> on <I>targets</I> =" syntax.
</P>
424 <P><DT><CODE>return
<I>values
</I> ;
</CODE></P>
425 <P><DD>Within a rule body, the return statement sets the return
426 value for an invocation of the rule and terminates the rule's
429 <P><DT><CODE>rule
<I>rulename
</I> [ :
<I>vars
</I> ] {
<I>statements
</I> }
</CODE></P>
430 <P><DD>Define a rule's procedure, replacing any previous
431 definition. If
<I>vars
</I> are provided, they are assigned
432 the values of the parameters ($(
1) to $(
9)) when
<I>statements
</I>
433 are executed, as with the
<B>local
</B> statement.
</P>
435 <A NAME=
"switch"></A>
436 <P><DT><CODE>switch
<I>value
</I>
438 <BR> case
<I>pattern1
</I> :
<I>statements
</I> ;
439 <BR> case
<I>pattern2
</I> :
<I>statements
</I> ;
443 <P><DD>The switch statement executes zero or one of the
444 enclosed
<i>statements
</i>, depending on which, if any, is
445 the first case whose
<i>pattern
</I> matches
<i>value
</i>.
446 The
<i>pattern
</I> values are not variable-expanded. The
447 <i>pattern
</I> values may include the following wildcards:
449 <TR><TD><CODE>?
</CODE></TD><TD>match any single character
</TD></TR>
450 <TR><TD><CODE>*
</CODE></TD><TD>match zero or more characters
</TD></TR>
451 <TR><TD><CODE>[
<i>chars
</i>]
</CODE></TD><TD>match any single character in
<i>chars
</i></TD></TR>
452 <TR><TD><CODE>[^
<i>chars
</i>]
</CODE></TD><TD>match any single character not in
<i>chars
</i></TD></TR>
453 <TR><TD><CODE>\
<i>x
</i></CODE></TD><TD>match
<i>x
</i> (escapes the other wildcards)
</i></TD></TR>
455 Note that escaping isn't working in range definitions. To include
"]" in range, one can
456 write range as
"[]...]" or
"[^]...]".
</P>
458 <P><DT><CODE>while
<I>cond
</I> {
<I>statements
</I> }
</CODE></P>
459 <P><DD>Repeatedly execute
<I>statements
</I> while
<I>cond
</I>
460 remains true upon entry. (See the description of
<I>cond
</I>
461 expression syntax under
<a href=
"#if">if
</a>, above).
462 </DL></TD></TR></TABLE></P>
465 <DT><P><H3>Variables
</H3><DD>
466 <P><B>Jam
</b> variables are lists of zero or more elements, with
467 each element being a string value. An undefined variable is
468 indistinguishable from a variable with an empty list, however,
469 a defined variable may have one more elements which are null
470 strings. All variables are referenced as $(
<I>variable
</I>).
</P>
472 <P>Variables are either global or target-specific. In the latter
473 case, the variable takes on the given value only during the
474 target's binding, header file scanning, and updating; and during
475 the
"on <I>target</I> <I>statement</I>" statement.
</P>
477 <P>A variable is defined with:
</P>
478 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><DL>
479 <DT><CODE><I>variable
</I> =
<I>elements
</I> ;
</CODE>
480 <DT><CODE><I>variable
</I> +=
<I>elements
</I> ;
</CODE>
481 <DT><CODE><I>variable
</I> ?=
<I>elements
</I> ;
</CODE>
482 <DT><CODE><I>variable
</I> on
<I>targets
</I> =
<I>elements
</I> ;
</CODE>
483 <DT><CODE><I>variable
</I> on
<I>targets
</I> +=
<I>elements
</I> ;
</CODE>
484 <DT><CODE><I>variable
</I> on
<I>targets
</I> ?=
<I>elements
</I> ;
</CODE>
485 </DL></TD></TR></TABLE>
487 <P>The first three forms set
<I>variable
</I> globally. The last
488 three forms set a target-specific variable. The = operator
489 replaces any previous elements of
<I>variable
</I> with
490 <I>elements
</I>; the += operation adds
<I>elements
</I> to
491 <I>variable
</I>'s list of elements; the ?= operator sets
492 <I>variable
</I> only if it was previously unset. The last form
493 "<I>variable</I> on <I>targets</I> ?= <I>elements</I>" checks
494 to see if the target-specific, not the global, variable is set.
495 (The ?= operator also has an old form
"default =".)
</P>
497 <P>Variables referenced in updating commands will be replaced with
498 their values; target-specific values take precedence over global
499 values. Variables passed as arguments ($(
1) and $(
2)) to actions
500 are replaced with their bound values; the
"bind" modifier can
501 be used on actions to cause other variables to be replaced with
502 bound values. See
<A HREF=
"#actionmods">Action Modifiers
</A>
505 <P><B>Jam
</b> variables are not re-exported to the environment of
506 the shell that executes the updating actions, but the updating
507 actions can reference
<b>jam
</b> variables with $(
<I>variable
</I>).
</P>
509 <A NAME=
"varexp"></A>
510 <DT><P><H3>Variable Expansion
</H3></P><DD>
511 <P>During parsing,
<b>jam
</b> performs variable expansion on each
512 token that is not a keyword or rule name. Such tokens with
513 embedded variable references are replaced with zero or more
514 tokens. Variable references are of the form $(
<I>v
</I>) or
515 $(
<I>vm
</I>), where
<i>v
</i> is the variable name, and
<I>m
</I>
516 are optional modifiers.
</P>
518 <P>Variable expansion in a rule's actions is similar to variable
519 expansion in statements, except that the action string is
520 tokenized at whitespace regardless of quoting.
</P>
522 <P>The result of a token after variable expansion is the
523 <i>product
</i> of the components of the token, where each
524 component is a literal substring or a list substituting a variable
525 reference. For example:
</P>
526 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><CODE>
528 <BR>t$(X) -
> ta tb tc
529 <BR>$(X)z -
> az bz cz
530 <BR>$(X)-$(X) -
> a-a a-b a-c b-a b-b b-c c-a c-b c-c
531 </CODE></TD></TR></TABLE></P>
533 <P>The variable name and modifiers can themselves contain
534 a variable reference, and this partakes of the product
536 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><CODE>
540 <BR>$($(Z)) -
> a b c
1 2
541 </CODE></TD></TR></TABLE></P>
543 <P>Because of this product expansion, if any variable reference in
544 a token is undefined, the result of the expansion is an empty
545 list. If any variable element is a null string, the result
546 propagates the non-null elements:
</P>
547 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><CODE>
551 <BR>*$(X)$(Y)* -
> *a* *a1* ** *
1*
553 </CODE></TD></TR></TABLE></P>
555 <P>A variable element's string value can be parsed into grist and
556 filename-related components. Modifiers to a variable are used
557 to select elements, select components, and replace components.
558 The modifiers are:
</P>
559 <P><TABLE WIDTH=
"75%" BORDER=
"1" ALIGN=
"CENTER">
560 <TR><TD><CODE>[
<I>n
</I>]
</CODE></TR>
561 <TD>Select element number
<I>n
</I> (starting at
1).
562 If the variable contains fewer than
<I>n
</I> elements,
563 the result is a zero-element list.
565 <TR><TD><CODE>[
<I>n
</I>-
<I>m
</I>]
</CODE></TD>
566 <TD>Select elements number
<I>n
</I> through
<I>m
</I>.
</TD></TR>
567 <TR><TD><CODE>[
<I>n
</I>-]
</CODE></TD>
568 <TD>Select elements number
<I>n
</I> through the last.
</TD></TR>
569 <TR><TD><CODE>:B
</CODE></TD><TD>Select filename base.
</TD></TR>
570 <TR><TD><CODE>:S
</CODE></TD><TD>Select (last) filename suffix.
</TD></TR>
571 <TR><TD><CODE>:M
</CODE></TD><TD>Select archive member name.
</TD></TR>
572 <TR><TD><CODE>:D
</CODE></TD><TD>Select directory path.
</TD></TR>
573 <TR><TD><CODE>:P
</CODE></TD><TD>Select parent directory.
</TD></TR>
574 <TR><TD><CODE>:G
</CODE></TD><TD>Select grist.
</TD></TR>
575 <TR><TD><CODE>:U
</CODE></TD><TD>Replace lowercase characters with uppercase.
</TD></TR>
576 <TR><TD><CODE>:L
</CODE></TD><TD>Replace uppercase characters with lowercase.
</TD></TR>
577 <TR><TD><CODE>:Q
</CODE></TD><TD>Quote special characters for safe shell execution.
</TD></TR>
578 <TR><TD><CODE>:
<i>chars
</I></CODE></TD><TD>Select the components listed in
<i>chars
</i>.
</TD></TR>
579 <TR><TD><CODE>:G=
<I>grist
</I></CODE></TD><TD>Replace grist with
<I>grist
</I>.
</TD></TR>
580 <TR><TD><CODE>:D=
<I>path
</I></CODE></TD><TD>Replace directory with
<I>path
</I>.
</TD></TR>
581 <TR><TD><CODE>:B=
<I>base
</I></CODE></TD><TD>Replace the base part of file name with
<I>base
</I>.
</TD></TR>
582 <TR><TD><CODE>:S=
<I>suf
</I></CODE></TD><TD>Replace the suffix of file name with
<I>suf
</I>.
</TD></TR>
583 <TR><TD><CODE>:M=
<I>mem
</I></CODE></TD><TD>Replace the archive member name with
<I>mem
</I>.
</TD></TR>
584 <TR><TD><CODE>:R=
<I>root
</I></CODE></TD><TD>Prepend
<I>root
</I> to the whole file name, if not already rooted.
</TD></TR>
585 <TR><TD><CODE>:E=
<I>value
</I></CODE></TD><TD>Use
<I>value
</I> instead if the variable is unset.
</TD></TR>
586 <TR><TD><CODE>:J=
<I>joinval
</I></CODE></TD><TD>Concatentate list elements into single element, separated by
<I>joinval
</I>.
</TD></TR>
589 <P>on Unix and NT, $(var:P) and $(var:D) are the same.
<BR/>
590 <b><u>TODO:
</u></b> <i>make $(var:P) return parent dir on Unix and NT!
</i>
594 <DT><P><H3>Built-in Rules
</H3></P><DD>
595 <P><B>Jam
</b> has twelve built-in rules, all of which are pure
596 procedure rules without updating actions. They are in
597 three groups: the first builds the dependency graph;
598 the second modifies it; and the third are just utility
601 <P><H5>Dependency Building
</H5></P>
602 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><DL>
603 <P><DT><CODE>DEPENDS
<I>targets1
</I> :
<I>targets2
</I> ;
</CODE>
604 <DD>Builds a direct dependency: makes each of
<I>targets1
</I>
605 depend on each of
<I>targets2
</I>. Generally,
<I>targets1
</I>
606 will be rebuilt if
<I>targets2
</I> are themselves rebuilt are
607 or are newer than
<I>targets1
</I>.
</P>
608 <P><DT><CODE>INCLUDES
<I>targets1
</I> :
<I>targets2
</I> ;
</CODE>
609 <DD>Builds a sibling dependency: makes any target that depends
610 on any of
<I>targets1
</I> also depend on each of
<I>targets2
</I>.
611 This reflects the dependencies that arise when one source file
612 includes another: the object built from the source file depends
613 both on the original and included source file, but the two
614 sources files don't depend on each other. For example:
616 <P>DEPENDS foo.o : foo.c ;
617 <BR>INCLUDES foo.c : foo.h ;
619 <P>"foo.o" depends on
"foo.c" and
"foo.h" in this example.
</P>
620 </DL></TD></TR></TABLE></P>
622 <A NAME=
"bindingmods"></A>
623 <P><H5>Modifying Binding
</H5></P>
624 <P>The six rules ALWAYS, LEAVES, NOCARE, NOTFILE, NOUPDATE, and
625 TEMPORARY modify the dependency graph so that
<b>jam
</b> treats
626 the targets differently during its target binding phase. See
627 <A HREF=
"#binding">Binding
</A> above. Normally,
<b>jam
</b>
628 updates a target if it is missing, if its filesystem modification
629 time is older than any of its dependencies (recursively), or if
630 any of its dependencies are being updated. This basic behavior
631 can be changed by invoking the following rules:
</P>
632 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><DL>
633 <P><DT><CODE>ALWAYS
<I>targets
</I> ;
</CODE>
634 <DD>Causes
<I>targets
</I> to be rebuilt regardless of whether
635 they are up-to-date (they must still be in the dependency graph).
636 This is used for the clean and uninstall targets, as they have
637 no dependencies and would otherwise appear never to need building.
638 It is best applied to targets that are also NOTFILE targets,
639 but it can also be used to force a real file to be updated as
641 <P><DT><CODE>LEAVES
<I>targets
</I> ;
</CODE>
642 <DD> Makes each of
<I>targets
</I> depend only on its leaf sources,
643 and not on any intermediate targets. This makes it immune to
644 its dependencies being updated, as the
"leaf" dependencies are
645 those without their own dependencies and without updating actions.
646 This allows a target to be updated only if original source files
648 <P><DT><CODE>NOCARE
<I>targets
</I> ;
</CODE>
649 <DD>Causes
<b>jam
</b> to ignore
<I>targets
</I> that neither
650 can be found nor have updating actions to build them. Normally
651 for such targets
<B>jam
</B> issues a warning and then skips
652 other targets that depend on these missing targets. The HdrRule
653 in Jambase uses NOCARE on the header file names found during
654 header file scanning, to let
<b>jam
</b> know that the included
655 files may not exist. For example, if a #include is within an
656 #ifdef, the included file may not actually be around.
</P>
657 <P><DT><CODE>NOTFILE
<I>targets
</I> ;
</CODE>
658 <DD>Marks
<I>targets
</I> as pseudotargets and not real files.
659 No timestamp is checked, and so the actions on such a target
660 are only executed if the target's dependencies are updated, or
661 if the target is also marked with ALWAYS. The default
<b>jam
</b>
662 target
"all" is a pseudotarget. In Jambase, NOTFILE is used to
663 define several addition convenient pseudotargets.
</P>
664 <P><DT><CODE>NOUPDATE
<I>targets
</I> ;
</CODE>
665 <DD>Causes the timestamps on
<I>targets
</I> to be ignored.
666 This has two effects: first, once the target has been created
667 it will never be updated; second, manually updating target will
668 not cause other targets to be updated. In Jambase, for example,
669 this rule is applied to directories by the MkDir rule, because
670 MkDir only cares that the target directory exists, not when it
671 has last been updated.
</P>
672 <P><DT><CODE>TEMPORARY
<I>targets
</I> ;
</CODE>
673 <DD>Marks
<I>targets
</I> as temporary, allowing them to be
674 removed after other targets that depend upon them have been
675 updated. If a TEMPORARY target is missing,
<b>jam
</b> uses the
676 timestamp of the target's parent. Jambase uses TEMPORARY to
677 mark object files that are archived in a library after they are
678 built, so that they can be deleted after they are archived.
</P>
679 </DL></TD></TR></TABLE></P>
681 <P><H5>Utility Rules
</H5></P>
682 The remaining rules are utility rules.
683 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><DL>
685 ECHO
<i>args
</I> ;
<br>
686 Echo
<i>args
</I> ;
<br>
689 <DD>Blurts out the message
<i>args
</I> to stdout.
</P>
691 EXIT
<i>args
</I> ;
<br>
692 Exit
<i>args
</I> ;
<br>
695 <DD>Blurts out the message
<i>args
</I> to stdout and then exits
696 with a failure status.
</P>
698 GLOB
<i>directories
</I> :
<I>patterns
</I> ;
699 Glob
<i>directories
</I> :
<I>patterns
</I> ;
701 <DD>Scans
<i>directories
</i> for files matching
<i>patterns
</i>,
702 returning the list of matching files (with directory prepended).
703 <i>patterns
</i> uses the same syntax as in the
<b>switch
</b>
704 statement. Only useful within the
<tt>[ ]
</tt> construct, to
705 change the result into a list. Files with names
"." and
".." will
706 be automatically ommited.
</P>
708 MATCH
<i>regexps
</I> :
<I>list
</I> ;
709 Match
<i>regexps
</I> :
<I>list
</I> ;
711 <DD>Matches the
<b>egrep
</b>(
1) style regular expressions
712 <I>regexps
</I> against the strings in
<I>list
</I>. The result
713 is the concatenation of matching
<tt>()
</tt> subexpressions for
714 each string in
<I>list
</I>, and for each regular expression in
715 <I>regexps
</I>. Only useful within the
<tt>[ ]
</tt> construct,
716 to change the result into a list.
</P>
718 COMMAND
<i>shellcmd
</i> :
<i>options
</i> ;
719 Command
<i>shellcmd
</i> :
<i>options
</i> ;
721 <DD>Execute external command and return exit code and/or command output.
722 Only useful within the
<tt>[ ]
</tt> construct.
723 <P>possible
"options" values (can be combined):
</P>
724 <P><TABLE WIDTH=
"75%" BORDER=
"1" ALIGN=
"CENTER">
725 <TR><TD><CODE>exit-status, exit-code
</CODE></TD>
726 <TD>Return exit code as the last list element (default: return as the first element).
</TD></TR>
727 <TR><TD><CODE>no-output
</CODE></TD>
728 <TD>Don't process and return command output (default: process).
</TD></TR>
729 <TR><TD><CODE>no-trim
</CODE></TD>
730 <TD>Don't trim command output (default: trim left and right).
</TD></TR>
731 <TR><TD><CODE>no-trim-left
</CODE></TD>
732 <TD>Don't left-trim command output (default: trim left and right).
</TD></TR>
733 <TR><TD><CODE>no-trim-right
</CODE></TD>
734 <TD>Don't right-trim command output (default: trim left and right).
</TD></TR>
735 <TR><TD><CODE>status-first, code-first
</CODE></TD>
736 <TD>Put exit code first (default: last)
</TD></TR>
737 <TR><TD><CODE>parse-output
</CODE></TD>
738 <TD>Parse output as list (break on chars witch codes
1.
.32) (default: don't break).
</TD></TR>
739 <TR><TD><CODE>no-space-break
</CODE></TD>
740 <TD>Don't break on spaces (' ') when 'parse-output' activated.
</TD></TR>
741 <TR><TD><CODE>no-tab-break
</CODE></TD>
742 <TD>Don't break on tabs ('\t') when 'parse-output' activated.
</TD></TR>
743 <TR><TD><CODE>no-nl-break, no-lf-break
</CODE></TD>
744 <TD>Don't break on LF ('\n') when 'parse-output' activated.
</TD></TR>
745 <TR><TD><CODE>no-cr-break
</CODE></TD>
746 <TD>Don't break on CR ('\r') when 'parse-output' activated.
</TD></TR>
753 <DD>Sort list alphabetically (ascending).
754 Only useful within the
<tt>[ ]
</tt> construct.
760 <DD>Return current working directory. Only useful within the
<tt>[ ]
</tt> construct.
762 </DL></TD></TR></TABLE></P>
764 <DT><P><H3>Built-in Variables
</H3></P><DD>
765 <P>This section discusses variables that have special meaning to
<b>jam
</b>.
</P>
766 <A NAME=
"search"></A>
767 <P><H4>SEARCH and LOCATE Variables
</H4></P>
768 <P>These two variables control the binding of file target names to
769 locations in the file system. Generally, $(SEARCH) is used to
770 find existing sources while $(LOCATE) is used to fix the location
771 for built targets.
</P>
773 <P>Rooted (absolute path) file targets are bound as is. Unrooted
774 file target names are also normally bound as is, and thus relative
775 to the current directory, but the settings of $(LOCATE) and
776 $(SEARCH) alter this:
</P>
779 <LI>If $(LOCATE) is set then the target is bound relative to
780 the first directory in $(LOCATE). Only the first element is
781 used for binding.
</LI>
782 <LI>If $(SEARCH) is set then the target is bound to the first
783 directory in $(SEARCH) where the target file already exists.
</LI>
784 <LI>If the $(SEARCH) search fails, the target is bound relative
785 to the current directory anyhow.
</LI>
788 <P>Both $(SEARCH) and $(LOCATE) should be set target-specific and
789 not globally. If they were set globally,
<b>jam
</b> would use
790 the same paths for all file binding, which is not likely to
791 produce sane results. When writing your own rules, especially
792 ones not built upon those in Jambase, you may need to set
793 $(SEARCH) or $(LOCATE) directly. Almost all of the rules defined
794 in Jambase set $(SEARCH) and $(LOCATE) to sensible values for
795 sources they are looking for and targets they create, respectively.
</P>
797 <A NAME=
"hdrscan"></A>
798 <P><H4>HDRSCAN and HDRRULE Variables
</H4></P>
799 <P>These two variable control header file scanning. $(HDRSCAN) is
800 an
<b>egrep
</b>(
1) pattern, with ()'s surrounding the file name,
801 used to find file inclusion statements in source files. Jambase
802 uses $(HDRPATTERN) as the pattern for $(HDRSCAN). $(HDRRULE)
803 is the name of a rule to invoke with the results of the scan:
804 the scanned file is the target, the found files are the sources.
805 $(HDRRULE) is run under the influence of the scanned file's
806 target-specific variables.
</P>
808 <P>Both $(HDRSCAN) and $(HDRRULE) must be set for header file
809 scanning to take place, and they should be set target-specific
810 and not globally. If they were set globally, all files, including
811 executables and libraries, would be scanned for header file
812 include statements.
</P>
814 <P>The scanning for header file inclusions is not exact, but it is
815 at least dynamic, so there is no need to run something like
816 <b>makedepend
</b>(GNU) to create a static dependency file. The
817 scanning mechanism errs on the side of inclusion (i.e., it is
818 more likely to return filenames that are not actually used by
819 the compiler than to miss include files) because it can't tell
820 if #include lines are inside #ifdefs or other conditional logic.
821 In Jambase, HdrRule applies the NOCARE rule to each header file
822 found during scanning so that if the file isn't present yet
823 doesn't cause the compilation to fail,
<b>jam
</b> won't care.
</P>
825 <P>Also, scanning for regular expressions only works where the
826 included file name is literally in the source file. It can't
827 handle languages that allow including files using variable names
828 (as the Jam language itself does).
</P>
830 <P><H4>Platform Identifier Variables
</H4></P>
831 <P>A number of Jam built-in variables can be used to identify
832 runtime platform:
</P>
833 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER">
834 <TR><TD>OS
</TD><TD>OS identifier string
</TD></TR>
835 <TR><TD>OSPLAT
</TD><TD>Underlying architecture, when applicable
</TD></TR>
836 <TR><TD>NT
</TD><TD>true on NT platform
</TD></TR>
837 <TR><TD>UNIX
</TD><TD>true on Unix platforms
</TD></TR>
840 <P><H4>Jam Version Variables
</H4></P>
841 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER">
842 <TR><TD>JAMDATE
</TD><TD>Time and date at
<b>jam
</b> start-up.
</TD></TR>
843 <TR><TD>JAMUNAME
</TD><TD>Ouput of
<b>uname
</b>(
1) command (Unix only)
</TD></TR>
844 <TR><TD>JAMVERSION
</TD><TD><b>jam
</b> version, as reported by jam -v.
</TD></TR>
845 <TR><TD>JAMBASEDATE
</TD><TD><i>Obsolete:
</i> <i>Jambase
</i> date.
</TD></TR>
846 <TR><TD>THIS_IS_KJAM
</TD><TD>Not empty if this is
<b>K8Jam
</b>.
</TD></TR>
849 <P><H4>JAMCMDARGS Variable
</H4></P>
850 <P>A new builting variable has been defined. When K8Jam start, it defines
851 the variable JAMCMDARGS which contains the list of targets used on the
852 command line when Jam was invoked.
</P>
854 <P>This is useful to provide richer control flow in the Jambase depending
855 on command line arguments.
</P>
857 <P><H4>JAMSHELL Variable
</H4></P>
858 <P>When
<b>jam
</b> executes a rule's action block, it forks and
859 execs a shell, passing the action block as an argument to the
860 shell. The invocation of the shell can be controlled by
861 $(JAMSHELL).The default on Unix is, for example:
</P>
863 <P><CODE>JAMSHELL = /bin/sh -c % ;
</CODE></P>
864 <P>The % is replaced with the text of the action block.
</P>
866 <P><B>Jam
</b> does not directly support building in parallel across
867 multiple hosts, since that is heavily dependent on the local
868 environment. To build in parallel across multiple hosts, you
869 need to write your own shell that provides access to the multiple
870 hosts. You then reset $(JAMSHELL) to reference it.
</P>
872 <P>Just as
<b>jam
</b> expands a % to be the text of the rule's
873 action block, it expands a ! to be the multi-process slot number.
874 The slot number varies between
1 and the number of concurrent
875 jobs permitted by the -j flag given on the command line. Armed
876 with this, it is possible to write a multiple host shell. For
879 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><CODE>
882 <BR># This sample JAMSHELL uses the SunOS on(
1) command to execute a
883 <BR># command string with an identical environment on another host.
885 <BR># Set JAMSHELL = jamshell ! %
887 <BR># where jamshell is the name of this shell file.
889 <BR># This version handles up to -j6; after that they get executed
893 <BR>1|
4) on winken sh -c
"$2";;
894 <BR>2|
5) on blinken sh -c
"$2";;
895 <BR>3|
6) on nod sh -c
"$2";;
898 </CODE></TD></TR></TABLE></P>
901 <DT><P><H2>DIAGNOSTICS
</H2></P><DD>
902 <P>In addition to generic error messages,
<B>jam
</B> may emit one of the following:
</P>
903 <P><TABLE WIDTH=
"75%" ALIGN=
"CENTER"><TR><TD><DL>
904 <P><DT><CODE>warning: unknown rule X
</CODE><DD>
905 A rule was invoked that has not been defined with an
"actions" or
"rule" statement.
906 <P><DT><CODE>using N temp target(s)
</CODE><DD>
907 Targets marked as being temporary (but nonetheless present) have been found.
908 <P><DT><CODE>updating N target(s)
</CODE><DD>
909 Targets are out-of-date and will be updated.
910 <P><DT><CODE>can't find N target(s)
</CODE><DD>
911 Source files can't be found and there are no actions to create them.
912 <P><DT><CODE>can't make N target(s)
</CODE><DD>
913 Due to sources not being found, other targets cannot be made.
914 <P><DT><CODE>warning: X depends on itself
</CODE><DD>
915 A target depends on itself either directly or through its sources.
916 <P><DT><CODE>don't know how to make X
</CODE><DD>
917 A target is not present and no actions have been defined to create it.
918 <P><DT><CODE>X skipped for lack of Y
</CODE><DD>
919 A source failed to build, and thus a target cannot be built.
920 <P><DT><CODE>warning: using independent target X
</CODE><DD>
921 A target that is not a dependency of any other target is being referenced with $(
<) or $(
>).
922 <P><DT><CODE>X removed
</CODE><DD>
923 <b>Jam
</b> removed a partially built target after being interrupted.
924 </DL></TD></TR></TABLE></P>
926 <DT><P><H2>BUGS, LIMITATIONS
</H2></P><DD>
927 <P>The -j flag can cause
<B>jam
</B> to get confused when single
928 actions update more than one target at a time.
<B>jam
</B> may
929 proceed as if the targets were built even though they are still
930 under construction.
</P>
932 <P>For parallel building to be successful, the dependencies among
933 files must be properly spelled out, as targets tend to get built
934 in a quickest-first ordering. Also, beware of un-parallelizable
935 commands that drop fixed-named files into the current directory,
936 like
<b>yacc
</b>(
1) does.
</P>
938 <P>With the -j flag, errors from failed commands can get staggeringly
941 <P>A poorly set $(JAMSHELL) is likely to result in silent failure.
</P>
943 <DT><P><H2>SEE ALSO
</H2><DD>
945 <LI><a href=
"Jambase.html">Jambase Reference
</a></LI>
946 <LI><a href=
"Jamfile.html">Using Jamfiles and Jambase
</a></LI>
949 <P>Jam documentation and source are available from the
950 <A HREF=
"http://public.perforce.com/public/index.html">Perforce Public Depot
</a>.
</P>
952 <DT><P><H2>AUTHOR
</H2></P><DD>
953 <P>Jam's author is Christopher Seiwald (
<a href=
"mailto:seiwald@perforce.com">seiwald@perforce.com
</A>).
<BR/>
954 Documentation is provided by
<A HREF=
"http://www.perforce.com">Perforce Software, Inc.
</A><BR/>
955 "FT-Jam" is a simple derivative of the Jam build tool, based and
100% compatible with Jam
2.5.
956 See
<a href=
"http://www.freetype.org/jam/">http://www.freetype.org/jam/
</a> for more details.
<BR/>
957 "K8Jam" is a derivative of FT-Jam.
958 See
<a href=
"http://gitorious.org/projects/kjam">gitorious repository
</a> for the latest sources.
963 <P>Copyright
1993-
2002 Christopher Seiwald and Perforce Software, Inc.
<BR>