Jam - Command

The Jam Executable

USAGE

jam [ -a ] [ -g ] [ -n ] [ -q ] [ -v ]
    [ -d display ]
    [ -f Jambase ]
    [ -j jobs ]
    [ -o actionsfile ]
    [ -s var=value ]
    [ -t target ]
    [ target ... ]

DESCRIPTION

Jam is a program construction tool, like make(1).

Jam recursively builds target files from source files, using dependency information and updating actions expressed in the Jambase file, which is written in jam's own interpreted language. The default Jambase is compiled into jam and provides a boilerplate for common use, relying on a user-provide file "Jamfile" to enumerate actual targets and sources.

The Jambase is described in the Jambase Reference and the document Using Jamfile, Jamrules and Jambase.

OPTIONS

If target is provided on the command line, jam builds target; otherwise jam builds the target 'all'.

Jam may be invoked with the following options:

-a Build all targets anyway, even if they are up-to-date.
-d c
-d n
-d +n
Display:
change default option to c
change default option to 1 thru n
add default option +n

a

Show summary info, actions, quiet actions, temporary targets (-d2)

c

Show the cause (file names) cause rebuilds; new sources, missing targets

d

Display a dependency graph (in jam syntax).

m

Display the dependency analysis, and target/source timestamps and paths (-d3)

x

Show shell arguments (-d2)

0

Turn off all display. Only errors are emitted.

1

Show actions and summary info (the default)

3

dependency analysis (-dm)

5

Show rule invocations and variable expansions

6

Show directory/header file/archive scans

7

Show variable settings

8

Show variable fetches

9

Show variable manipulation, scanner tokens
-f Jambase Read Jambase instead of using the built-in Jambase.
Multiple -f flags are permitted.
-g Build targets with the newest sources first, rather than the order of appearance in the Jambase/Jamfiles.
-j n Run up to n shell commands concurrently. The default is 1.
-n Don't actually execute the updating actions, but do everything else. This changes the debug level to -dax.
-o file Write the updating actions to the specified file instead of running them. These are the actual compiler commands; different from the output from -dx.
-q Quit quickly (as if an interrupt was received) as soon as any target build fails.
-s var=value Set the variable var to value, overriding both internal variables and variables imported from the environment.
-t target Touch target and rebuild everything that depends on it, even if it is up-to-date.
-v Print the version of jam and exit.

OPERATION

Jam has four phases of operation: start-up, parsing, binding, and updating.

Start-up

Upon start-up, jam imports environment variable settings into jam variables. Environment variables are split at blanks with each word becoming an element in the variable's list of values. Environment variables whose names end in PATH are split at $(SPLITPATH) characters (e.g., ":" for Unix).

To set a variable's value on the command line, overriding the variable's environment value, use the -s option. To see variable assignments made during jam's execution, use the -d+7 option.

Parsing

In the parsing phase, jam reads and executes the Jambase file, by default the built-in one. It is written in the jam language. See Language below. The last action of the Jambase is to read (via the "include" rule) a user-provided file called "Jamfile".

Collectively, the purpose of the Jambase and the Jamfile is to name built target and source files, construct the dependency graph among them, and associate build actions with targets. The Jambase defines boilerplate rules and variable assignments, and the Jamfile uses these to specify the actual relationship among the target and source files. See the Jambase Reference and the document Using Jamfiles and Jambase for information.

Binding

After parsing, jam recursively descends the dependency graph and binds every file target with a location in the filesystem.

Targets
Any string value in jam can represent a target, and it does so if the Depends or Includes rules make it part of the dependency graph. Build targets are files to be updated. Source targets are the files used in updating build targets. Build targets and source targets are collectively referred to as file targets, and frequently build targets are source targets for other build targets. Pseudotargets are symbols which represent dependencies on other targets, but which are not themselves associated with any real file.

A file target's identifier is generally the file's name, which can be absolutely rooted, relative to the directory of jam's invocation, or simply local (no directory). Most often it is the last case, and the actual file path is bound using the $(SEARCH) and $(LOCATE) special variables. See SEARCH and LOCATE Variables below. A local filename is optionally qualified with "grist," a string value used to assure uniqueness. A file target with an identifier of the form file(member) is a library member (usually an ar(1) archive on UNIX).

