JamPlus manual
|
Jam has four phases of operation: start-up, parsing, binding, and updating.
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 Windows and ":"
for Unix).
To set a variable's value on the command line, overriding the variable's environment value, use a KEY=VALUE
syntax.
(To see variable assignments made during jam's execution, use the -d+7
option.)
In the parsing phase, Jam reads and executes the Jambase.jam
file. It finds a Jambase.jam
file by looking for one in the current working directory. If the Jambase.jam
is not found in the current directory, the Jambase.jam
sitting side-by-side with or one level up from the Jam executable is read in.
The Jambase
file is written in the Jam Language. The last action of the Jambase
is to read (via the "include" rule) a user-provided file called "Jamfile.jam
".
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 Rules document for information.
parsing, Jam recursively descends the dependency graph and binds every file target with a location in the filesystem.
Any string value in Jam can represent a target, and it does so if the Depends, Includes, or Needs 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 $(BINDING), $(SEARCH), and $(LOCATE) special variables. See BINDING, SEARCH, and LOCATE Variables. 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 $(BINDING), $(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.
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, md5 command line flags have changed, 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.
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 (or whatever is appropriate for other file formats). 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 Header Scanning Variables.
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.
Jam has a 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.
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 a updating actions is treated as a single string. A backslash () can escape a double quote, or any single whitespace character. Both a newline and a tab must be represented physically within quotes. There is no backslash escape for them. \b Jam requires whitespace (blanks, tabs, or newlines) to surround all tokens, <b>including the colon (:) and semicolon (;) tokens</b>. If a colon or semicolon is found and is not surrounded by whitespace, an error is raised unless the colon or semicolon and surrounding content is in double quotes. @code # Parses successfully. MyRule arg1 : arg2 : arg3 ; # Does not parse due to the colon at the end of Error. Echo Error: This won't work! ; # Parses successfully. Echo "Error: This works fine!" ; \endcode \b 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. @subsection language_datatype Datatype <b>Jam</b>'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. @code variableName = hello ; listOfStrings = hello hi bonjour hola! "how are you?" "i am fine." ; \endcode @subsection language_rules Rules The basic \b Jam language entity is called a rule. A rule is simply a procedure definition, with a body of \b Jam statements to be run when the rule is invoked. The syntax of rule invocation make 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 ]. Rule names can be expanded in place using the same techniques as described in \ref language_variable_expansion. @code FLAG = Dirty ; # or Clean rule MarkDirty { } rule MarkClean { } # Calls MarkDirty Mark$(FLAG) ; \endcode @subsection language_updating_actions 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, those actions are added to those associated with its built targets (\$(1)) before the rule's procedure is run. Later, to build the targets in the updating phase, the actions are passed to the OS command shell, with \$(1) and \$(2) replaced by bound versions of the target names. See \ref operation_binding above. @subsection language_statements Statements @anchor actions_autosettings @anchor actions_lua @anchor actions_removeemptydirs @anchor actions_screenoutput <tt>Jam</tt>'s language has the following statements: @htmlonly <blockquote> \endhtmlonly <tt><i>rulename</i> <i>field1</i> : <i>field2</i> : ... : <i>fieldN</i> ;</tt> @htmlonly <blockquote> \endhtmlonly Invoke a rule. A rule is invoked with values in \em field1 through \em fieldN (9 max). They may be referenced in the procedure's \em statements as $(1) through $(<9>N). $(<) and $(>) are synonymous with $(1) and $(2). \em rulename undergoes \ref language_variable_expansion. If the resulting list is more than one value, each rule is invoked with the same arguments, and the result of the invocation is the concatenation of all the results. @htmlonly </blockquote> \endhtmlonly <tt>actions [ <i>modifiers</i> ] <i>rulename</i> { <i>commands</i> }</tt> @htmlonly <blockquote> \endhtmlonly Define a rule's updating actions, replacing any previous definition. The first two arguments may be referenced in the action's \em commands as $(1) and $(2) or $(<) and $(>). Normally, the settings from $(1) are made active during the run of the action. Sometimes, it is useful to make additional settings available. If a third optional argument is provided, the settings assigned to the third target are activated during the action. $(1)'s settings take precedence over the third argument. Example: @code # tests/autosettings the_echo on myshell = echo ; actions DoEcho { echo $(the_echo) $(the_string) hello everyone } # the_echo on myshell = echo # the_string = # # Prints: echo hello everyone DoEcho all : : myshell ; # the_echo on myshell = echo # the_string = *********** # # Prints: echo *********** hello everyone Depends all : all2 ; the_string on all2 = *********** ; DoEcho all2 : : myshell ; # the_echo on myshell = echo # the_echo on all3 = ===== # the_string = # # Prints: ===== hello everyone Depends all : all3 ; the_echo on all3 = "=====" ; DoEcho all3 : : myshell ;
The following action modifiers are understood:
actions bind vars (deprecated) | $(vars) will be replaced with bound values. The preferred way to expand a bound value in JamPlus is to use the :T variable expansion modifier like so: $(vars:T) |
actions existing | $(>) includes only source targets currently existing. |
actions ignore | The return status of the commands is ignored. |
actions lua | Flags this action contains embedded Lua script that is executed in a thread local to the running Jam process. For more information, see Using Lua in Actions. |
actions maxtargets # | When batching files through the action, using maxtargets limits the number of source files passed to the action's command each time. |
actions piecemeal | commands are repeatedly invoked with a subset of $(>) small enough to fit in the command buffer on this OS. |
actions quietly | The action is not echoed to the standard output. |
actions removeemptydirs | Although useful in other circumstances, removeemptydirs is primarily intended to be used with the various Clean actions. For any sources sent to an action using removeemptydirs , any empty directories associated with the source target location are removed. |
actions response | Enables automatically generated response files. Response files store text surrounded by actions response C++
{
$(C++) @@($(2))
}
It is valid to nest the generation of response files. In the example below, the file list is written to a temporary response file and the filename is inserted in the place of actions response C++
{
$(C++) @@(-filelist @($(2)))
}
Note that Additionally, the actions C++
{
$(C++) @^^^(-filelist @($(2)))
}
|
actions screenoutput | Normally, actions collect all output before displaying it to the user in order to avoid interleaving the output from different processes. 'screenoutput' may be used to display the output as it happens. It will be more difficult to follow multiprocess output, but during some long running actions, the user may need faster visual response. |
actions together | The $(>) from multiple invocations of the same action on the same built target are concatenated together. |
actions updated | $(>) includes only source targets themselves marked for updating. |
Two other sets of symbols are understood within the body of the action.
The first is used to write a file to disk based on the contents of an available variable.
The second is used to write a response file to disk. Response files store text surrounded by ^^^(text...)
into a temporary response file. The ^^^(text)
in an action is replaced with the full path to the temporary response file. The response file is deleted when the action completes.
It is valid to nest the generation of response files. In the example below, the file list is written to a temporary response file and the filename is inserted in the place of ^^^($(2))
. In a secondary response file, the -filelist
parameter and the first response filename are added. This response filename is then passed to the C++ compiler.
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:
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
logical and cond || cond
logical or ( cond )
precedence grouping
include file ;
Causes Jam to read the named file. The file is bound like a regular target (see Binding Phase above) but unlike a regular target, the include file cannot be built. Marking an include file target with the rule NoCare targets ; 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.
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).