diff --git a/src/engine/readme.html b/src/engine/readme.html index 967cc883b..f600afc5b 100644 --- a/src/engine/readme.html +++ b/src/engine/readme.html @@ -3,24 +3,21 @@
- - + +|
- |
Boost.Jam@@ -36,13 +33,57 @@
Introduction-Boost.Jam (BJam) is a build tool based on FTJam, which - in turn is based on Perforce Jam. It contains significant - improvements made to facilitate its use in the Boost Build - System, but should be backward compatible with Perforce - Jam. +Boost.Jam (BJam) is a build tool based on FTJam, which in turn + is based on Perforce Jam. It contains significant improvements made to + facilitate its use in the Boost Build System, but should be backward + compatible with Perforce Jam. This is version 3.1.3 of BJam and is based on version 2.4 of Jam/MR: @@ -56,77 +97,65 @@ are clearly marked. ALL WARRANTIES ARE HEREBY DISCLAIMED. Features-Jam is a make(1) replacement that makes building simple - things simple and building complicated things manageable. -Jam's language is expressive, making Jamfiles (c.f. - Makefiles) compact. Here's a sample: +Jam is a make(1) replacement that makes building simple things simple + and building complicated things manageable. +Jam's language is expressive, making Jamfiles (c.f. Makefiles) + compact. Here's a sample:
Main smail : main.c map.c resolve.c deliver.c
misc.c parser.y alias.c pw.c headers.c
scanner.l getpath.c str.c ;
- This builds "smail" from a dozen source files. Jam - handles header file dependencies automatically and - on-the-fly. -Jam is very portable: it runs on UNIX, VMS, Mac, and NT. - Most Jamfiles themselves are portable, like the sample - above. -Jam is unintrusive: it is small, it has negligible CPU - overhead, and it doesn't create any of its own funny files - (c.f. Odin, nmake, SunOS make). -Jam can build large projects spread across many directories - in one pass, without recursing, tracking the relationships - among all files. Jam can do this with multiple, concurrent - processes. -Jam isn't under the blinkin GNU copyright, so you can - incorporate it into commercial products. +This builds "smail" from a dozen source files. Jam handles + header file dependencies automatically and on-the-fly. +Jam is very portable: it runs on UNIX, VMS, Mac, and NT. Most Jamfiles + themselves are portable, like the sample above. +Jam is unintrusive: it is small, it has negligible CPU overhead, and + it doesn't create any of its own funny files (c.f. Odin, nmake, SunOS + make). +Jam can build large projects spread across many directories in one + pass, without recursing, tracking the relationships among all files. Jam + can do this with multiple, concurrent processes. +Jam isn't under the blinkin GNU copyright, so you can incorporate it + into commercial products. Contents-
Installing-
Installing BJam after building it is simply a matter of copying the + generated executables someplace in your PATH. For building the + executables there are a set of build bootstrap scripts to + accomodate particular environments. The scripts take one optional + argument, the name of the toolset to build with. When the toolset is not + given an attempt is made to detect an available toolset and use that. The + build scripts accept these areguments: <build script name> [toolset]- Running the scripts without arguments will give you the best - chance of success. On Windows platforms from a command console - do: +Running the scripts without arguments will give you the best chance of + success. On Windows platforms from a command console do: cd <jam source location> .\build.bat @@ -136,137 +165,562 @@ cd <jam source location> cd <jam source location> sh ./build.sh- If the scripts fail to detect an appropriate toolset to - build with your particular toolset may not be auto-detectable. - In that case, you can specify the toolset as the first - argument, this assumes that the toolset is readily available in - the PATH. The supported toolsets, and wether they are - auto-detected, are: -
The built executables are placed in a subdirectory specific - to your platform. For example, in Linux running on an Intel x86 - compatible chip, the executables are placed in: - "bin.linuxx86". There are two executables generated: - jam[.exe], and bjam[.exe], both are the same - binary but with different names. The "jam" invocation is used - for compatability with the Perforce Jam/MR functionality, - whereas "bjam" is used for the extended Boost.Build - functionality. -The build scripts support additional invocation - arguments for use by developers of Boost.Jam. The extra - arguments come after the toolset, and can take the form of - "--options" or targets for the build.jam - script: +The built executables are placed in a subdirectory specific to your + platform. For example, in Linux running on an Intel x86 compatible chip, + the executables are placed in: "bin.linuxx86". There are two + executables generated: jam[.exe], and bjam[.exe], both + are the same binary but with different names. The "jam" invocation is + used for compatability with the Perforce Jam/MR functionality, whereas + "bjam" is used for the extended Boost.Build functionality. +The build scripts support additional invocation arguments for + use by developers of Boost.Jam. The extra arguments come after the + toolset, and can take the form of "--options" or targets for the + build.jam script: <build script name> [toolset] [--options* [targets]*]- There is current only one available option, - "--debug", which builds debugging versions of the - executable. When built they are placed in their own directory - "bin.<platform>.debug". -Currently there are two targets supported: dist, - and clean. Respectively they: generate packages - (compressed archives) as appropriate for distribution in the - platform, or remove all the built executables and objects. +There is current only one available option, "--debug", which + builds debugging versions of the executable. When built they are placed + in their own directory "bin.<platform>.debug". +Currently there are two targets supported: dist, and + clean. Respectively they: generate packages (compressed + archives) as appropriate for distribution in the platform, or remove all + the built executables and objects. +Core Jam Extensions+A number of enhancements have been made to the core language of + Classic Jam. These changes were aimed primarily at making it easier to + manage the complexity of a large system such as Boost.Build. +Command-line and Environment Variable + Quoting+Classic Jam had an odd behavior with + respect to command-line variable ( -s...) and environment + variable settings which made it impossible to define an arbitrary + variable with spaces in the value. Boost Jam remedies that by treating + all such settings as a single string if they are surrounded by + double-quotes. Uses of this feature can look interesting, since shells + require quotes to keep characters separated by whitespace from being + treated as separate arguments: ++jam -sMSVCNT="\"\"C:\Program Files\Microsoft Visual C++\VC98\"\"" ... ++ The outer quote is for the shell. The middle quote is for Jam, to tell + it to take everything within those quotes literally, and the inner quotes + are for the shell again when paths are passed as arguments to build + actions. Under NT, it looks a lot more sane to use environment variables + before invoking jam when you have to do this sort of quoting: ++set MSVCNT=""C:\Program Files\Microsoft Visual C++\VC98\"" ++ Startup Behavior+The Boost.Build v2 initialization behavior has been implemented. This
+ behavior only applies when the executable being invoked is called
+ "
Rule Indirection+Boost Jam allows you to call a rule whose name is held in a variable + or computed as the result of an expression: +
+x = foo ;
+rule foobar { ECHO foobar ; } # a trivial rule
+$(x)bar ; # invokes foobar
+
+ Furthermore, if the first expression expands to more than one list + item, everything after the first item becomes part of the first argument. + This allows a crude form of argument binding: +
+# return the elements of sequence for which predicate returns non-nil
+rule filter ( sequence * : predicate + )
+{
+ local result ;
+ for local x in $(sequence)
+ {
+ if [ $(predicate) $(x) ] { result += $(x); }
+ }
+ return $(result);
+}
+# true iff x == y
+rule equal ( x y )
+{
+ if $(x) = $(y) { return true; }
+}
+# bind 3 to the first argument of equal
+ECHO [ filter 1 2 3 4 5 4 3 : equal 3 ] ; # prints "3 3"
+
+ Argument lists+You can now describe the arguments accepted by a rule, and refer to + them by name within the rule. For example, the following prints ``I'm + sorry, Dave'' to the console: +
+rule report ( pronoun index ? : state : names + )
+{
+ local he.suffix she.suffix it.suffix = s ;
+ local I.suffix = m ;
+ local they.suffix you.suffix = re ;
+ ECHO $(pronoun)'$($(pronoun).suffix) $(state), $(names[$(index)]) ;
+}
+report I 2 : sorry : Joe Dave Pete ;
+
+ Each name in a list of formal arguments (separated by ``:'' + in the rule declaration) is bound to a single element of the + corresponding actual argument unless followed by one of these + modifiers: +
The actual and formal arguments are checked for inconsistencies, which + cause Jam to exit with an error code: ++### argument error +# rule report ( pronoun index ? : state : names + ) +# called with: ( I 2 foo : sorry : Joe Dave Pete ) +# extra argument foo +### argument error +# rule report ( pronoun index ? : state : names + ) +# called with: ( I 2 : sorry ) +# missing argument names ++ If you omit the list of formal arguments, all checking is bypassed as + in ``classic'' Jam. Argument lists drastically improve the reliability + and readability of your rules, however, and are strongly + recommended for any new Jam code you write. +Module Support+Boost Jam introduces support for modules, which provide some + rudimentary namespace protection for rules and variables. A new keyword, + ``module'' was also introduced. The features described in this + section are primitives, meaning that they are meant to provide the + operations needed to write Jam rules which provide a more elegant module + interface. +Declaration+
+module expression { ... }
+
+ Code within the { ... } executes within + the module named by evaluating expression. Rule definitions can be + found in the module's own namespace, and in the namespace of the global + module as module-name.rule-name, so within a + module, other rules in that module may always be invoked without + qualification: +
+module my_module
+{
+ rule salute ( x ) { ECHO $(x), world ; }
+ rule greet ( ) { salute hello ; }
+ greet ;
+}
+my_module.salute goodbye ;
+
+ When an invoked rule is not found in the current module's namespace, + it is looked up in the namespace of the global module, so qualified calls + work across modules: +
+module your_module
+{
+ rule bedtime ( ) { my_module.salute goodnight ; }
+}
+
+ Variable Scope+Each module has its own set of dynamically nested variable scopes. + When execution passes from module A to module B, all the variable + bindings from A become unavailable, and are replaced by the bindings that + belong to B. This applies equally to local and global variables: +
+module A
+{
+ x = 1 ;
+ rule f ( )
+ {
+ local y = 999 ; # becomes visible again when B.f calls A.g
+ B.f ;
+ }
+ rule g ( )
+ {
+ ECHO $(y) ; # prints "999"
+ }
+}
+module B
+{
+ y = 2 ;
+ rule f ( )
+ {
+ ECHO $(y) ; # always prints "2"
+ A.g ;
+ }
+}
+
+ The only way to access another module's variables is by entering that + module: +
+rule peek ( module-name ? : variables + )
+{
+ module $(module-name)
+ {
+ return $($(>)) ;
+ }
+}
+
+ Note that because existing variable bindings change whenever a new module
+ scope is entered, argument bindings become unavailable. That explains the
+ use of "$(>)" in the peek rule above.
+ Local Rules++local rule rulename... ++ The rule is declared locally to the current module. It is not entered + in the global module with qualification, and its name will not appear in + the result of: ++[ RULENAMES module-name ] ++ The RULENAMES Rule++rule RULENAMES ( module ? ) ++ Returns a list of the names of all non-local rules in the given + module. If module is omitted, the names of all non-local rules + in the global module are returned. +The IMPORT Rule+IMPORT allows rule name aliasing across modules: ++rule IMPORT ( source_module ? : source_rules * + : target_module ? : target_rules * ) ++ The IMPORT rule copies rules from the source_module + into the target_module as local rules. If either + source_module or target_module is not supplied, it + refers to the global module. source_rules specifies which rules + from the source_module to import; TARGET_RULES + specifies the names to give those rules in target_module. If + source_rules contains a name which doesn't correspond to a rule + in source_module, or if it contains a different number of items + than target_rules, an error is issued. For example, ++# import m1.rule1 into m2 as local rule m1-rule1. +IMPORT m1 : rule1 : m2 : m1-rule1 ; +# import all non-local rules from m1 into m2 +IMPORT m1 : [ RULENAMES m1 ] : m2 : [ RULENAMES m1 ] ; ++ The EXPORT Rule+EXPORT allows rule name aliasing across modules: ++rule EXPORT ( module ? : rules * ) ++ The EXPORT rule marks rules from the + source_module as non-local (and thus exportable). If an element + of rules does not name a rule in module, an error is + issued. For example, +
+module X {
+ local rule r { ECHO X.r ; }
+}
+IMPORT X : r : : r ; # error - r is local in X
+EXPORT X : r ;
+IMPORT X : r : : r ; # OK.
+
+ The CALLER_MODULE Rule++rule CALLER_MODULE ( levels ? ) ++ CALLER_MODULE returns the name of the module scope enclosing + the call to its caller (if levels is supplied, it is interpreted as an + integer number of additional levels of call stack to traverse to locate + the module). If the scope belongs to the global module, or if no such + module exists, returns the empty list. For example, the following prints + "{Y} {X}": +
+module X {
+ rule get-caller { return [ CALLER_MODULE ] ; }
+ rule get-caller's-caller { return [ CALLER_MODULE 1 ] ; }
+ rule call-Y { return Y.call-X2 ; }
+}
+module Y {
+ rule call-X { return X.get-caller ; }
+ rule call-X2 { return X.get-caller's-caller ; }
+}
+callers = [ X.get-caller ] [ Y.call-X ] [ X.call-Y ] ;
+ECHO {$(callers)} ;
+
+ Local For Loop Variables+Boost Jam allows you to declare a local for loop control + variable right in the loop: +
+x = 1 2 3 ;
+y = 4 5 6 ;
+for local y in $(x)
+{
+ ECHO $(y) ; # prints "1", "2", or "3"
+}
+ECHO $(y) ; # prints "4 5 6"
+
+ Negative Indexing+Classic Jam supplies 1-based list indexing, and slicing on a closed + (inclusive) range: ++x = 1 2 3 4 5 ; +ECHO $(x[3]) ; # prints "3" +ECHO $(x[2-4]) ; # prints "2 3 4" +ECHO $(x[2-]) ; # prints "2 3 4 5" ++ Boost Jam adds Python-style negative indexing to access locations + relative to the end of the list. ++ECHO $(x[-1]) $(x[-3]) ; # prints "5 3" +ECHO $(x[-3--1]) ; # prints "3 4 5" +ECHO $(x[-3-4]) ; # prints "3 4" +ECHO $(x[2--2]) ; # prints "2 3 4" ++ Consistency with the 1-based, inclusive indexing of Classic Jam and + the use of ``-'' as the range separator make this feature a bit + clumsier than it would otherwise need to be, but it does work. +Target Binding Detection+Whenever a target is bound to a location in the + filesystem, Boost Jam will look for a variable called BINDRULE + (first ``on'' the target being bound, then in the global + module). If non-empty, $(BINDRULE[1]) names a rule which is + called with the name of the target and the path it is being bound to. The + signature of the rule named by $(BINDRULE[1]) should match the + following: ++rule bind-rule ( target : path ) ++ This facility is useful for correct header file scanning, since many + compilers will search for #included files first in the directory + containing the file doing the #include directive. + $(BINDRULE) can be used to make a record of that directory. +Return Code Inversion+For handling targets whose build actions are expected to fail (e.g. + when testing that assertions or compile-time type checkin work properly), + Boost Jam supplies a FAIL_EXPECTED rule in the same style as + NOCARE, et. al. During target updating, the return code of the + build actions for arguments to FAIL_EXPECTED is inverted: if it + fails, building of dependent targets continues as though it succeeded. If + it succeeds, dependent targets are skipped. +Ignoring Return Codes+Perforce Jam supplied a NOCARE rule which is typically used + for header files to indicate that if they are not found, the dependent + targets should be built anyway. Boost Jam extends NOCARE to + apply to targets with build actions: if their build actions exit with a + nonzero return code, dependent targets will still be built. +Removing Outdated Targets++rule RMOLD ( targets * ) ++ Perforce Jam removes any target files that may exist on disk when the
+ rule used to build those targets fails. However, targets whose
+ dependencies fail to build are not removed by default. The
+ The SUBST Rule+Note: the The behavior of the SUBST rule for regular-expression + matching and replacement (originally added in FTJam) has been + modified: +
The JAM_VERSION global + variable+A predefined global variable with two elements indicates the version + number of Boost Jam. Boost Jam versions start at "03" "00". + Earlier versions of Jam do not automatically define + JAM_VERSION. +Debugging Support+The BACKTRACE rule++rule BACKTRACE ( ) ++ Returns a list of quadruples: filename line module rulename..., + describing each shallower level of the call stack. This rule can be used + to generate useful diagnostic messages from Jam rules. +The -d command-line option admits new arguments: +
The UPDATE rule and changes to command line + handling+Classic jam treats any non-option element of command line as a name of + target to be updated. This prevented more sophisticated handling of + command line and was disabled. Instead of it, a new UPDATE + builtin rule was added: ++rule UPDATE ( targets * ) ++ The rule causes the specified targets to be updated. If no target was + specified with the UPDATE rule, the "all" target will be + implicitly updated. Revised - 12 November, 2002 + 15 November, 2002 -© Copyright René Rivera 2002. All - Rights Reserved. +© Copyright René + Rivera, David Abrahams 2002. All Rights Reserved. Permission to + copy, use, modify, sell and distribute this document is granted provided + this copyright notice appears in all copies. This document is provided + "as is" without express or implied warranty, and with no claim as to its + suitability for any purpose. |