The use of $(SEARCH) and $(LOCATE) allows jam to separate the the location of files from their names, so that Jamfiles can refer to files locally (i.e. relative to the Jamfile's directory), yet still be usable when jam is invoked from a distant directory. The use of grist allows files with the same name to be identified uniquely, so that jam can read a whole directory tree of Jamfiles and not mix up same-named targets.

ToDo: LOCATE_SEARCH and LOCATE_TARGET

Update Determination
After binding each target, jam determines whether the target needs updating, and if so marks the target for the updating phase. A target is normally so marked if it is missing, it is older than any of its sources, or any of its sources are marked for updating. This behavior can be modified by the application of special built-in rules. See Modifying Binding below.

Header File Scanning
During the binding phase, jam also performs header file scanning, where it looks inside source files for the implicit dependencies on other files caused by C's #include syntax. This is controlled by the special variables $(HDRSCAN) and $(HDRRULE). The result of the scan is formed into a rule invocation, with the scanned file as the target and the found included file names as the sources. Note that this is the only case where rules are invoked outside the parsing phase. See HDRSCAN and HDRRULE Variables below.

Updating

After binding, jam again recursively descends the dependency graph, this time executing the update actions for each target marked for update during the binding phase. If a target's updating actions fail, then all other targets which depend on that target are skipped.

The -j flag instructs jam to build more than one target at a time. If there are multiple actions on a single target, they are run sequentially. The -g flag reorders builds so that targets with newest sources are built first. Normally, they are built in the order of appearance in the Jamfiles.

LANGUAGE

Overview

Jam has an interpreted, procedural language with a few select features to effect program construction. Statements in jam are rule (procedure) definitions, rule invocations, updating action definitions, flow-of-control structures, variable assignments, and sundry language support.

Lexical Features

Jam treats its input files as whitespace-separated tokens, with two exceptions: double quotes (") can enclose whitespace to embed it into a token, and everything between the matching curly braces ({}) in the definition of updating actions is treated as a single string. A backslash (\) can escape a double quote, or any single whitespace character. ToDo: rephrase this.

Jam requires whitespace (blanks, tabs, or newlines) to surround all tokens, including the colon (:) and semicolon (;) tokens.

Jam keywords (as mentioned in this document) are reserved and generally must be quoted with double quotes (") to be used as arbitrary tokens, such as variable or target names.

Name conventions:
lowercase pseudo target names (all, clean, obj, exe ... ), language syntax (if, on, case ...)
InitialCap rule name convention
UPPER variable name convention

Datatype

Jam's only data type is a one-dimensional list of arbitrary strings.
They arise as literal (whitespace-separated) tokens in the Jambase or included files, as the result of variable expansion of those tokens, or as the return value from a rule invocation.

Rules

The basic jam language entity is called a rule. A rule is simply a procedure definition, with a body of jam statements to be run when the rule is invoked. The syntax of rule invocation makes it possible to write Jamfiles that look a bit like Makefiles.

Rules take up to 9 arguments ($(1) through $(9), each a list) and can have a return value (a single list).
A rule's return value can be expanded in a list by enclosing the rule invocation with [ and ]. ToDo: examples
$(<) is a synonym for $(1) ... the argument before the (:)
$(>) is a synonym for $(2) ... the argument after the (:) ToDo: so where are $(3) - $(9) ?

Updating Actions

A rule may have updating actions associated with it, in which case arguments $(1) and $(2) are treated as built targets and sources, respectively. Updating actions are the OS shell commands to execute when updating the built targets of the rule.

When a rule with updating actions is invoked, the actions are added to those associated with its built targets ($(1)) before the rule's procedure is run. To build the targets in the updating phase, the actions are passed to the OS command shell ($JAMSHELL), with $(1) and $(2) replaced by bound versions of the target names. See Binding above.

Statements

Jam's language has the following statements:
ToDo: what happened to "set"? "set variable" ??

Causes jam to invoke commands to build the target specified by Rule name.

ToDo: Where does NoCare fit in?

break

Breaks out of the closest enclosing for or while loop.

continue

Jumps to the end of the closest enclosing for or while loop.

for var in list { statements }

Executes statements for each element in list, setting the variable var to the element value.

if cond { statements } [ else statement ]

Does the obvious; the else clause is optional. cond is built of:

actions Rule { commands ; }

bind vars

$(vars) will be replaced with bound values.

existing

$(>) includes only source targets that currently exist.

ignore

The return status of the commands is ignored.

piecemeal

commands are repeatedly invoked with a subset of $(>) small enough to fit in the command buffer on this OS.

quietly

The action is not echoed to the standard output.

together

The $(>) from multiple invocations of the same action on the same built target are glommed together.

updated

$(>) includes only source targets themselves marked for updating.

a

true if any a element is a non-zero-length string

a = b

list a matches list b string-for-string

a != b

list a does not match list b

a < b

a[i] string is less than b[i] string, where i is first mismatched element in lists a and b

a <= b

every a string is less than or equal to its b counterpart

a > b

a[i] string is greater than b[i] string, where i is first mismatched element

a >= b

every a string is greater than or equal to its b counterpart

a in b

true if all elements of a can be found in b, or if a has no elements

! cond

condition not true

cond && cond

conjunction

cond || cond

disjunction

( cond )

precedence grouping

include file ;

Causes jam to read the named file. The file is bound like a regular target (see Binding above) but unlike a regular target the include file cannot be built. Marking an include file target with the NoCare rule makes it optional: if it is missing, it causes no error.

The include file is inserted into the input stream during the parsing phase. The primary input file and all the included file(s) are treated as a single file; that is, jam infers no scope boundaries from included files.

local vars [ = values ] ;

Creates new vars inside to the enclosing {} block, obscuring any previous values they might have. The previous values for vars are restored when the current block ends. Any rule called or file included will see the local and not the previous value (this is sometimes called Dynamic Scoping). The local statement may appear anywhere, even outside of a block (in which case the previous value is restored when the input ends). The vars are initialized to values if present, or left uninitialized otherwise.

on target statement ;

Run statement under the influence of target's target-specific variables. These variables become local copies during statement's run, but they may be updated as target-specific variables using the usual "variable on targets =" syntax.

return values ;

Within a rule body, the return statement sets the return value for an invocation of the rule and terminates the rule's execution.

rule Rulename [ : vars ] { statements }

Define a rule's procedure, replacing any previous definition. If vars are provided, they are assigned the values of the parameters ($(1) to $(9)) when statements are executed, as with the local statement.
set var = value ;
Assigns a value to symbol.

switch value {
case pattern1 : statements ;
case pattern2 : statements ;
...
}
The switch statement executes zero or one of the enclosed statements, depending on which, if any, is the first case whose pattern matches value. The pattern values are not variable-expanded. The pattern values may include the following wildcards:
? match any single character
* match zero or more characters
[chars] match any single character in chars
[^chars] match any single character not in chars
\x match x (escapes the other wildcards)
while cond { statements }

Repeatedly execute statements while cond remains true upon entry. (See the description of cond expression syntax under if, above).

Flow-of-Control

In addition to statements for defining and invoking rules and setting variables, the Jam language contains statements for flow-of-control and file inclusion. The statements are:

    if <cond> { <statements> } [ else { <statements> } ]
    for <var> in <list> { <statements> } 
    while <cond> { <statements> } ;
    switch <value> { case <pattern1> : <statements> ; ... }
    break ;
    continue ;
    return <values> ;
    include <file> ;

The if statement does the obvious; the <condition> is the usual mix of comparison and logical operators applied to variables.

The for statement iterates over the elements of <value>, assigning the (global) variable <var> to each element and executing the statement block.

The switch statement executes the statement block whose case <value> matches the switch's <value>.

The include statement sources another file containing Jam statements.

Variables

Jam variables are lists of zero or more elements, with each element being a string value. An undefined variable is indistinguishable from a variable with an empty list, however, a defined variable may have one more elements which are null strings. All variables are referenced as $(variable) or with modifiers $(variable:BS).

Variables are either global or target-specific. In the latter case, the variable takes on the given value only during the target's binding, header file scanning, and updating; and during the "on target statement" statement.

A variable is defined with:
variable = elements ;
variable += elements ;
variable =+ elements ; ToDo: Unique addition of element
variable ?= elements ;
variable on targets = elements ;
variable on targets += elements ;
variable on targets ?= elements ;
set variable = elements ;

The first three forms set variable globally. The last three forms set a target-specific variable. The = operator replaces any previous elements of variable with elements; the += operation adds elements to variable's list of elements; the ?= operator sets variable only if it was previously unset. The last form "variable on targets ?= elements" checks to see if the target-specific, not the global, variable is set.

Variables referenced in updating commands will be replaced with their values; target-specific values take precedence over global values. Variables passed as arguments ($(1) and $(2)) to actions are replaced with their bound values; the "bind" modifier can be used on actions to cause other variables to be replaced with bound values. See Action Modifiers above.

Jam variables are not re-exported to the environment of the shell that executes the updating actions, but the updating actions can reference jam variables with $(variable).

Variable Expansion

During parsing, jam performs variable expansion on each token that is not a keyword or rule name. Such tokens with embedded variable references are replaced with zero or more tokens. Variable references are of the form $(v) or $(vm), where v is the variable name, and m are optional modifiers. For example,
$(v:D) is the directory path for the variable $(v). See table below.

Variable expansion in a rule's actions is similar to variable expansion in statements, except that the action string is tokenized at whitespace regardless of quoting.

The result of a token after variable expansion is the product of the components of the token, where each component is a literal substring or a list substituting a variable reference. For example:


$(X) -> a b c
t$(X) -> ta tb tc
$(X)z -> az bz cz
$(X)-$(X) -> a-a a-b a-c b-a b-b b-c c-a c-b c-c

The variable name and modifiers can themselves contain a variable reference:

$(X) -> a b c
$(Y) -> 1 2
$(Z) -> X Y
$($(Z)) -> a b c 1 2

If any variable reference in a token is undefined, the result of the expansion is an empty list. If any variable element is a null string, the result propagates the non-null elements:

$(X) -> a ""
$(Y) -> "" 1
$(Z) ->
*$(X)$(Y)* -> *a* *a1* ** *1*
*$(X)$(Z)* ->

A variable element's string value can be parsed into grist and filename-related components. Modifiers to a variable are used to select elements, select components, and replace components.

Variable Modifiers

[n] Select element number n (starting at 1). If the variable contains fewer than n elements, the result is a zero-element list.
[n-m] Select elements number n through m.
[n-] Select elements number n through the last.
:chars Select the components listed in chars.
:B Select filename base.
:B=base Replace the base part of file name with base
:D Select directory path.
:D=path Replace directory with path.
:E=value Use value instead if the variable is unset.
:G Select grist.
:G=grist Replace grist with grist.
:J=joinval Concatenate list elements into single element, separated by joinval.
:L Replace uppercase characters with lowercase.
:M Select archive member name.
:M=mem Replace the archive member name with mem.
:P Select parent directory.
:R=root Prepend root to the whole file name, if not already rooted.
:S Select (last) filename suffix.
:S=suf Replace the suffix of file name with suf.
:U Replace lowercase characters with uppercase.

$(var:P) is the parent directory of $(var:D).

Built-in Rules

Jam has twelve built-in rules, all of which are pure procedure rules without updating actions. They are in three groups: the first builds the dependency graph; the second modifies it; and the third are just utility rules.

Dependency Building

Depends targets1 : targets2 ;
Builds a direct dependency: makes each of targets1 depend on each of targets2. Generally, targets1 will be rebuilt if targets2 are themselves rebuilt or are newer than targets1.

Includes targets1 : targets2 ;
Builds a sibling dependency. Makes any target that depends on any of targets1 also depend on each of targets2. This reflects the dependencies that arise when one source file includes another. The object built from the source file depends both on the original and included source file, but the two sources files don't depend on each other. For example:

Depends foo.o : foo.c ;
Includes foo.c : goo.c ;

"foo.o" depends on "foo.c" and "goo.c" in this example.

Modifying Binding

The six rules Always, Leaves, NoCare, NotFile, NoUpdate, and Temporary modify the dependency graph so that jam treats the targets differently during its target binding phase. See Binding above. Normally, jam updates a target if it is missing, if its filesystem modification time is older than any of its dependencies (recursively), or if any of its dependencies are being updated. This basic behavior can be changed by invoking utility rules:

Utility Rules
The remaining rules are utility rules.


Echo args ;
Blurts out the message args to stdout.
Exit args ;
Blurts out the message args to stdout and then exits with a failure status.

Glob directories : patterns ;
Scans directories for files matching patterns, returning the list of matching files (with directory prepended). patterns uses the same syntax as in the switch statement. Only useful within the [ ] construct, to change the result into a list.

Match regexps : list ;
Matches the egrep(1) style regular expressions regexps against the strings in list. The result is the concatenation of matching () subexpressions for each string in list, and for each regular expression in regexps. Only useful within the [ ] construct, to change the result into a list.

Built-in Variables

This section discusses variables that have special meaning to jam. By convention, variables names are in CAPS.

SEARCH and LOCATE Variables

These two variables control the binding of file target names to locations in the file system. Generally, $(SEARCH) is used to find existing sources while $(LOCATE) is used to fix the location for built targets.

Rooted (absolute path) file targets are bound as is. Unrooted file target names are also normally bound as is, and thus relative to the current directory, but the settings of $(LOCATE) and $(SEARCH) alter this:

Both $(SEARCH) and $(LOCATE) should be set target-specific and not globally. If they were set globally, jam would use the same paths for all file binding, which is not likely to produce sane results. When writing your own rules, especially ones not built upon those in Jambase, you may need to set $(SEARCH) or $(LOCATE) directly. Almost all of the rules defined in Jambase set $(SEARCH) and $(LOCATE) to sensible values for sources they are looking for and targets they create, respectively.

HDRSCAN, HDRRULE and HDRGRIST Variables

These two variable control header file scanning. $(HDRSCAN) is an egrep(1) pattern, with ()'s surrounding the file name, used to find file inclusion statements in source files. Jambase uses $(HDRPATTERN) as the pattern for $(HDRSCAN). $(HDRRULE) is the name of a rule to invoke with the results of the scan: the scanned file is the target, the found files are the sources. $(HDRRULE) is run under the influence of the scanned file's target-specific variables.

Both $(HDRSCAN) and $(HDRRULE) must be set for header file scanning to take place, and they should be set target-specific and not globally. If they were set globally, all files, including executables and libraries, would be scanned for header file include statements.

The scanning for header file inclusions is not exact, but it is at least dynamic, so there is no need to run something like makedepend(GNU) to create a static dependency file. The scanning mechanism errs on the side of inclusion (i.e., it is more likely to return filenames that are not actually used by the compiler than to miss include files) because it can't tell if #include lines are inside #ifdefs or other conditional logic. In Jambase, HdrRule applies the NOCARE rule to each header file found during scanning so that if the file isn't present yet doesn't cause the compilation to fail, jam won't care.

Also, scanning for regular expressions only works where the included file name is literally in the source file. It can't handle languages that allow including files using variable names (as the Jam language itself does).

Platform Identifier Variables

A number of Jam built-in variables can be used to identify runtime platform:

OS OS identifier string
OSPLAT Underlying architecture, when applicable
NT true on NT platform
AIX true on AIX platform (see also OSVER)
HPUX true on HPUX platform
SOLARIS true on Solaris platform
UNIX true on Unix platforms

Jam Version Variables

JAMDATE Time and date at jam start-up.
JAMUNAME Output of uname(1) command (Unix only)
JAMVERSION jam version, as reported by jam -v.
JAMUSER username that invoked jam.

JAMSHELL Variable

When jam executes a rule's action block, it forks and execs a shell, passing the action block as an argument to the shell. The invocation of the shell can be controlled by $(JAMSHELL). The default on Unix is, for example:

JAMSHELL = "/bin/sh -c %" ;

The % is replaced with the text of the action block.

Jam does not directly support building in parallel across multiple hosts, since that is heavily dependent on the local environment. To build in parallel across multiple hosts, you need to write your own shell that provides access to the multiple hosts. You then reset $(JAMSHELL) to reference it.

Just as jam expands a % to be the text of the rule's action block, it expands a ! to be the multi-process slot number. The slot number varies between 1 and the number of concurrent jobs permitted by the -j flag given on the command line. Armed with this, it is possible to write a multiple host shell. For example:


#!/bin/sh

# This sample JAMSHELL uses the SunOS on(1) command to execute a
# command string with an identical environment on another host.

# Set JAMSHELL = jamshell ! %
#
# where jamshell is the name of this shell file.
#
# This version handles up to -j6; after that they get executed
# locally.

case $1 in
1|4) on winken sh -c "$2";;
2|5) on blinken sh -c "$2";;
3|6) on nod sh -c "$2";;
*) eval "$2";;
esac

DIAGNOSTICS

In addition to generic error messages, jam may emit one of the following:

warning: unknown rule X
A rule was invoked that has not been defined with an "actions" or "rule" statement.

using N temp target(s)
Targets marked as being temporary (but nonetheless present) have been found.

updating N target(s)
Targets are out-of-date and will be updated.

can't find N target(s)
Source files can't be found and there are no actions to create them.

can't make N target(s)
Due to sources not being found, other targets cannot be made.

warning: X depends on itself
A target depends on itself either directly or through its sources.

don't know how to make X
A target is not present and no actions have been defined to create it.

X skipped for lack of Y
A source failed to build, and thus a target cannot be built.

warning: using independent target X
A target that is not a dependency of any other target is being referenced with $(<) or $(>).

X removed
Jam removed a partially built target after being interrupted.

BUGS, LIMITATIONS

The -j flag can cause jam to get confused when single actions update more than one target at a time. jam may proceed as if the targets were built even though they are still under construction.

For parallel building to be successful, the dependencies among files must be properly spelled out, as targets tend to get built in a quickest-first ordering. Also, beware of un-parallelizable commands that drop fixed-named files into the current directory, like yacc(1) does.

With the -j flag, errors from failed commands can get staggeringly mixed up.

A poorly set $(JAMSHELL) is likely to result in silent failure.

SEE ALSO

Jam documentation and source are available from the Perforce Public Depot.
Siebel development on sdch70a014: /vol1/users/ddunbar/Jam

AUTHOR

Jam's author is Christopher Seiwald (seiwald@perforce.com).
Siebel modifications by Dick Dunbar (Dick.Dunbar@Siebel.com) 2004


Appendix A: Relationship to make

AIX make flags:

make Command

Purpose

Maintains, updates, and regenerates groups of programs.

Syntax

make [ -DVariable ] [ -d Option] ] [ -e ] [ -i ] [ -k ] [ -n ] [ -p ] [ -q ] [
-r ] [ -S ] [ -s ] [ -t ] [ -f MakeFile ... ] [ Target ... ]

$<
Represents either the full name of a prerequisite that made a target
out-of-date (inference rule), or the full name of a target (.DEFAULT rule).

$*
Represents the file name section of a prerequisite that made a target
out-of-date (in an inference rule) without a suffix.

$@
Represents the full target name of the current target or the archive file name
part of the library archive target.

$%
Represents a library member in a target rule if the target is a member of the
archive library.

You can also use these local variables appended with D or F:

D
Indicates that the local variable applies to the directory part of the name.
This is the path name prefix without a trailing / (slash). For current
directories, D is a . (period).

F
Indicates that the local variable applies to the file name part of the name.

In addition, the make command sets or knows about the following variables:

$ A single $ (dollar sign); that is, $$ expands to a single dollar sign.
Flags

-DVariable Sets the value of Variable to 1.
-dOption Displays detailed information ...
A
Displays all possible debug information.

a
Displays debug information about archive searching and caching.

d
Displays debug information about directory searching.

g1
Displays debug information about input graph before making anything.

g2
Displays debug information about input graph after making everything, or
before exiting on an error.

m
Displays debug information about making targets, including modification dates.

s
Displays debug information about suffix searching.

v
Displays debug information about variable assignments.

-e Specifies that environmental variables override macro assignments within
makefiles.

-f MakeFile Specifies a makefile to read instead of the default makefile. If
MakeFile is - (dash), standard input is read. Multiple makefiles can be
specified and are read in the order specified.

-i Ignores nonzero exit of shell commands in the makefile. Equivalent to
specifying - (dash) before each command line in the makefile.

-k Continues processing after errors are encountered, but only on those targets
that do not depend on the target whose creation caused the error.

-n Displays commands, but does not run them. However, lines beginning with a +
(plus sign) are executed.

-p Displays the complete set of macro definitions and target descriptions before
performing any commands.
-q Returns a zero status code if the target file is up-to-date; returns a one
status code if the target file is not up-to-date. However, a command line with
the + (plus sign) prefix will be executed.

-r Does not use the default rules.

-S Terminates the make command if an error occurs. This is the default and the
opposite of -k flag.

-s Does not display commands on the screen as they are performed.

-t Creates a target or updates its modification time to make it appear
up-to-date. Executes command lines beginning with a + (plus) sign.

Target Specifies a target name of the form Target or sets the value of
variables.

Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.