summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 11:05:34 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 11:06:28 +0900
commit34bd32e225e2a8a94104489b31c42e5801cc1f4a (patch)
treed021b579a0c190354819974e1eaf0baa54b551f3 /tools
parentf763a99a501650eff2c60288aa6f10ef916d769e (diff)
downloadboost-34bd32e225e2a8a94104489b31c42e5801cc1f4a.tar.gz
boost-34bd32e225e2a8a94104489b31c42e5801cc1f4a.tar.bz2
boost-34bd32e225e2a8a94104489b31c42e5801cc1f4a.zip
Imported Upstream version 1.63.0upstream/1.63.0
Change-Id: Iac85556a04b7e58d63ba636dedb0986e3555714a Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/boostbook/test/Jamfile.v22
-rwxr-xr-xtools/boostbook/test/more/run-tests.py2
-rw-r--r--tools/boostbook/test/more/tests/libs/array.gold24
-rw-r--r--tools/boostbook/test/more/tests/libs/hash-ref.gold108
-rw-r--r--tools/boostbook/test/more/tests/libs/unordered-ref.gold48
-rw-r--r--tools/boostbook/xsl/navbar.xsl72
-rw-r--r--tools/boostdep/depinst/depinst.py202
-rw-r--r--tools/boostdep/depinst/exceptions.txt397
-rw-r--r--tools/boostdep/doc/html/index.html18
-rw-r--r--tools/boostdep/doc/src/boostdep.qbk11
-rw-r--r--tools/boostdep/src/boostdep.cpp305
-rw-r--r--tools/build/CONTRIBUTING.rst161
-rw-r--r--tools/build/README.rst6
-rw-r--r--tools/build/doc/bin/gcc-4.8/debug/jam_docs.xml3463
-rw-r--r--tools/build/doc/bjam.qbk2
-rw-r--r--tools/build/doc/src/faq.xml2
-rw-r--r--tools/build/doc/src/overview.xml10
-rw-r--r--tools/build/doc/src/reference.xml46
-rw-r--r--tools/build/doc/src/tasks.xml12
-rw-r--r--tools/build/doc/src/tutorial.xml12
-rw-r--r--tools/build/example/complex-testing/compile-fail.cpp17
-rw-r--r--tools/build/example/complex-testing/fail.cpp17
-rw-r--r--tools/build/example/complex-testing/jamroot.jam15
-rw-r--r--tools/build/example/complex-testing/post.cpp17
-rw-r--r--tools/build/example/complex-testing/success.cpp17
-rw-r--r--tools/build/example/time/jamroot.jam13
-rw-r--r--tools/build/example/time/main_cpp.pro1
-rw-r--r--tools/build/example/try_compile/Jamroot.jam29
-rw-r--r--tools/build/example/try_compile/foo.cpp6
-rw-r--r--tools/build/example/try_compile/main.cpp8
-rw-r--r--tools/build/example/user-config.jam2
-rw-r--r--tools/build/index.html3
-rw-r--r--tools/build/notes/hacking.txt138
-rw-r--r--tools/build/src/__init__.py0
-rw-r--r--tools/build/src/build-system.jam10
-rw-r--r--tools/build/src/build/build_request.py2
-rw-r--r--tools/build/src/build/engine.py28
-rw-r--r--tools/build/src/build/errors.py12
-rw-r--r--tools/build/src/build/feature.py280
-rw-r--r--tools/build/src/build/generators.py107
-rw-r--r--tools/build/src/build/project.ann.py996
-rw-r--r--tools/build/src/build/project.py287
-rw-r--r--tools/build/src/build/property.py249
-rw-r--r--tools/build/src/build/property_set.py130
-rw-r--r--tools/build/src/build/scanner.py10
-rw-r--r--tools/build/src/build/targets.py83
-rw-r--r--tools/build/src/build/toolset.py35
-rw-r--r--tools/build/src/build/type.py48
-rw-r--r--tools/build/src/build/version.py6
-rw-r--r--tools/build/src/build/virtual_target.py35
-rw-r--r--tools/build/src/build_system.py207
-rw-r--r--tools/build/src/engine/build.bat27
-rw-r--r--tools/build/src/engine/build.jam7
-rw-r--r--tools/build/src/engine/debug.c45
-rw-r--r--tools/build/src/engine/debug.h29
-rw-r--r--tools/build/src/engine/execunix.c21
-rw-r--r--tools/build/src/engine/filent.c5
-rw-r--r--tools/build/src/engine/function.c227
-rw-r--r--tools/build/src/engine/hash.c2
-rw-r--r--tools/build/src/engine/make1.c14
-rw-r--r--tools/build/src/engine/timestamp.c8
-rw-r--r--tools/build/src/engine/timestamp.h1
-rw-r--r--tools/build/src/exceptions.py65
-rw-r--r--tools/build/src/kernel/bootstrap.jam1
-rw-r--r--tools/build/src/tools/builtin.jam2
-rw-r--r--tools/build/src/tools/builtin.py69
-rw-r--r--tools/build/src/tools/bzip2.jam18
-rw-r--r--tools/build/src/tools/cast.py8
-rw-r--r--tools/build/src/tools/clang.jam2
-rw-r--r--tools/build/src/tools/common.py82
-rw-r--r--tools/build/src/tools/darwin.jam40
-rw-r--r--tools/build/src/tools/doxproc.py14
-rw-r--r--tools/build/src/tools/emscripten.jam112
-rw-r--r--tools/build/src/tools/gcc.py26
-rw-r--r--tools/build/src/tools/intel-win.jam1
-rw-r--r--tools/build/src/tools/mc.py2
-rw-r--r--tools/build/src/tools/message.py18
-rw-r--r--tools/build/src/tools/mpi.jam184
-rw-r--r--tools/build/src/tools/msvc.jam10
-rw-r--r--tools/build/src/tools/msvc.py146
-rw-r--r--tools/build/src/tools/python.jam102
-rw-r--r--tools/build/src/tools/rc.py5
-rw-r--r--tools/build/src/tools/stage.py10
-rw-r--r--tools/build/src/tools/testing-aux.jam2
-rw-r--r--tools/build/src/tools/testing.jam32
-rw-r--r--tools/build/src/tools/testing.py2
-rw-r--r--tools/build/src/tools/types/asm.py2
-rw-r--r--tools/build/src/tools/types/cpp.py76
-rw-r--r--tools/build/src/tools/unix.py9
-rw-r--r--tools/build/src/tools/zlib.jam21
-rw-r--r--tools/build/src/util/option.py2
-rw-r--r--tools/build/src/util/os_j.py5
-rw-r--r--tools/build/src/util/path.py2
-rw-r--r--tools/build/src/util/regex.py11
-rw-r--r--tools/build/src/util/set.py10
-rw-r--r--tools/build/src/util/utility.py35
-rw-r--r--tools/build/test/BoostBuild.py7
-rwxr-xr-xtools/build/test/conditionals_multiple.py2
-rw-r--r--tools/build/test/dependency_property.py7
-rw-r--r--tools/build/test/inherit_toolset.py49
-rwxr-xr-xtools/build/test/scanner_causing_rebuilds.py48
-rwxr-xr-xtools/build/test/source_order.py31
-rwxr-xr-xtools/build/test/test_rc.py38
-rw-r--r--tools/build/test/timedata.py9
-rw-r--r--tools/build/tutorial.html2
105 files changed, 3373 insertions, 6043 deletions
diff --git a/tools/boostbook/test/Jamfile.v2 b/tools/boostbook/test/Jamfile.v2
index 23aff82796..fc72f13bb6 100644
--- a/tools/boostbook/test/Jamfile.v2
+++ b/tools/boostbook/test/Jamfile.v2
@@ -5,7 +5,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
project /boost/boostbook/test ;
-import boostbook : boostbook ;
+using boostbook ;
boostbook alt : alt.xml :
<xsl:param>boost.root=../../../..
diff --git a/tools/boostbook/test/more/run-tests.py b/tools/boostbook/test/more/run-tests.py
index 393e8cc2ed..c91f84c8f9 100755
--- a/tools/boostbook/test/more/run-tests.py
+++ b/tools/boostbook/test/more/run-tests.py
@@ -95,7 +95,7 @@ def normalize_boostbook_ids(doc):
if(match):
# Truncate id name, as it sometimes has different lengths...
match2 = re.match("(.*?)([^.]*?)(_?id)", match.group(1))
- base = match2.group(1) + match2.group(2)[:14] + match2.group(3)
+ base = match2.group(1) + match2.group(2)[:7] + match2.group(3)
count = id_bases[base] + 1
id_bases[base] = count
ids[id] = base + str(count) + match.group(3)
diff --git a/tools/boostbook/test/more/tests/libs/array.gold b/tools/boostbook/test/more/tests/libs/array.gold
index af1935031a..f76ffae620 100644
--- a/tools/boostbook/test/more/tests/libs/array.gold
+++ b/tools/boostbook/test/more/tests/libs/array.gold
@@ -87,13 +87,13 @@
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <link linkend="boost.array.operator!="><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operato_id3"><phrase role="keyword">operator</phrase><phrase role="special">&lt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operato_id4"><phrase role="keyword">operator</phrase><phrase role="special">&gt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase></synopsis>
<refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.array"><refmeta><refentrytitle>Class template array</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::array</refname><refpurpose>STL compliant container wrapper for arrays of constant size</refpurpose></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.array_hpp">boost/array.hpp</link>&gt;
@@ -163,13 +163,13 @@
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <link linkend="boost.array.operator!="><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operato_id3"><phrase role="keyword">operator</phrase><phrase role="special">&lt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><refsect2><title><anchor id="boost.arrayconstruct-copy-destruct"/><computeroutput>array</computeroutput>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operato_id4"><phrase role="keyword">operator</phrase><phrase role="special">&gt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><refsect2><title><anchor id="boost.arrayconstruct-copy-destruct"/><computeroutput>array</computeroutput>
public
construct/copy/destruct</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> U<phrase role="special">&gt;</phrase> array&amp; <anchor id="id1-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> other<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
@@ -220,16 +220,16 @@
<phrase role="keyword">bool</phrase> <anchor id="boost.array.operator!="/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>!(x == y)</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_id1"/><phrase role="keyword">operator</phrase><phrase role="special">&lt;</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operato_id1"/><phrase role="keyword">operator</phrase><phrase role="special">&lt;</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>std::lexicographical_compare(x.<link linkend="id3-bb">begin</link>(), x.<link linkend="id6-bb">end</link>(), y.<link linkend="id3-bb">begin</link>(), y.<link linkend="id6-bb">end</link>())</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_id2"/><phrase role="keyword">operator</phrase><phrase role="special">&gt;</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operato_id2"/><phrase role="keyword">operator</phrase><phrase role="special">&gt;</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>y &lt; x</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">&lt;=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operato_id3"/><phrase role="keyword">operator</phrase><phrase role="special">&lt;=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>!(y &lt; x)</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_=_id2"/><phrase role="keyword">operator</phrase><phrase role="special">&gt;=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operato_id4"/><phrase role="keyword">operator</phrase><phrase role="special">&gt;=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>!(x &lt; y)</computeroutput></simpara></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2></refsect1></refentry>
</section>
diff --git a/tools/boostbook/test/more/tests/libs/hash-ref.gold b/tools/boostbook/test/more/tests/libs/hash-ref.gold
index 6404700c3a..e2a1815705 100644
--- a/tools/boostbook/test/more/tests/libs/hash-ref.gold
+++ b/tools/boostbook/test/more/tests/libs/hash-ref.gold
@@ -13,24 +13,24 @@
</para><synopsis xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash">hash</link><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_bool_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_char_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_signed_ch_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_wchar_t_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_short_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id2">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_int_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id3">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id4">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id5">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_float_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_double_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_doub_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_strin_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_wstri_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_bo_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_ch_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_si_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_wc_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_sh_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id2">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_in_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id3">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id4">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id2">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id5">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_fl_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_do_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id3">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_st_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_st_id2">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_T_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
<phrase role="comment">// <link linkend="id1-bb">Support functions (Boost extension).</link></phrase>
@@ -259,129 +259,129 @@
</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>
Only throws if
<computeroutput><link linkend="boost.hash_value">hash_value</link>(T)</computeroutput> throws.
- </para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_bool_id1"><refmeta><refentrytitle>Struct hash&lt;bool&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;bool&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ </para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_bo_id1"><refmeta><refentrytitle>Struct hash&lt;bool&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;bool&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_bool_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_bo_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id35-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">bool</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id35-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">bool</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_char_id1"><refmeta><refentrytitle>Struct hash&lt;char&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;char&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_ch_id1"><refmeta><refentrytitle>Struct hash&lt;char&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;char&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_char_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_ch_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id36-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id36-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_signed_ch_id1"><refmeta><refentrytitle>Struct hash&lt;signed char&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;signed char&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_si_id1"><refmeta><refentrytitle>Struct hash&lt;signed char&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;signed char&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_signed_ch_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_si_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id37-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id37-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned__id1"><refmeta><refentrytitle>Struct hash&lt;unsigned char&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned char&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_un_id1"><refmeta><refentrytitle>Struct hash&lt;unsigned char&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned char&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id38-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id38-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_wchar_t_id1"><refmeta><refentrytitle>Struct hash&lt;wchar_t&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;wchar_t&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_wc_id1"><refmeta><refentrytitle>Struct hash&lt;wchar_t&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;wchar_t&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_wchar_t_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_wc_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id39-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id39-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">wchar_t</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_short_id1"><refmeta><refentrytitle>Struct hash&lt;short&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;short&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_sh_id1"><refmeta><refentrytitle>Struct hash&lt;short&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;short&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_short_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_sh_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id40-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">short</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id40-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">short</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned__id2"><refmeta><refentrytitle>Struct hash&lt;unsigned short&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned short&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_un_id2"><refmeta><refentrytitle>Struct hash&lt;unsigned short&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned short&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id2">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id2">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id41-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id41-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_int_id1"><refmeta><refentrytitle>Struct hash&lt;int&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;int&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_in_id1"><refmeta><refentrytitle>Struct hash&lt;int&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;int&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_int_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_in_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id42-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id42-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned__id3"><refmeta><refentrytitle>Struct hash&lt;unsigned int&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned int&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_un_id3"><refmeta><refentrytitle>Struct hash&lt;unsigned int&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned int&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id3">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id3">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id43-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id43-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_long_id1"><refmeta><refentrytitle>Struct hash&lt;long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_lo_id1"><refmeta><refentrytitle>Struct hash&lt;long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id44-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">long</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id44-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">long</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned__id4"><refmeta><refentrytitle>Struct hash&lt;unsigned long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_un_id4"><refmeta><refentrytitle>Struct hash&lt;unsigned long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id4">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id4">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id45-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id45-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_long_long_id1"><refmeta><refentrytitle>Struct hash&lt;long long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;long long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_lo_id2"><refmeta><refentrytitle>Struct hash&lt;long long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;long long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id2">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id46-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id46-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned__id5"><refmeta><refentrytitle>Struct hash&lt;unsigned long long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned long long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_un_id5"><refmeta><refentrytitle>Struct hash&lt;unsigned long long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned long long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id5">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id5">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id47-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id47-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_float_id1"><refmeta><refentrytitle>Struct hash&lt;float&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;float&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_fl_id1"><refmeta><refentrytitle>Struct hash&lt;float&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;float&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_float_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_fl_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id48-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">float</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id48-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">float</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_double_id1"><refmeta><refentrytitle>Struct hash&lt;double&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;double&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_do_id1"><refmeta><refentrytitle>Struct hash&lt;double&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;double&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_double_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_do_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id49-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id49-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_long_doub_id1"><refmeta><refentrytitle>Struct hash&lt;long double&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;long double&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_lo_id3"><refmeta><refentrytitle>Struct hash&lt;long double&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;long double&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_doub_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id3">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id50-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id50-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_std_strin_id1"><refmeta><refentrytitle>Struct hash&lt;std::string&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;std::string&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_st_id1"><refmeta><refentrytitle>Struct hash&lt;std::string&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;std::string&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_strin_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_st_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id51-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id51-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
- ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_std_wstri_id1"><refmeta><refentrytitle>Struct hash&lt;std::wstring&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;std::wstring&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_st_id2"><refmeta><refentrytitle>Struct hash&lt;std::wstring&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;std::wstring&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
</phrase>
-<phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_wstri_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_st_id2">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id52-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id52-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
diff --git a/tools/boostbook/test/more/tests/libs/unordered-ref.gold b/tools/boostbook/test/more/tests/libs/unordered-ref.gold
index 8a0793a396..b43156e679 100644
--- a/tools/boostbook/test/more/tests/libs/unordered-ref.gold
+++ b/tools/boostbook/test/more/tests/libs/unordered-ref.gold
@@ -6,10 +6,10 @@
<phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <link linkend="boost.unordered_set">unordered_set</link><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <link linkend="boost.unordered_set.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
@@ -19,10 +19,10 @@
<phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <link linkend="boost.unordered_multiset">unordered_multiset</link><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <link linkend="boost.unordered_multiset.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
@@ -141,10 +141,10 @@
<phrase role="comment">// <link linkend="id68-bb">Equality Comparisons</link></phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="comment">// <link linkend="id69-bb">swap</link></phrase>
@@ -366,12 +366,12 @@
?><varlistentry><term>Effects:</term><listitem><para>Changes the container's maximum load factor, using <computeroutput>z</computeroutput> as a hint.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id67-bb"/><phrase role="identifier">rehash</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Changes the number of buckets so that there at least <computeroutput>n</computeroutput> buckets, and so that the load factor is less than the maximum load factor.</para><para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Throws:</term><listitem><para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id68-bb"/><computeroutput>unordered_set</computeroutput> Equality Comparisons</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_set.operator==_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_set.operato_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
<phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_set.operator!=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_set.operato_id2"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
<phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
@@ -494,10 +494,10 @@
<phrase role="comment">// <link linkend="id137-bb">Equality Comparisons</link></phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="comment">// <link linkend="id138-bb">swap</link></phrase>
@@ -719,12 +719,12 @@
?><varlistentry><term>Effects:</term><listitem><para>Changes the container's maximum load factor, using <computeroutput>z</computeroutput> as a hint.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id136-bb"/><phrase role="identifier">rehash</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Changes the number of buckets so that there at least <computeroutput>n</computeroutput> buckets, and so that the load factor is less than the maximum load factor.</para><para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Throws:</term><listitem><para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id137-bb"/><computeroutput>unordered_multiset</computeroutput> Equality Comparisons</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multiset.operator==_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multiset.operato_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
<phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multiset.operator!=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multiset.operato_id2"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
<phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
@@ -742,11 +742,11 @@
<phrase role="keyword">class</phrase> <link linkend="boost.unordered_map">unordered_map</link><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
@@ -758,11 +758,11 @@
<phrase role="keyword">class</phrase> <link linkend="boost.unordered_multimap">unordered_multimap</link><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
@@ -887,11 +887,11 @@
<phrase role="comment">// <link linkend="id210-bb">Equality Comparisons</link></phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="comment">// <link linkend="id211-bb">swap</link></phrase>
@@ -1124,13 +1124,13 @@
list-presentation="table"
?><varlistentry><term>Throws:</term><listitem><para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id210-bb"/><computeroutput>unordered_map</computeroutput> Equality Comparisons</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_map.operator==_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_map.operato_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
<phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_map.operator!=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_map.operato_id2"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
<phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
@@ -1256,11 +1256,11 @@
<phrase role="comment">// <link linkend="id279-bb">Equality Comparisons</link></phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operato_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operato_id2"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
<phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
<phrase role="comment">// <link linkend="id280-bb">swap</link></phrase>
@@ -1487,13 +1487,13 @@
list-presentation="table"
?><varlistentry><term>Throws:</term><listitem><para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id279-bb"/><computeroutput>unordered_multimap</computeroutput> Equality Comparisons</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multimap.operator==_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multimap.operato_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
<phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
<phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
- <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multimap.operator!=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multimap.operato_id2"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
<phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
list-presentation="table"
?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
diff --git a/tools/boostbook/xsl/navbar.xsl b/tools/boostbook/xsl/navbar.xsl
index ffbbbcb5ea..7c320bbd71 100644
--- a/tools/boostbook/xsl/navbar.xsl
+++ b/tools/boostbook/xsl/navbar.xsl
@@ -33,8 +33,9 @@
</xsl:param>
<!--
header border layout
- Boost - place the old-Boost border around the header
- *none - do not place a border around the header
+ Boost - place the old-Boost border around the header
+ Fullbleed - Simple CSS based full bleed header image
+ *none - do not place a border around the header
-->
<xsl:param name = "nav.border" select = "'none'" />
@@ -87,35 +88,50 @@
<xsl:variable name = "home" select = "/*[1]"/>
<xsl:variable name = "up" select = "parent::*"/>
- <xsl:if test = "boolean(normalize-space($boost.image.src)) or $nav.layout != 'none'">
- <table cellpadding = "2" width = "100%"><tr>
- <xsl:if test = "$nav.border = 'Boost'">
- <xsl:attribute name = "class">boost-head</xsl:attribute>
- </xsl:if>
-
- <td valign = "top">
- <xsl:if test = "$nav.border = 'Boost'">
- <xsl:attribute name = "style">background-color: white; width: 50%;</xsl:attribute>
- </xsl:if>
- <xsl:if test = "boolean(normalize-space($boost.image.src))">
+ <xsl:choose>
+ <xsl:when test = "$nav.border = 'Fullbleed'">
+ <xsl:if test = "boolean(normalize-space($boost.image.src))">
+ <div class="header-fullbleed">
<img alt="{$boost.image.alt}" width="{$boost.image.w}" height="{$boost.image.h}">
- <xsl:attribute name="src">
- <xsl:call-template name="href.target.relative">
- <xsl:with-param name="target" select="$boost.image.src"/>
- </xsl:call-template>
- </xsl:attribute>
+ <xsl:attribute name="src">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$boost.image.src"/>
+ </xsl:call-template>
+ </xsl:attribute>
</img>
+ </div>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test = "boolean(normalize-space($boost.image.src)) or $nav.layout != 'none'">
+ <table cellpadding = "2" width = "100%"><tr>
+ <xsl:if test = "$nav.border = 'Boost'">
+ <xsl:attribute name = "class">boost-head</xsl:attribute>
</xsl:if>
- </td><xsl:choose>
- <xsl:when test = "$nav.layout = 'horizontal'">
- <xsl:call-template name = "header.navdata-horiz"/>
- </xsl:when><xsl:when test = "$nav.layout = 'vertical'">
- <xsl:call-template name = "header.navdata-vert"/>
- </xsl:when>
- </xsl:choose>
- </tr></table>
- <hr/>
- </xsl:if>
+
+ <td valign = "top">
+ <xsl:if test = "$nav.border = 'Boost'">
+ <xsl:attribute name = "style">background-color: white; width: 50%;</xsl:attribute>
+ </xsl:if>
+ <xsl:if test = "boolean(normalize-space($boost.image.src))">
+ <img alt="{$boost.image.alt}" width="{$boost.image.w}" height="{$boost.image.h}">
+ <xsl:attribute name="src">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$boost.image.src"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </img>
+ </xsl:if>
+ </td><xsl:choose>
+ <xsl:when test = "$nav.layout = 'horizontal'">
+ <xsl:call-template name = "header.navdata-horiz"/>
+ </xsl:when><xsl:when test = "$nav.layout = 'vertical'">
+ <xsl:call-template name = "header.navdata-vert"/>
+ </xsl:when>
+ </xsl:choose>
+ </tr></table>
+ <hr/>
+ </xsl:when>
+ </xsl:choose>
<xsl:choose>
<xsl:when test = "$nav.flow = 'DocBook'">
<table width = "100%" class = "navheader">
diff --git a/tools/boostdep/depinst/depinst.py b/tools/boostdep/depinst/depinst.py
new file mode 100644
index 0000000000..2154cc2a87
--- /dev/null
+++ b/tools/boostdep/depinst/depinst.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+
+# depinst.py - installs the dependencies needed to test
+# a Boost library
+#
+# Copyright 2016 Peter Dimov
+#
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+import re
+import sys
+import os
+
+def is_module( m, gm ):
+
+ return ( 'libs/' + m ) in gm
+
+def module_for_header( h, x, gm ):
+
+ if h in x:
+
+ return x[ h ]
+
+ else:
+
+ # boost/function.hpp
+ m = re.match( 'boost/([^\\./]*)\\.h[a-z]*$', h )
+
+ if m and is_module( m.group( 1 ), gm ):
+
+ return m.group( 1 )
+
+ # boost/numeric/conversion.hpp
+ m = re.match( 'boost/([^/]*/[^\\./]*)\\.h[a-z]*$', h )
+
+ if m and is_module( m.group( 1 ), gm ):
+
+ return m.group( 1 )
+
+ # boost/numeric/conversion/header.hpp
+ m = re.match( 'boost/([^/]*/[^/]*)/', h )
+
+ if m and is_module( m.group( 1 ), gm ):
+
+ return m.group( 1 )
+
+ # boost/function/header.hpp
+ m = re.match( 'boost/([^/]*)/', h )
+
+ if m and is_module( m.group( 1 ), gm ):
+
+ return m.group( 1 )
+
+ print 'Cannot determine module for header', h
+
+ return None
+
+def scan_header_dependencies( f, x, gm, deps ):
+
+ for line in f:
+
+ m = re.match( '[ \t]*#[ \t]*include[ \t]*["<](boost/[^">]*)[">]', line )
+
+ if m:
+
+ h = m.group( 1 )
+
+ mod = module_for_header( h, x, gm )
+
+ if mod:
+
+ if not mod in deps:
+
+ vprint( 'Adding dependency', mod )
+ deps[ mod ] = 0
+
+def scan_directory( d, x, gm, deps ):
+
+ vprint( 'Scanning directory', d )
+
+ for root, dirs, files in os.walk( d ):
+
+ for file in files:
+
+ fn = os.path.join( root, file )
+
+ vprint( 'Scanning file', fn )
+
+ with open( fn, 'r' ) as f:
+
+ scan_header_dependencies( f, x, gm, deps )
+
+def scan_module_dependencies( m, x, gm, deps, test ):
+
+ vprint( 'Scanning module', m )
+
+ scan_directory( os.path.join( 'libs', m, 'include' ), x, gm, deps )
+ scan_directory( os.path.join( 'libs', m, 'src' ), x, gm, deps )
+
+ if test:
+ scan_directory( os.path.join( 'libs', m, 'test' ), x, gm, deps )
+
+def read_exceptions():
+
+ # exceptions.txt is the output of "boostdep --list-exceptions"
+
+ x = {}
+
+ module = None
+
+ with open( os.path.join( os.path.dirname( sys.argv[0] ), 'exceptions.txt' ), 'r' ) as f:
+
+ for line in f:
+
+ line = line.rstrip()
+
+ m = re.match( '(.*):$', line )
+
+ if m:
+
+ module = m.group( 1 ).replace( '~', '/' )
+
+ else:
+
+ header = line.lstrip()
+ x[ header ] = module
+
+ return x
+
+def read_gitmodules():
+
+ gm = []
+
+ with open( '.gitmodules', 'r' ) as f:
+
+ for line in f:
+
+ line = line.strip()
+
+ m = re.match( 'path[ \t]*=[ \t]*(.*)$', line )
+
+ if m:
+
+ gm.append( m.group( 1 ) )
+
+ return gm
+
+def install_modules( deps, x, gm ):
+
+ r = 0
+
+ for m, i in deps.items():
+
+ if not i:
+
+ print 'Installing module', m
+ os.system( 'git submodule -q update --init libs/' + m )
+
+ r += 1
+
+ deps[ m ] = 1 # mark as installed
+
+ scan_module_dependencies( m, x, gm, deps, False )
+
+ return r
+
+if( __name__ == "__main__" ):
+
+ argv = sys.argv[ 1: ]
+
+ if argv[0] == '-v':
+
+ def vprint( *args ):
+ for arg in args:
+ print arg,
+ print
+
+ argv = argv[ 1: ]
+
+ else:
+
+ def vprint( *args ):
+ pass
+
+ x = read_exceptions()
+ # vprint( 'Exceptions:', x )
+
+ gm = read_gitmodules()
+ # vprint( '.gitmodules:', gm )
+
+ m = argv[0]
+
+ deps = { m : 1 }
+
+ scan_module_dependencies( m, x, gm, deps, True )
+
+ # vprint( 'Dependencies:', deps )
+
+ while install_modules( deps, x, gm ):
+ pass
diff --git a/tools/boostdep/depinst/exceptions.txt b/tools/boostdep/depinst/exceptions.txt
new file mode 100644
index 0000000000..96515bb9ec
--- /dev/null
+++ b/tools/boostdep/depinst/exceptions.txt
@@ -0,0 +1,397 @@
+assert:
+ boost/current_function.hpp
+atomic:
+ boost/memory_order.hpp
+bind:
+ boost/is_placeholder.hpp
+ boost/mem_fn.hpp
+circular_buffer:
+ boost/circular_buffer_fwd.hpp
+concept_check:
+ boost/concept/assert.hpp
+ boost/concept/detail/backward_compatibility.hpp
+ boost/concept/detail/borland.hpp
+ boost/concept/detail/concept_def.hpp
+ boost/concept/detail/concept_undef.hpp
+ boost/concept/detail/general.hpp
+ boost/concept/detail/has_constraints.hpp
+ boost/concept/detail/msvc.hpp
+ boost/concept/requires.hpp
+ boost/concept/usage.hpp
+ boost/concept_archetype.hpp
+config:
+ boost/cstdint.hpp
+ boost/cxx11_char_types.hpp
+ boost/detail/workaround.hpp
+ boost/limits.hpp
+ boost/version.hpp
+conversion:
+ boost/implicit_cast.hpp
+ boost/polymorphic_cast.hpp
+ boost/polymorphic_pointer_cast.hpp
+convert:
+ boost/make_default.hpp
+core:
+ boost/checked_delete.hpp
+ boost/detail/iterator.hpp
+ boost/detail/lightweight_test.hpp
+ boost/detail/no_exceptions_support.hpp
+ boost/detail/scoped_enum_emulation.hpp
+ boost/detail/sp_typeinfo.hpp
+ boost/get_pointer.hpp
+ boost/iterator.hpp
+ boost/non_type.hpp
+ boost/noncopyable.hpp
+ boost/ref.hpp
+ boost/swap.hpp
+ boost/type.hpp
+ boost/utility/addressof.hpp
+ boost/utility/empty_deleter.hpp
+ boost/utility/enable_if.hpp
+ boost/utility/explicit_operator_bool.hpp
+ boost/utility/swap.hpp
+ boost/visit_each.hpp
+detail:
+ boost/blank.hpp
+ boost/blank_fwd.hpp
+ boost/cstdlib.hpp
+disjoint_sets:
+ boost/pending/detail/disjoint_sets.hpp
+ boost/pending/disjoint_sets.hpp
+dynamic_bitset:
+ boost/detail/dynamic_bitset.hpp
+ boost/dynamic_bitset_fwd.hpp
+ boost/pending/lowest_bit.hpp
+exception:
+ boost/exception_ptr.hpp
+foreach:
+ boost/foreach_fwd.hpp
+function:
+ boost/function_equal.hpp
+graph:
+ boost/detail/algorithm.hpp
+ boost/pending/bucket_sorter.hpp
+ boost/pending/container_traits.hpp
+ boost/pending/detail/property.hpp
+ boost/pending/fenced_priority_queue.hpp
+ boost/pending/fibonacci_heap.hpp
+ boost/pending/indirect_cmp.hpp
+ boost/pending/is_heap.hpp
+ boost/pending/mutable_heap.hpp
+ boost/pending/mutable_queue.hpp
+ boost/pending/property.hpp
+ boost/pending/queue.hpp
+ boost/pending/relaxed_heap.hpp
+ boost/pending/stringtok.hpp
+graph_parallel:
+ boost/graph/accounting.hpp
+ boost/graph/distributed/adjacency_list.hpp
+ boost/graph/distributed/adjlist/handlers.hpp
+ boost/graph/distributed/adjlist/initialize.hpp
+ boost/graph/distributed/adjlist/redistribute.hpp
+ boost/graph/distributed/adjlist/serialization.hpp
+ boost/graph/distributed/betweenness_centrality.hpp
+ boost/graph/distributed/boman_et_al_graph_coloring.hpp
+ boost/graph/distributed/breadth_first_search.hpp
+ boost/graph/distributed/compressed_sparse_row_graph.hpp
+ boost/graph/distributed/concepts.hpp
+ boost/graph/distributed/connected_components.hpp
+ boost/graph/distributed/connected_components_parallel_search.hpp
+ boost/graph/distributed/crauser_et_al_shortest_paths.hpp
+ boost/graph/distributed/dehne_gotz_min_spanning_tree.hpp
+ boost/graph/distributed/delta_stepping_shortest_paths.hpp
+ boost/graph/distributed/depth_first_search.hpp
+ boost/graph/distributed/detail/dijkstra_shortest_paths.hpp
+ boost/graph/distributed/detail/filtered_queue.hpp
+ boost/graph/distributed/detail/mpi_process_group.ipp
+ boost/graph/distributed/detail/queue.ipp
+ boost/graph/distributed/detail/remote_update_set.hpp
+ boost/graph/distributed/detail/tag_allocator.hpp
+ boost/graph/distributed/dijkstra_shortest_paths.hpp
+ boost/graph/distributed/distributed_graph_utility.hpp
+ boost/graph/distributed/eager_dijkstra_shortest_paths.hpp
+ boost/graph/distributed/filtered_graph.hpp
+ boost/graph/distributed/fruchterman_reingold.hpp
+ boost/graph/distributed/graphviz.hpp
+ boost/graph/distributed/hohberg_biconnected_components.hpp
+ boost/graph/distributed/local_subgraph.hpp
+ boost/graph/distributed/mpi_process_group.hpp
+ boost/graph/distributed/named_graph.hpp
+ boost/graph/distributed/one_bit_color_map.hpp
+ boost/graph/distributed/page_rank.hpp
+ boost/graph/distributed/queue.hpp
+ boost/graph/distributed/reverse_graph.hpp
+ boost/graph/distributed/rmat_graph_generator.hpp
+ boost/graph/distributed/selector.hpp
+ boost/graph/distributed/shuffled_distribution.hpp
+ boost/graph/distributed/st_connected.hpp
+ boost/graph/distributed/strong_components.hpp
+ boost/graph/distributed/two_bit_color_map.hpp
+ boost/graph/distributed/unsafe_serialize.hpp
+ boost/graph/distributed/vertex_list_adaptor.hpp
+ boost/graph/parallel/algorithm.hpp
+ boost/graph/parallel/basic_reduce.hpp
+ boost/graph/parallel/container_traits.hpp
+ boost/graph/parallel/detail/inplace_all_to_all.hpp
+ boost/graph/parallel/detail/property_holders.hpp
+ boost/graph/parallel/detail/untracked_pair.hpp
+ boost/graph/parallel/distribution.hpp
+ boost/graph/parallel/process_group.hpp
+ boost/graph/parallel/properties.hpp
+ boost/graph/parallel/simple_trigger.hpp
+ boost/pending/property_serialize.hpp
+integer:
+ boost/integer_fwd.hpp
+ boost/integer_traits.hpp
+ boost/pending/integer_log2.hpp
+io:
+ boost/io_fwd.hpp
+iterator:
+ boost/function_output_iterator.hpp
+ boost/generator_iterator.hpp
+ boost/indirect_reference.hpp
+ boost/iterator_adaptors.hpp
+ boost/pending/detail/int_iterator.hpp
+ boost/pending/iterator_adaptors.hpp
+ boost/pending/iterator_tests.hpp
+ boost/pointee.hpp
+ boost/shared_container_iterator.hpp
+lexical_cast:
+ boost/detail/basic_pointerbuf.hpp
+ boost/detail/lcast_precision.hpp
+math:
+ boost/cstdfloat.hpp
+ boost/math_fwd.hpp
+multi_index:
+ boost/multi_index_container.hpp
+ boost/multi_index_container_fwd.hpp
+numeric/conversion:
+ boost/cast.hpp
+optional:
+ boost/none.hpp
+ boost/none_t.hpp
+predef:
+ boost/detail/endian.hpp
+ boost/predef.h
+random:
+ boost/nondet_random.hpp
+regex:
+ boost/cregex.hpp
+ boost/regex.h
+ boost/regex_fwd.hpp
+serialization:
+ boost/archive/archive_exception.hpp
+ boost/archive/basic_archive.hpp
+ boost/archive/basic_binary_iarchive.hpp
+ boost/archive/basic_binary_iprimitive.hpp
+ boost/archive/basic_binary_oarchive.hpp
+ boost/archive/basic_binary_oprimitive.hpp
+ boost/archive/basic_streambuf_locale_saver.hpp
+ boost/archive/basic_text_iarchive.hpp
+ boost/archive/basic_text_iprimitive.hpp
+ boost/archive/basic_text_oarchive.hpp
+ boost/archive/basic_text_oprimitive.hpp
+ boost/archive/basic_xml_archive.hpp
+ boost/archive/basic_xml_iarchive.hpp
+ boost/archive/basic_xml_oarchive.hpp
+ boost/archive/binary_iarchive.hpp
+ boost/archive/binary_iarchive_impl.hpp
+ boost/archive/binary_oarchive.hpp
+ boost/archive/binary_oarchive_impl.hpp
+ boost/archive/binary_wiarchive.hpp
+ boost/archive/binary_woarchive.hpp
+ boost/archive/codecvt_null.hpp
+ boost/archive/detail/abi_prefix.hpp
+ boost/archive/detail/abi_suffix.hpp
+ boost/archive/detail/archive_serializer_map.hpp
+ boost/archive/detail/auto_link_archive.hpp
+ boost/archive/detail/auto_link_warchive.hpp
+ boost/archive/detail/basic_iarchive.hpp
+ boost/archive/detail/basic_iserializer.hpp
+ boost/archive/detail/basic_oarchive.hpp
+ boost/archive/detail/basic_oserializer.hpp
+ boost/archive/detail/basic_pointer_iserializer.hpp
+ boost/archive/detail/basic_pointer_oserializer.hpp
+ boost/archive/detail/basic_serializer.hpp
+ boost/archive/detail/basic_serializer_map.hpp
+ boost/archive/detail/check.hpp
+ boost/archive/detail/common_iarchive.hpp
+ boost/archive/detail/common_oarchive.hpp
+ boost/archive/detail/decl.hpp
+ boost/archive/detail/helper_collection.hpp
+ boost/archive/detail/interface_iarchive.hpp
+ boost/archive/detail/interface_oarchive.hpp
+ boost/archive/detail/iserializer.hpp
+ boost/archive/detail/oserializer.hpp
+ boost/archive/detail/polymorphic_iarchive_route.hpp
+ boost/archive/detail/polymorphic_oarchive_route.hpp
+ boost/archive/detail/register_archive.hpp
+ boost/archive/detail/utf8_codecvt_facet.hpp
+ boost/archive/dinkumware.hpp
+ boost/archive/impl/archive_serializer_map.ipp
+ boost/archive/impl/basic_binary_iarchive.ipp
+ boost/archive/impl/basic_binary_iprimitive.ipp
+ boost/archive/impl/basic_binary_oarchive.ipp
+ boost/archive/impl/basic_binary_oprimitive.ipp
+ boost/archive/impl/basic_text_iarchive.ipp
+ boost/archive/impl/basic_text_iprimitive.ipp
+ boost/archive/impl/basic_text_oarchive.ipp
+ boost/archive/impl/basic_text_oprimitive.ipp
+ boost/archive/impl/basic_xml_grammar.hpp
+ boost/archive/impl/basic_xml_iarchive.ipp
+ boost/archive/impl/basic_xml_oarchive.ipp
+ boost/archive/impl/text_iarchive_impl.ipp
+ boost/archive/impl/text_oarchive_impl.ipp
+ boost/archive/impl/text_wiarchive_impl.ipp
+ boost/archive/impl/text_woarchive_impl.ipp
+ boost/archive/impl/xml_iarchive_impl.ipp
+ boost/archive/impl/xml_oarchive_impl.ipp
+ boost/archive/impl/xml_wiarchive_impl.ipp
+ boost/archive/impl/xml_woarchive_impl.ipp
+ boost/archive/iterators/base64_exception.hpp
+ boost/archive/iterators/base64_from_binary.hpp
+ boost/archive/iterators/binary_from_base64.hpp
+ boost/archive/iterators/dataflow.hpp
+ boost/archive/iterators/dataflow_exception.hpp
+ boost/archive/iterators/escape.hpp
+ boost/archive/iterators/insert_linebreaks.hpp
+ boost/archive/iterators/istream_iterator.hpp
+ boost/archive/iterators/mb_from_wchar.hpp
+ boost/archive/iterators/ostream_iterator.hpp
+ boost/archive/iterators/remove_whitespace.hpp
+ boost/archive/iterators/transform_width.hpp
+ boost/archive/iterators/unescape.hpp
+ boost/archive/iterators/wchar_from_mb.hpp
+ boost/archive/iterators/xml_escape.hpp
+ boost/archive/iterators/xml_unescape.hpp
+ boost/archive/iterators/xml_unescape_exception.hpp
+ boost/archive/polymorphic_binary_iarchive.hpp
+ boost/archive/polymorphic_binary_oarchive.hpp
+ boost/archive/polymorphic_iarchive.hpp
+ boost/archive/polymorphic_oarchive.hpp
+ boost/archive/polymorphic_text_iarchive.hpp
+ boost/archive/polymorphic_text_oarchive.hpp
+ boost/archive/polymorphic_text_wiarchive.hpp
+ boost/archive/polymorphic_text_woarchive.hpp
+ boost/archive/polymorphic_xml_iarchive.hpp
+ boost/archive/polymorphic_xml_oarchive.hpp
+ boost/archive/polymorphic_xml_wiarchive.hpp
+ boost/archive/polymorphic_xml_woarchive.hpp
+ boost/archive/text_iarchive.hpp
+ boost/archive/text_oarchive.hpp
+ boost/archive/text_wiarchive.hpp
+ boost/archive/text_woarchive.hpp
+ boost/archive/tmpdir.hpp
+ boost/archive/wcslen.hpp
+ boost/archive/xml_archive_exception.hpp
+ boost/archive/xml_iarchive.hpp
+ boost/archive/xml_oarchive.hpp
+ boost/archive/xml_wiarchive.hpp
+ boost/archive/xml_woarchive.hpp
+signals:
+ boost/last_value.hpp
+ boost/signal.hpp
+smart_ptr:
+ boost/detail/atomic_count.hpp
+ boost/detail/lightweight_mutex.hpp
+ boost/detail/lightweight_thread.hpp
+ boost/detail/quick_allocator.hpp
+ boost/enable_shared_from_this.hpp
+ boost/intrusive_ptr.hpp
+ boost/make_shared.hpp
+ boost/make_unique.hpp
+ boost/pointer_cast.hpp
+ boost/pointer_to_other.hpp
+ boost/scoped_array.hpp
+ boost/scoped_ptr.hpp
+ boost/shared_array.hpp
+ boost/shared_ptr.hpp
+ boost/weak_ptr.hpp
+system:
+ boost/cerrno.hpp
+thread:
+ boost/detail/atomic_redef_macros.hpp
+ boost/detail/atomic_undef_macros.hpp
+throw_exception:
+ boost/exception/exception.hpp
+timer:
+ boost/progress.hpp
+tokenizer:
+ boost/token_functions.hpp
+ boost/token_iterator.hpp
+type_traits:
+ boost/aligned_storage.hpp
+ boost/utility/declval.hpp
+unordered:
+ boost/unordered_map.hpp
+ boost/unordered_set.hpp
+utility:
+ boost/call_traits.hpp
+ boost/compressed_pair.hpp
+ boost/detail/call_traits.hpp
+ boost/detail/compressed_pair.hpp
+ boost/detail/ob_compressed_pair.hpp
+ boost/next_prior.hpp
+ boost/operators.hpp
+ boost/operators_v1.hpp
+winapi:
+ boost/detail/interlocked.hpp
+ boost/detail/winapi/GetCurrentProcess.hpp
+ boost/detail/winapi/GetCurrentThread.hpp
+ boost/detail/winapi/GetLastError.hpp
+ boost/detail/winapi/GetProcessTimes.hpp
+ boost/detail/winapi/GetThreadTimes.hpp
+ boost/detail/winapi/access_rights.hpp
+ boost/detail/winapi/apc.hpp
+ boost/detail/winapi/basic_types.hpp
+ boost/detail/winapi/character_code_conversion.hpp
+ boost/detail/winapi/condition_variable.hpp
+ boost/detail/winapi/config.hpp
+ boost/detail/winapi/critical_section.hpp
+ boost/detail/winapi/crypt.hpp
+ boost/detail/winapi/dbghelp.hpp
+ boost/detail/winapi/detail/cast_ptr.hpp
+ boost/detail/winapi/directory_management.hpp
+ boost/detail/winapi/dll.hpp
+ boost/detail/winapi/environment.hpp
+ boost/detail/winapi/error_codes.hpp
+ boost/detail/winapi/error_handling.hpp
+ boost/detail/winapi/event.hpp
+ boost/detail/winapi/file_management.hpp
+ boost/detail/winapi/file_mapping.hpp
+ boost/detail/winapi/get_current_process.hpp
+ boost/detail/winapi/get_current_process_id.hpp
+ boost/detail/winapi/get_current_thread.hpp
+ boost/detail/winapi/get_current_thread_id.hpp
+ boost/detail/winapi/get_last_error.hpp
+ boost/detail/winapi/get_process_times.hpp
+ boost/detail/winapi/get_system_directory.hpp
+ boost/detail/winapi/get_thread_times.hpp
+ boost/detail/winapi/handle_info.hpp
+ boost/detail/winapi/handles.hpp
+ boost/detail/winapi/heap_memory.hpp
+ boost/detail/winapi/init_once.hpp
+ boost/detail/winapi/jobs.hpp
+ boost/detail/winapi/limits.hpp
+ boost/detail/winapi/local_memory.hpp
+ boost/detail/winapi/memory.hpp
+ boost/detail/winapi/mutex.hpp
+ boost/detail/winapi/overlapped.hpp
+ boost/detail/winapi/page_protection_flags.hpp
+ boost/detail/winapi/pipes.hpp
+ boost/detail/winapi/priority_class.hpp
+ boost/detail/winapi/process.hpp
+ boost/detail/winapi/security.hpp
+ boost/detail/winapi/semaphore.hpp
+ boost/detail/winapi/shell.hpp
+ boost/detail/winapi/show_window.hpp
+ boost/detail/winapi/srw_lock.hpp
+ boost/detail/winapi/synchronization.hpp
+ boost/detail/winapi/system.hpp
+ boost/detail/winapi/thread.hpp
+ boost/detail/winapi/thread_pool.hpp
+ boost/detail/winapi/time.hpp
+ boost/detail/winapi/timers.hpp
+ boost/detail/winapi/tls.hpp
+ boost/detail/winapi/wait.hpp
+ boost/detail/winapi/waitable_timer.hpp
diff --git a/tools/boostdep/doc/html/index.html b/tools/boostdep/doc/html/index.html
index 5d654eccc5..1a27d3f2b7 100644
--- a/tools/boostdep/doc/html/index.html
+++ b/tools/boostdep/doc/html/index.html
@@ -59,6 +59,7 @@
<dt><span class="section"><a href="index.html#boostdep.reference.reverse">--reverse</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.subset">--subset</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.header">--header</a></span></dt>
+<dt><span class="section"><a href="index.html#boostdep.reference.test">--test</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.track_sources">--track-sources</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.title">--title</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.footer">--footer</a></span></dt>
@@ -322,6 +323,7 @@ nothing added to commit but untracked files present (use "git add" to track)
boostdep [options] --reverse &lt;module&gt;
boostdep [options] --subset &lt;module&gt;
boostdep [options] [--header] &lt;header&gt;
+ boostdep --test &lt;module&gt;
[options]: [--track-sources] [--title &lt;title&gt;] [--footer &lt;footer&gt;] [--html]
</pre>
@@ -580,6 +582,7 @@ FOR /f %%i IN (%OUTDIR%\list-modules.txt) DO %BOOSTDEP% --title "Dependency Repo
<dt><span class="section"><a href="index.html#boostdep.reference.reverse">--reverse</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.subset">--subset</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.header">--header</a></span></dt>
+<dt><span class="section"><a href="index.html#boostdep.reference.test">--test</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.track_sources">--track-sources</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.title">--title</a></span></dt>
<dt><span class="section"><a href="index.html#boostdep.reference.footer">--footer</a></span></dt>
@@ -802,6 +805,19 @@ align -&gt; assert config core static_assert throw_exception
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
+<a name="boostdep.reference.test"></a><a class="link" href="index.html#boostdep.reference.test" title="--test">--test</a>
+</h3></div></div></div>
+<p>
+ <code class="literal">boostdep --test <span class="emphasis"><em>module</em></span></code> lists the
+ test dependencies of <span class="emphasis"><em>module</em></span>, that is, it lists which
+ modules need to be present so that the tests of <span class="emphasis"><em>module</em></span>
+ can be run.
+ </p>
+<pre class="programlisting">dist/bin/boostdep --test filesystem
+</pre>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
<a name="boostdep.reference.track_sources"></a><a class="link" href="index.html#boostdep.reference.track_sources" title="--track-sources">--track-sources</a>
</h3></div></div></div>
<p>
@@ -841,7 +857,7 @@ align -&gt; assert config core static_assert throw_exception
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
-<td align="left"><p><small>Last revised: March 04, 2016 at 11:24:14 GMT</small></p></td>
+<td align="left"><p><small>Last revised: November 09, 2016 at 22:11:27 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>
diff --git a/tools/boostdep/doc/src/boostdep.qbk b/tools/boostdep/doc/src/boostdep.qbk
index 545f6122c2..68d738e14e 100644
--- a/tools/boostdep/doc/src/boostdep.qbk
+++ b/tools/boostdep/doc/src/boostdep.qbk
@@ -244,6 +244,7 @@ Usage:
boostdep \[options\] --reverse <module>
boostdep \[options\] --subset <module>
boostdep \[options\] \[--header\] <header>
+ boostdep --test <module>
\[options\]: \[--track-sources\] \[--title <title>\] \[--footer <footer>\] \[--html\]
]
@@ -644,6 +645,16 @@ dist/bin/boostdep --title "Inclusion Report for <boost/shared_ptr.hpp>" --footer
[endsect]
+[section --test]
+
+[^boostdep --test /module/] lists the test dependencies of /module/, that is, it lists which modules need to be present so that the tests of /module/ can be run.
+
+[pre
+dist/bin/boostdep --test filesystem
+]
+
+[endsect]
+
[section --track-sources]
The =--track-sources= option instructs /Boostdep/ to scan the =src= library subdirectory for `#include` directives. By default,
diff --git a/tools/boostdep/src/boostdep.cpp b/tools/boostdep/src/boostdep.cpp
index 7b30fef313..03c8b7d0cc 100644
--- a/tools/boostdep/src/boostdep.cpp
+++ b/tools/boostdep/src/boostdep.cpp
@@ -46,13 +46,14 @@ static void scan_module_headers( fs::path const & path )
for( ; it != last; ++it )
{
- fs::directory_entry const & e = *it;
+ if( it->status().type() == fs::directory_file )
+ {
+ continue;
+ }
- std::string p2 = e.path().generic_string();
+ std::string p2 = it->path().generic_string();
p2 = p2.substr( n+1 );
- // std::cout << module << ": " << p2 << std::endl;
-
s_header_map[ p2 ] = module;
s_module_headers[ module ].insert( p2 );
}
@@ -190,48 +191,59 @@ static fs::path module_build_path( std::string module )
return fs::path( "libs" ) / module / "build";
}
-static void scan_module_dependencies( std::string const & module, module_primary_actions & actions, bool track_sources, bool include_self )
+static fs::path module_test_path( std::string module )
{
- // module -> [ header, header... ]
- std::map< std::string, std::set< std::string > > deps;
+ std::replace( module.begin(), module.end(), '~', '/' );
+ return fs::path( "libs" ) / module / "test";
+}
- // header -> included from [ header, header... ]
- std::map< std::string, std::set< std::string > > from;
+static void scan_module_path( fs::path const & dir, bool remove_prefix, std::map< std::string, std::set< std::string > > & deps, std::map< std::string, std::set< std::string > > & from )
+{
+ size_t n = dir.generic_string().size();
+ if( fs::exists( dir ) )
{
- fs::path dir = module_include_path( module );
- size_t n = dir.generic_string().size();
-
fs::recursive_directory_iterator it( dir ), last;
for( ; it != last; ++it )
{
- std::string header = it->path().generic_string().substr( n+1 );
+ if( it->status().type() == fs::directory_file )
+ {
+ continue;
+ }
+
+ std::string header = it->path().generic_string();
+
+ if( remove_prefix )
+ {
+ header = header.substr( n+1 );
+ }
fs::ifstream is( it->path() );
scan_header_dependencies( header, is, deps, from );
}
}
+}
- if( track_sources )
- {
- fs::path dir = module_source_path( module );
- size_t n = dir.generic_string().size();
+static void scan_module_dependencies( std::string const & module, module_primary_actions & actions, bool track_sources, bool track_tests, bool include_self )
+{
+ // module -> [ header, header... ]
+ std::map< std::string, std::set< std::string > > deps;
- if( fs::exists( dir ) )
- {
- fs::recursive_directory_iterator it( dir ), last;
+ // header -> included from [ header, header... ]
+ std::map< std::string, std::set< std::string > > from;
- for( ; it != last; ++it )
- {
- std::string header = it->path().generic_string().substr( n+1 );
+ scan_module_path( module_include_path( module ), true, deps, from );
- fs::ifstream is( it->path() );
+ if( track_sources )
+ {
+ scan_module_path( module_source_path( module ), false, deps, from );
+ }
- scan_header_dependencies( header, is, deps, from );
- }
- }
+ if( track_tests )
+ {
+ scan_module_path( module_test_path( module ), false, deps, from );
}
actions.heading( module );
@@ -318,20 +330,20 @@ struct build_mdmap_actions: public module_primary_actions
}
};
-static void build_module_dependency_map( bool track_sources )
+static void build_module_dependency_map( bool track_sources, bool track_tests )
{
for( std::set< std::string >::iterator i = s_modules.begin(); i != s_modules.end(); ++i )
{
build_mdmap_actions actions;
- scan_module_dependencies( *i, actions, track_sources, true );
+ scan_module_dependencies( *i, actions, track_sources, track_tests, true );
}
}
-static void output_module_primary_report( std::string const & module, module_primary_actions & actions, bool track_sources )
+static void output_module_primary_report( std::string const & module, module_primary_actions & actions, bool track_sources, bool track_tests )
{
try
{
- scan_module_dependencies( module, actions, track_sources, false );
+ scan_module_dependencies( module, actions, track_sources, track_tests, false );
}
catch( fs::filesystem_error const & x )
{
@@ -357,12 +369,10 @@ static void exclude( std::set< std::string > & x, std::set< std::string > const
}
}
-static void output_module_secondary_report( std::string const & module, module_secondary_actions & actions )
+static void output_module_secondary_report( std::string const & module, std::set< std::string> deps, module_secondary_actions & actions )
{
actions.heading( module );
- std::set< std::string > deps = s_module_deps[ module ];
-
deps.insert( module );
// build transitive closure
@@ -405,6 +415,11 @@ static void output_module_secondary_report( std::string const & module, module_s
}
}
+static void output_module_secondary_report( std::string const & module, module_secondary_actions & actions )
+{
+ output_module_secondary_report( module, s_module_deps[ module ], actions );
+}
+
struct header_inclusion_actions
{
virtual void heading( std::string const & header, std::string const & module ) = 0;
@@ -512,17 +527,17 @@ struct module_primary_html_actions: public module_primary_actions
}
};
-static void output_module_primary_report( std::string const & module, bool html, bool track_sources )
+static void output_module_primary_report( std::string const & module, bool html, bool track_sources, bool track_tests )
{
if( html )
{
module_primary_html_actions actions;
- output_module_primary_report( module, actions, track_sources );
+ output_module_primary_report( module, actions, track_sources, track_tests );
}
else
{
module_primary_txt_actions actions;
- output_module_primary_report( module, actions, track_sources );
+ output_module_primary_report( module, actions, track_sources, track_tests );
}
}
@@ -1300,13 +1315,13 @@ static void output_html_footer( std::string const & footer )
std::cout << "</html>\n";
}
-static void enable_secondary( bool & secondary, bool track_sources )
+static void enable_secondary( bool & secondary, bool track_sources, bool track_tests )
{
if( !secondary )
{
try
{
- build_module_dependency_map( track_sources );
+ build_module_dependency_map( track_sources, track_tests );
}
catch( fs::filesystem_error const & x )
{
@@ -1610,11 +1625,39 @@ struct module_subset_actions
virtual void from_path( std::vector<std::string> const & path ) = 0;
};
-static void output_module_subset_report( std::string const & module, module_subset_actions & actions )
+static void add_module_headers( fs::path const & dir, std::set<std::string> & headers )
+{
+ if( fs::exists( dir ) )
+ {
+ fs::recursive_directory_iterator it( dir ), last;
+
+ for( ; it != last; ++it )
+ {
+ if( it->status().type() == fs::directory_file )
+ {
+ continue;
+ }
+
+ headers.insert( it->path().generic_string() );
+ }
+ }
+}
+
+static void output_module_subset_report( std::string const & module, bool track_sources, bool track_tests, module_subset_actions & actions )
{
// build header closure
- std::set<std::string> const & headers = s_module_headers[ module ];
+ std::set<std::string> headers = s_module_headers[ module ];
+
+ if( track_sources )
+ {
+ add_module_headers( module_source_path( module ), headers );
+ }
+
+ if( track_tests )
+ {
+ add_module_headers( module_test_path( module ), headers );
+ }
// header -> (header)*
std::map< std::string, std::set<std::string> > inc2;
@@ -1784,20 +1827,139 @@ struct module_subset_html_actions: public module_subset_actions
}
};
-static void output_module_subset_report( std::string const & module, bool html )
+static void output_module_subset_report( std::string const & module, bool track_sources, bool track_tests, bool html )
{
if( html )
{
module_subset_html_actions actions;
- output_module_subset_report( module, actions );
+ output_module_subset_report( module, track_sources, track_tests, actions );
}
else
{
module_subset_txt_actions actions;
- output_module_subset_report( module, actions );
+ output_module_subset_report( module, track_sources, track_tests, actions );
}
}
+static void list_exceptions()
+{
+ std::string lm;
+
+ for( std::map< std::string, std::set<std::string> >::const_iterator i = s_module_headers.begin(); i != s_module_headers.end(); ++i )
+ {
+ std::string module = i->first;
+
+ std::replace( module.begin(), module.end(), '~', '/' );
+
+ std::string const prefix = "boost/" + module;
+ size_t const n = prefix.size();
+
+ for( std::set< std::string >::const_iterator j = i->second.begin(); j != i->second.end(); ++j )
+ {
+ std::string const & header = *j;
+
+ if( header.substr( 0, n+1 ) != prefix + '/' && header != prefix + ".hpp" )
+ {
+ if( lm != module )
+ {
+ std::cout << module << ":\n";
+ lm = module;
+ }
+
+ std::cout << " " << header << '\n';
+ }
+ }
+ }
+}
+
+struct module_test_primary_actions: public module_primary_actions
+{
+ std::set< std::string > & m_;
+
+ module_test_primary_actions( std::set< std::string > & m ): m_( m )
+ {
+ }
+
+ void heading( std::string const & module )
+ {
+ std::cout << "Test dependencies for " << module << ":\n\n";
+ }
+
+ void module_start( std::string const & module )
+ {
+ std::cout << module << "\n";
+ m_.insert( module );
+ }
+
+ void module_end( std::string const & /*module*/ )
+ {
+ }
+
+ void header_start( std::string const & /*header*/ )
+ {
+ }
+
+ void header_end( std::string const & /*header*/ )
+ {
+ }
+
+ void from_header( std::string const & /*header*/ )
+ {
+ }
+};
+
+struct module_test_secondary_actions: public module_secondary_actions
+{
+ std::set< std::string > & m_;
+ std::string m2_;
+
+ module_test_secondary_actions( std::set< std::string > & m ): m_( m )
+ {
+ }
+
+ void heading( std::string const & module )
+ {
+ }
+
+ void module_start( std::string const & module )
+ {
+ m2_ = module;
+ }
+
+ void module_end( std::string const & /*module*/ )
+ {
+ }
+
+ void module_adds( std::string const & module )
+ {
+ if( m_.count( module ) == 0 )
+ {
+ std::cout << module << " (from " << m2_ << ")\n";
+ m_.insert( module );
+ }
+ }
+};
+
+static void output_module_test_report( std::string const & module )
+{
+ std::set< std::string > m;
+
+ module_test_primary_actions a1( m );
+ output_module_primary_report( module, a1, true, true );
+
+ std::cout << "\n";
+
+ bool secondary = false;
+ enable_secondary( secondary, true, false );
+
+ std::set< std::string > m2( m );
+ m2.insert( module );
+
+ module_test_secondary_actions a2( m2 );
+
+ output_module_secondary_report( module, m, a2 );
+}
+
int main( int argc, char const* argv[] )
{
if( argc < 2 )
@@ -1808,7 +1970,8 @@ int main( int argc, char const* argv[] )
"\n"
" boostdep --list-modules\n"
" boostdep --list-buildable\n"
- " boostdep [--track-sources] --list-dependencies\n"
+ " boostdep [--track-sources] [--track-tests] --list-dependencies\n"
+ " boostdep --list-exceptions\n"
"\n"
" boostdep [options] --module-overview\n"
" boostdep [options] --module-levels\n"
@@ -1819,8 +1982,10 @@ int main( int argc, char const* argv[] )
" boostdep [options] --reverse <module>\n"
" boostdep [options] --subset <module>\n"
" boostdep [options] [--header] <header>\n"
+ " boostdep --test <module>\n"
"\n"
- " [options]: [--track-sources] [--title <title>] [--footer <footer>] [--html]\n";
+ " [options]: [--[no-]track-sources] [--[no-]track-tests]\n"
+ " [--title <title>] [--footer <footer>] [--html]\n";
return -1;
}
@@ -1837,6 +2002,7 @@ int main( int argc, char const* argv[] )
bool html = false;
bool secondary = false;
bool track_sources = false;
+ bool track_tests = false;
std::string title = "Boost Dependency Report";
std::string footer;
@@ -1879,18 +2045,30 @@ int main( int argc, char const* argv[] )
{
track_sources = true;
}
+ else if( option == "--no-track-sources" )
+ {
+ track_sources = false;
+ }
+ else if( option == "--track-tests" )
+ {
+ track_tests = true;
+ }
+ else if( option == "--no-track-tests" )
+ {
+ track_tests = false;
+ }
else if( option == "--primary" )
{
if( i + 1 < argc )
{
- output_module_primary_report( argv[ ++i ], html, track_sources );
+ output_module_primary_report( argv[ ++i ], html, track_sources, track_tests );
}
}
else if( option == "--secondary" )
{
if( i + 1 < argc )
{
- enable_secondary( secondary, track_sources );
+ enable_secondary( secondary, track_sources, track_tests );
output_module_secondary_report( argv[ ++i ], html );
}
}
@@ -1898,7 +2076,7 @@ int main( int argc, char const* argv[] )
{
if( i + 1 < argc )
{
- enable_secondary( secondary, track_sources );
+ enable_secondary( secondary, track_sources, track_tests );
output_module_reverse_report( argv[ ++i ], html );
}
}
@@ -1906,7 +2084,7 @@ int main( int argc, char const* argv[] )
{
if( i + 1 < argc )
{
- enable_secondary( secondary, track_sources );
+ enable_secondary( secondary, track_sources, track_tests );
output_header_report( argv[ ++i ], html );
}
}
@@ -1914,37 +2092,48 @@ int main( int argc, char const* argv[] )
{
if( i + 1 < argc )
{
- enable_secondary( secondary, track_sources );
- output_module_subset_report( argv[ ++i ], html );
+ enable_secondary( secondary, track_sources, track_tests );
+ output_module_subset_report( argv[ ++i ], track_sources, track_tests, html );
+ }
+ }
+ else if( option == "--test" )
+ {
+ if( i + 1 < argc )
+ {
+ output_module_test_report( argv[ ++i ] );
}
}
else if( option == "--module-levels" )
{
- enable_secondary( secondary, track_sources );
+ enable_secondary( secondary, track_sources, track_tests );
output_module_level_report( html );
}
else if( option == "--module-overview" )
{
- enable_secondary( secondary, track_sources );
+ enable_secondary( secondary, track_sources, track_tests );
output_module_overview_report( html );
}
else if( option == "--module-weights" )
{
- enable_secondary( secondary, track_sources );
+ enable_secondary( secondary, track_sources, track_tests );
output_module_weight_report( html );
}
else if( option == "--list-dependencies" )
{
- enable_secondary( secondary, track_sources );
+ enable_secondary( secondary, track_sources, track_tests );
list_dependencies();
}
+ else if( option == "--list-exceptions" )
+ {
+ list_exceptions();
+ }
else if( s_modules.count( option ) )
{
- output_module_primary_report( option, html, track_sources );
+ output_module_primary_report( option, html, track_sources, track_tests );
}
else if( s_header_map.count( option ) )
{
- enable_secondary( secondary, track_sources );
+ enable_secondary( secondary, track_sources, track_tests );
output_header_report( option, html );
}
else
diff --git a/tools/build/CONTRIBUTING.rst b/tools/build/CONTRIBUTING.rst
new file mode 100644
index 0000000000..77a071dfe6
--- /dev/null
+++ b/tools/build/CONTRIBUTING.rst
@@ -0,0 +1,161 @@
+:Copyright:
+ Copyright 2003, 2006 Vladimir Prus
+:License:
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+Boost.Build contributor guidelines
+==================================
+
+Boost.Build is an open-source project. This means that we welcome and appreciate
+all contributions --- be it ideas, bug reports, or patches. This document
+contains guidelines which helps to assure that development goes on smoothly, and
+changes are made quickly.
+
+The guidelines are not mandatory, and you can decide for yourself which one to
+follow. But note, that 10 mins that you spare writing a comment, for example,
+might lead to significally longer delay for everyone.
+
+Before contributing, make sure you are subscribed to our mailing list
+at boost-build@lists.boost.org.
+
+Additional resources include
+
+- The issue tracker
+
+ http://trac.lvk.cs.msu.su/boost.build/
+
+- mailing list
+
+ boost-build@lists.boost.org
+
+ http://lists.boost.org/boost-build/
+
+BUGS and PATCHES
+----------------
+
+Both bugs and patches can be send to our mailing list.
+
+When reporting a bug, please try to provide the following information.
+
+- What you did.
+
+ - A minimal reproducible testcase is very much appreciated.
+
+ - Shell script with some annotations is much better than verbose description
+ of the problem.
+
+ - A regression test is the best (see test/test_system.html).
+
+- What you got.
+
+- What you expected.
+
+- What version of Boost.Build and Boost.Jam did you use. If possible,
+ please try to test with the CVS HEAD state.
+
+When submitting a patch, please:
+
+- make a single patch for a single logical change
+- follow the policies and coding conventions below,
+- send patches in unified diff format, (using either "cvs diff -u" or "diff -u")
+- provide a log message together with the patch
+- put the patch and the log message as attachment to your email.
+
+The purpose of log message serves to communicate what was changed, and *why*.
+Without a good log message, you might spend a lot of time later, wondering where
+a strange piece of code came from and why it was necessary.
+
+The good log message mentions each changed file and each rule/method, saying
+what happend to it, and why. Consider, the following log message
+
+::
+
+ Better direct request handling.
+
+ * new/build-request.jam
+ (directly-requested-properties-adjuster): Redo.
+
+ * new/targets.jam
+ (main-target.generate-really): Adjust properties here.
+
+ * new/virtual-target.jam
+ (register-actual-name): New rule.
+ (virtual-target.actualize-no-scanner): Call the above, to detected bugs,
+ where two virtual target correspond to one Jam target name.
+
+The log messages for the last two files are good. They tell what was changed.
+The change to the first file is clearly undercommented.
+
+It's OK to use terse log messages for uninteresting changes, like ones induced
+by interface changes elsewhere.
+
+POLICIES.
+---------
+
+1. Testing.
+
+ All serious changes must be tested. New rules must be tested by the module where
+ they are declared. Test system (test/test_system.html) should be used to verify
+ user-observable behaviour.
+
+2. Documentation.
+
+ It turns out that it's hard to have too much comments, but it's easy to have too
+ little. Please prepend each rule with a comment saying what the rule does and
+ what arguments mean. Stop for a minute and consider if the comment makes sense
+ for anybody else, and completely describes what the rules does. Generic phrases
+ like "adjusts properties" are really not enough.
+
+When applicable, make changes to the user documentation as well.
+
+CODING CONVENTIONS.
+-------------------
+
+1. All names of rules and variables are lowercase with "-" to separate
+ words.
+
+ ::
+
+ rule call-me-ishmael ( ) ...
+
+2. Names with dots in them are "intended globals". Ordinary globals use a
+ dot prefix:
+
+ ::
+
+ .foobar
+ $(.foobar)
+
+3. Pseudofunctions or associations are <parameter>.<property>:
+
+ ::
+
+ $(argument).name = hello ;
+ $($(argument).name)
+
+4. Class attribute names are prefixed with "self.":
+
+ ::
+
+ self.x
+ $(self.x)
+
+5. Builtin rules are called via their ALL_UPPERCASE_NAMES:
+
+ ::
+
+ DEPENDS $(target) : $(sources) ;
+
+6. Opening and closing braces go on separate lines:
+
+ ::
+
+ if $(a)
+ {
+ #
+ }
+ else
+ {
+ #
+ }
diff --git a/tools/build/README.rst b/tools/build/README.rst
new file mode 100644
index 0000000000..fe0a6f3940
--- /dev/null
+++ b/tools/build/README.rst
@@ -0,0 +1,6 @@
+Boost.Build
+===========
+
+See the Boost.Build website at https://boost.org/build.
+
+See the `guidelines for contributing <./CONTRIBUTING.rst>`__.
diff --git a/tools/build/doc/bin/gcc-4.8/debug/jam_docs.xml b/tools/build/doc/bin/gcc-4.8/debug/jam_docs.xml
deleted file mode 100644
index a918eb6828..0000000000
--- a/tools/build/doc/bin/gcc-4.8/debug/jam_docs.xml
+++ /dev/null
@@ -1,3463 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<article id="jam" dirname="jam" last-revision="$Date: 2016/09/21 14:37:38 $" xmlns:xi="http://www.w3.org/2001/XInclude">
- <title>Boost.Jam : 3.1.19</title>
- <articleinfo>
- <authorgroup>
- <author>
- <firstname>Rene</firstname> <surname>Rivera</surname>
- </author>
- <author>
- <firstname>David</firstname> <surname>Abrahams</surname>
- </author>
- <author>
- <firstname>Vladimir</firstname> <surname>Prus</surname>
- </author>
- </authorgroup>
- <copyright>
- <year>2003</year> <year>2004</year> <year>2005</year> <year>2006</year> <year>2007</year>
- <holder>Rene Rivera, David Abrahams, Vladimir Prus</holder>
- </copyright>
- <legalnotice id="jam.legal">
- <para>
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
- </para>
- </legalnotice>
- <articlepurpose>
- Jam is a make(1) replacement that makes building simple things simple and building
- complicated things manageable.
- </articlepurpose>
- <articlecategory name="category:tool-build"></articlecategory>
- </articleinfo>
- <section id="jam.building">
- <title><link linkend="jam.building">Building B2</link></title>
- <para>
- Installing <literal>B2</literal> after building it is simply a matter of copying
- the generated executables someplace in your <literal>PATH</literal>. For building
- the executables there are a set of <literal>build</literal> 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 arguments:
- </para>
-<programlisting><emphasis>build</emphasis> [<emphasis>toolset</emphasis>]
-</programlisting>
- <para>
- Running the scripts without arguments will give you the best chance of success.
- On Windows platforms from a command console do:
- </para>
-<programlisting>cd <emphasis>jam source location</emphasis>
-.\build.bat
-</programlisting>
- <para>
- On Unix type platforms do:
- </para>
-<programlisting>cd <emphasis>jam source location</emphasis>
-sh ./build.sh
-</programlisting>
- <para>
- For the Boost.Jam source included with the Boost distribution the <emphasis>jam
- source location</emphasis> is <literal>BOOST_ROOT/tools/build/src/engine</literal>.
- </para>
- <para>
- 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 <literal>PATH</literal>.
- </para>
- <note>
- <para>
- The toolset used to build Boost.Jam is independent of the toolsets used for
- Boost.Build. Only one version of Boost.Jam is needed to use Boost.Build.
- </para>
- </note>
- <para>
- The supported toolsets, and whether they are auto-detected, are:
- </para>
- <table frame="all" id="jam.building.t0">
- <title>Supported Toolsets</title>
- <tgroup cols="4">
- <thead>
- <row>
- <entry>
- <para>
- Script
- </para>
- </entry>
- <entry>
- <para>
- Platform
- </para>
- </entry>
- <entry>
- <para>
- Toolset
- </para>
- </entry>
- <entry>
- <para>
- Detection and Notes
- </para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>
- <literal>build.bat</literal>
- </para>
- </entry>
- <entry>
- <para>
- Windows NT, 2000, and XP
- </para>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.codegear.com/downloads/free/cppbuilder"><literal>borland</literal></ulink></member>
- <member><ulink
- url="http://www.borland.com/">Borland</ulink> C++Builder (BCC 5.5)</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem>Common install location: &quot;<literal>C:\Borland\BCC55</literal>&quot;</listitem>
- <listitem><literal>BCC32.EXE</literal>
- in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.comeaucomputing.com/"><literal>como</literal></ulink></member>
- <member>Comeau
- Computing C/C++</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://gcc.gnu.org/"><literal>gcc</literal></ulink></member>
- <member>GNU
- GCC</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://gcc.gnu.org/"><literal>gcc-nocygwin</literal></ulink></member>
- <member>GNU
- GCC</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.intel.com/software/products/compilers/c60"><literal>intel-win32</literal></ulink></member>
- <member>Intel
- C++ Compiler for Windows</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>ICL.EXE</literal> in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.metrowerks.com/"><literal>metrowerks</literal></ulink></member>
- <member>MetroWerks
- CodeWarrior C/C++ 7.x, 8.x, 9.x</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>CWFolder</literal> variable configured</listitem>
- <listitem><literal>MWCC.EXE</literal>
- in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.mingw.org/"><literal>mingw</literal></ulink></member>
- <member>GNU
- <ulink url="http://gcc.gnu.org/">GCC</ulink> as the <ulink url="http://www.mingw.org/">MinGW</ulink>
- configuration</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem>Common install location: &quot;<literal>C:\MinGW</literal>&quot;</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://msdn.microsoft.com/visualc/"><literal>msvc</literal></ulink></member>
- <member>Microsoft
- Visual C++ 6.x</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>VCVARS32.BAT</literal> already configured</listitem>
- <listitem><literal>%MSVCDir%</literal>
- is present in environment</listitem>
- <listitem>Common install locations: &quot;<literal>%ProgramFiles%\Microsoft
- Visual Studio</literal>&quot;, &quot;<literal>%ProgramFiles%\Microsoft
- Visual C++</literal>&quot;</listitem>
- <listitem><literal>CL.EXE</literal> in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://msdn.microsoft.com/visualc/"><literal>vc7</literal></ulink></member>
- <member>Microsoft
- Visual C++ 7.x</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>VCVARS32.BAT</literal> or <literal>VSVARS32.BAT</literal>
- already configured</listitem>
- <listitem><literal>%VS71COMNTOOLS%</literal> is present in
- environment</listitem>
- <listitem><literal>%VCINSTALLDIR%</literal> is present in environment</listitem>
- <listitem>Common
- install locations: &quot;<literal>%ProgramFiles%\Microsoft Visual
- Studio .NET</literal>&quot;, &quot;<literal>%ProgramFiles%\Microsoft
- Visual Studio .NET 2003</literal>&quot;</listitem>
- <listitem><literal>CL.EXE</literal>
- in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://msdn.microsoft.com/visualc/"><literal>vc8</literal>
- and <literal>vc9</literal></ulink></member>
- <member>Microsoft Visual C++ 8.x and 9.x</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- Detection: <itemizedlist><listitem><literal>VCVARSALL.BAT</literal> already configured</listitem>
- <listitem><literal>%VS90COMNTOOLS%</literal>
- is present in environment</listitem>
- <listitem>Common install location: &quot;<literal>%ProgramFiles%\Microsoft
- Visual Studio 9</literal>&quot;</listitem>
- <listitem><literal>%VS80COMNTOOLS%</literal>
- is present in environment</listitem>
- <listitem>Common install location: &quot;<literal>%ProgramFiles%\Microsoft
- Visual Studio 8</literal>&quot;</listitem>
- <listitem><literal>CL.EXE</literal> in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- <para>
- Notes: <itemizedlist><listitem>If <literal>VCVARSALL.BAT</literal> is called to set up the
- toolset, it is passed all the extra arguments, see below for what
- those arguments are. This can be used to build, for example, a Win64
- specific version of <literal>b2</literal>. Consult the VisualStudio
- documentation for what the possible argument values to the <literal>VCVARSALL.BAT</literal>
- are.</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- <literal>build.sh</literal>
- </para>
- </entry>
- <entry>
- <para>
- Unix, Linux, Cygwin, etc.
- </para>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.hp.com/go/c++"><literal>acc</literal></ulink></member>
- <member>HP-UX
- aCC</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>aCC</literal> in <literal>PATH</literal></listitem>
- <listitem><literal>uname</literal>
- is &quot;HP-UX&quot;</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.comeaucomputing.com/"><literal>como</literal></ulink></member>
- <member>Comeau
- Computing C/C++</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem>como in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://gcc.gnu.org/"><literal>gcc</literal></ulink></member>
- <member>GNU
- GCC</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem>gcc in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.intel.com/software/products/compilers/c60l/"><literal>intel-linux</literal></ulink></member>
- <member>Intel
- C++ for Linux</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>icc</literal> in <literal>PATH</literal></listitem>
- <listitem>Common install locations:
- &quot;<literal>/opt/intel/cc/9.0</literal>&quot;, &quot;<literal>/opt/intel_cc_80</literal>&quot;,
- &quot;<literal>/opt/intel/compiler70</literal>&quot;, &quot;<literal>/opt/intel/compiler60</literal>&quot;,
- &quot;<literal>/opt/intel/compiler50</literal>&quot;</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><literal>kcc</literal></member>
- <member>Intel KAI C++</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>KCC</literal> in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.codegear.com/downloads/free/cppbuilder"><literal>kylix</literal></ulink></member>
- <member><ulink
- url="http://www.borland.com/">Borland</ulink> C++Builder</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem>bc++ in PATH</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.sgi.com/developers/devtools/languages/mipspro.html"><literal>mipspro</literal></ulink></member>
- <member>SGI
- MIPSpro C</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>uname</literal> is &quot;<literal>IRIX</literal>&quot; or
- &quot;<literal>IRIX64</literal>&quot;</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><literal>sunpro</literal></member>
- <member>Sun Workshop 6 C++</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem>Standard install location: &quot;<literal>/opt/SUNWspro</literal>&quot;</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><literal>qcc</literal></member>
- <member><ulink url="http://www.qnx.com/">QNX Neutrino</ulink></member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>uname</literal> is &quot;<literal>QNX</literal>&quot; and
- <literal>qcc</literal> in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.tru64unix.compaq.com/cplus/"><literal>true64cxx</literal></ulink></member>
- <member>Compaq
- C++ Compiler for True64 UNIX</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>uname</literal> is &quot;<literal>OSF1</literal>&quot;</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.ibm.com/software/awdtools/vacpp/"><literal>vacpp</literal></ulink></member>
- <member>IBM
- VisualAge C++</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>xlc</literal> in <literal>PATH</literal></listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- <para>
- MacOS X
- </para>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://developer.apple.com/tools/compilers.html"><literal>darwin</literal></ulink></member>
- <member>Apple
- MacOS X GCC</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem><literal>uname</literal> is &quot;<literal>Darwin</literal>&quot;</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- </entry>
- <entry>
- <para>
- Windows NT, 2000, and XP
- </para>
- </entry>
- <entry>
- <para>
- <simplelist type='vert' columns='1'><member><ulink url="http://www.mingw.org/"><literal>mingw</literal></ulink></member>
- <member>GNU
- <ulink url="http://gcc.gnu.org/">GCC</ulink> as the <ulink url="http://www.mingw.org/">MinGW</ulink>
- configuration with the MSYS shell</member>
- </simplelist>
- </para>
- </entry>
- <entry>
- <para>
- <itemizedlist><listitem>Common install location: &quot;<literal>/mingw</literal>&quot;</listitem>
- </itemizedlist>
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- 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: &quot;<literal>bin.linuxx86</literal>&quot;. The =b2[.exe]=
- executable can be used to invoke Boost.Build.
- </para>
- <para>
- The build scripts support additional invocation arguments for use by developers
- of Boost.Jam and for additional setup of the toolset. The extra arguments come
- after the toolset:
- </para>
- <itemizedlist>
- <listitem>
- <simpara>
- Arguments not in the form of an option, before option arguments, are used
- for extra setup to toolset configuration scripts.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- Arguments of the form &quot;<literal>--option</literal>&quot;, which are
- passed to the <literal>build.jam</literal> build script.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- Arguments not in the form of an option, after the options, which are targets
- for the <literal>build.jam</literal> script.
- </simpara>
- </listitem>
- </itemizedlist>
-<programlisting><emphasis>build</emphasis> [<emphasis>toolset</emphasis>] [<emphasis>setup</emphasis>*] [--<emphasis>option</emphasis>+ <emphasis>target</emphasis>*]
-</programlisting>
- <para>
- The arguments immediately after the toolset are passed directly to the setup
- script of the toolset, if available and if it needs to be invoked. This allows
- one to configure the toolset ass needed to do non-default builds of <literal>b2</literal>.
- For example to build a Win64 version with <literal>vc8</literal>. See the toolset
- descriptiona above for when particular toolsets support this.
- </para>
- <para>
- The arguments starting with the &quot;<literal>--option</literal>&quot; forms
- are passed to the <literal>build.jam</literal> script and are used to further
- customize what gets built. Options and targets supported by the <literal>build.jam</literal>
- script:
- </para>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literallayout><literal>---</literal></literallayout></term>
- <listitem>
- <para>
- Empty option when one wants to only specify a target.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>--release</literal></literallayout></term>
- <listitem>
- <para>
- The default, builds the optimized executable.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>--debug</literal></literallayout></term>
- <listitem>
- <para>
- Builds debugging versions of the executable. When built they are placed
- in their own directory &quot;<literal>bin./platform/.debug</literal>&quot;.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>--grammar</literal></literallayout></term>
- <listitem>
- <para>
- Normally the Jam language grammar parsing files are not regenerated.
- This forces building of the grammar, although it may not force the regeneration
- of the grammar parser. If the parser is out of date it will be regenerated
- and subsequently built.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>--with-python=<emphasis>path</emphasis></literal></literallayout></term>
- <listitem>
- <para>
- Enables Python integration, given a path to the Python libraries.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>--gc</literal></literallayout></term>
- <listitem>
- <para>
- Enables use of the Boehm Garbage Collector. The build will look for the
- Boehm-GC source in a &quot;boehm_gc&quot; subdirectory from the <literal>b2</literal>
- sources.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>--duma</literal></literallayout></term>
- <listitem>
- <para>
- Enables use of the DUMA (Detect Uintended Memory Access) debugging memory
- allocator. The build expects to find the DUMA source files in a &quot;duma&quot;
- subdirectory from the <literal>b2</literal> sources.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>--toolset-root=<emphasis>path</emphasis></literal></literallayout></term>
- <listitem>
- <para>
- Indicates where the toolset used to build is located. This option is
- passed in by the bootstrap (<literal>build.bat</literal> or <literal>build.sh</literal>)
- script.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>--show-locate-target</literal></literallayout></term>
- <listitem>
- <para>
- For information, prints out where it will put the built executable.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>--noassert</literal></literallayout></term>
- <listitem>
- <para>
- Disable debug assertions, even if building the debug version of the executable.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>dist</literal></literallayout></term>
- <listitem>
- <para>
- Generate packages (compressed archives) as appropriate for distribution
- in the platform, if possible.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literallayout><literal>clean</literal></literallayout></term>
- <listitem>
- <para>
- Remove all the built executables and objects.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </section>
- <section id="jam.language">
- <title><link linkend="jam.language">Language</link></title>
- <para>
- <literal>B2</literal> has an interpreted, procedural language. Statements in
- <literal>b2</literal> are rule (procedure) definitions, rule invocations, flow-of-control
- structures, variable assignments, and sundry language support.
- </para>
- <section id="jam.language.lexical">
- <title><link linkend="jam.language.lexical">Lexical Features</link></title>
- <para>
- <literal>B2</literal> treats its input files as whitespace-separated tokens,
- with two exceptions: double quotes (&quot;) can enclose whitespace to embed
- it into a token, and everything between the matching curly braces ({}) in
- the definition of a rule action is treated as a single string. A backslash
- (\) can escape a double quote, or any single whitespace character.
- </para>
- <para>
- <literal>B2</literal> requires whitespace (blanks, tabs, or newlines) to
- surround all tokens, including the colon (:) and semicolon (;) tokens.
- </para>
- <para>
- <literal>B2</literal> keywords (an mentioned in this document) are reserved
- and generally must be quoted with double quotes (&quot;) to be used as arbitrary
- tokens, such as variable or target names.
- </para>
- <para>
- Comments start with the <literal>#</literal> character and extend until the
- end of line.
- </para>
- </section>
- <section id="jam.language.target">
- <title><link linkend="jam.language.target">Targets</link></title>
- <para>
- The essential <literal>b2</literal> data entity is a target. Build targets
- are files to be updated. Source targets are the files used in updating built
- targets. Built targets and source targets are collectively referred to as
- file targets, and frequently built targets are source targets for other built
- targets. Pseudotargets are symbols representing dependencies on other targets,
- but which are not themselves associated with any real file.
- </para>
- <para>
- A file target's identifier is generally the file's name, which can be absolutely
- rooted, relative to the directory of <literal>b2</literal>'s invocation,
- or simply local (no directory). Most often it is the last case, and the actual
- file path is bound using the <literal>$(SEARCH)</literal> and <literal>$(LOCATE)</literal>
- special variables. See <link linkend="jam.language.variables.builtins.search">SEARCH
- and LOCATE Variables</link> 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 <emphasis>file(member)</emphasis> is a library
- member (usually an <literal>ar</literal>(1) archive on Unix).
- </para>
- <section id="jam.language.target.binding_detection">
- <title><link linkend="jam.language.target.binding_detection">Binding Detection</link></title>
- <para>
- Whenever a target is bound to a location in the filesystem, Boost Jam will
- look for a variable called <literal>BINDRULE</literal> (first &quot;on&quot;
- 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:
- </para>
-<programlisting>rule <emphasis>bind-rule</emphasis> ( <emphasis>target</emphasis> : <emphasis>path</emphasis> )
-</programlisting>
- <para>
- This facility is useful for correct header file scanning, since many compilers
- will search for <code><phrase role="preprocessor">#include</phrase></code>
- files first in the directory containing the file doing the <code><phrase
- role="preprocessor">#include</phrase></code> directive. <literal>$(BINDRULE)</literal>
- can be used to make a record of that directory.
- </para>
- </section>
- </section>
- <section id="jam.language.rules">
- <title><link linkend="jam.language.rules">Rules</link></title>
- <para>
- The basic <literal>b2</literal> language entity is called a rule. A rule
- is defined in two parts: the procedure and the actions. The procedure is
- a body of jam statements to be run when the rule is invoked; the actions
- are the OS shell commands to execute when updating the built targets of the
- rule.
- </para>
- <para>
- Rules can return values, which can be expanded into a list with &quot;[
- <emphasis>rule</emphasis> <emphasis>args</emphasis> ... ]&quot;. A rule's
- value is the value of its last statement, though only the following statements
- have values: 'if' (value of the leg chosen), 'switch' (value of the case
- chosen), set (value of the resulting variable), and 'return' (value of its
- arguments).
- </para>
- <para>
- The <literal>b2</literal> statements for defining and invoking rules are
- as follows:
- </para>
- <para>
- Define a rule's procedure, replacing any previous definition.
- </para>
-<programlisting>rule <emphasis>rulename</emphasis> { <emphasis>statements</emphasis> }
-</programlisting>
- <para>
- Define a rule's updating actions, replacing any previous definition.
- </para>
-<programlisting>actions [ <emphasis>modifiers</emphasis> ] <emphasis>rulename</emphasis> { <emphasis>commands</emphasis> }
-</programlisting>
- <para>
- Invoke a rule.
- </para>
-<programlisting><emphasis>rulename</emphasis> <emphasis>field1</emphasis> : <emphasis>field2</emphasis> : <emphasis>...</emphasis> : <emphasis>fieldN</emphasis> ;
-</programlisting>
- <para>
- Invoke a rule under the influence of target's specific variables..
- </para>
-<programlisting>on <emphasis>target</emphasis> <emphasis>rulename</emphasis> <emphasis>field1</emphasis> : <emphasis>field2</emphasis> : <emphasis>...</emphasis> : <emphasis>fieldN</emphasis> ;
-</programlisting>
- <para>
- Used as an argument, expands to the return value of the rule invoked.
- </para>
-<programlisting>[ <emphasis>rulename</emphasis> <emphasis>field1</emphasis> : <emphasis>field2</emphasis> : <emphasis>...</emphasis> : <emphasis>fieldN</emphasis> ]
-[ on <emphasis>target</emphasis> <emphasis>rulename</emphasis> <emphasis>field1</emphasis> : <emphasis>field2</emphasis> : <emphasis>...</emphasis> : <emphasis>fieldN</emphasis> ]
-</programlisting>
- <para>
- A rule is invoked with values in <emphasis>field1</emphasis> through <emphasis>fieldN</emphasis>.
- They may be referenced in the procedure's statements as <literal>$(1)</literal>
- through <literal>$(<emphasis>N</emphasis>)</literal> (9 max), and the first
- two only may be referenced in the action's <emphasis>commands</emphasis>
- as <literal>$(1)</literal> and <literal>$(2)</literal>. <literal>$(&lt;)</literal>
- and <literal>$(&gt;)</literal> are synonymous with <literal>$(1)</literal>
- and <literal>$(2)</literal>.
- </para>
- <para>
- Rules fall into two categories: updating rules (with actions), and pure procedure
- rules (without actions). Updating rules treat arguments <literal>$(1)</literal>
- and <literal>$(2)</literal> as built targets and sources, respectively, while
- pure procedure rules can take arbitrary arguments.
- </para>
- <para>
- When an updating rule is invoked, its updating actions are added to those
- associated with its built targets (<literal>$(1)</literal>) before the rule's
- procedure is run. Later, to build the targets in the updating phase, <emphasis>commands</emphasis>
- are passed to the OS command shell, with <literal>$(1)</literal> and <literal>$(2)</literal>
- replaced by bound versions of the target names. See Binding above.
- </para>
- <para>
- Rule invocation may be indirected through a variable:
- </para>
-<programlisting>$(<emphasis>var</emphasis>) <emphasis>field1</emphasis> : <emphasis>field2</emphasis> : <emphasis>...</emphasis> : <emphasis>fieldN</emphasis> ;
-
-on <emphasis>target</emphasis> $(<emphasis>var</emphasis>) <emphasis>field1</emphasis> : <emphasis>field2</emphasis> : <emphasis>...</emphasis> : <emphasis>fieldN</emphasis> ;
-
-[ $(<emphasis>var</emphasis>) <emphasis>field1</emphasis> : <emphasis>field2</emphasis> : <emphasis>...</emphasis> : <emphasis>fieldN</emphasis> ]
-[ on <emphasis>target</emphasis> $(<emphasis>var</emphasis>) <emphasis>field1</emphasis> : <emphasis>field2</emphasis> : <emphasis>...</emphasis> : <emphasis>fieldN</emphasis> ]
-</programlisting>
- <para>
- The variable's value names the rule (or rules) to be invoked. A rule is invoked
- for each element in the list of <literal>$(<emphasis>var</emphasis>)</literal>'s
- values. The fields <literal><emphasis>field1</emphasis> : <emphasis>field2</emphasis>
- : <emphasis>...</emphasis></literal> are passed as arguments for each invokation.
- For the [ ... ] forms, the return value is the concatenation of the return
- values for all of the invocations.
- </para>
- <section id="jam.language.rules.action_modifiers">
- <title><link linkend="jam.language.rules.action_modifiers">Action Modifiers</link></title>
- <para>
- The following action modifiers are understood:
- </para>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literal>actions bind <emphasis>vars</emphasis></literal></term>
- <listitem>
- <para>
- <literal>$(<emphasis>vars</emphasis>)</literal> will be replaced
- with bound values.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>actions existing</literal></term>
- <listitem>
- <para>
- <literal>$(&gt;)</literal> includes only source targets currently
- existing.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>actions ignore</literal></term>
- <listitem>
- <para>
- The return status of the commands is ignored.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>actions piecemeal</literal></term>
- <listitem>
- <para>
- commands are repeatedly invoked with a subset of <literal>$(&gt;)</literal>
- small enough to fit in the command buffer on this OS.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>actions quietly</literal></term>
- <listitem>
- <para>
- The action is not echoed to the standard output.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>actions together</literal></term>
- <listitem>
- <para>
- The <literal>$(&gt;)</literal> from multiple invocations of the same
- action on the same built target are glommed together.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>actions updated</literal></term>
- <listitem>
- <para>
- <literal>$(&gt;)</literal> includes only source targets themselves
- marked for updating.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </section>
- <section id="jam.language.rules.argument_lists">
- <title><link linkend="jam.language.rules.argument_lists">Argument lists</link></title>
- <para>
- You can describe the arguments accepted by a rule, and refer to them by
- name within the rule. For example, the following prints &quot;I'm sorry,
- Dave&quot; to the console:
- </para>
-<programlisting>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 ;
-</programlisting>
- <para>
- Each name in a list of formal arguments (separated by &quot;<literal>:</literal>&quot;
- in the rule declaration) is bound to a single element of the corresponding
- actual argument unless followed by one of these modifiers:
- </para>
- <informaltable frame="all">
- <tgroup cols="2">
- <thead>
- <row>
- <entry>
- <para>
- Symbol
- </para>
- </entry>
- <entry>
- <para>
- Semantics of preceding symbol
- </para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>
- <literal>?</literal>
- </para>
- </entry>
- <entry>
- <para>
- optional
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- <literal>*</literal>
- </para>
- </entry>
- <entry>
- <para>
- Bind to zero or more unbound elements of the actual argument.
- When <literal>*</literal> appears where an argument name is expected,
- any number of additional arguments are accepted. This feature
- can be used to implement &quot;varargs&quot; rules.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- <literal>+</literal>
- </para>
- </entry>
- <entry>
- <para>
- Bind to one or more unbound elements of the actual argument.
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- <para>
- The actual and formal arguments are checked for inconsistencies, which
- cause <literal>b2</literal> to exit with an error code:
- </para>
-<programlisting>### 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
-</programlisting>
- <para>
- If you omit the list of formal arguments, all checking is bypassed as in
- &quot;classic&quot; Jam. Argument lists drastically improve the reliability
- and readability of your rules, however, and are <emphasis role="bold">strongly
- recommended</emphasis> for any new Jam code you write.
- </para>
- </section>
- <section id="jam.language.rules.builtins">
- <title><link linkend="jam.language.rules.builtins">Built-in Rules</link></title>
- <para>
- <literal>B2</literal> has a growing set of 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.
- </para>
- <section id="jam.language.rules.builtins.dependency_building">
- <title><link linkend="jam.language.rules.builtins.dependency_building">Dependency
- Building</link></title>
- <section id="jam.language.rules.builtins.dependency_building._depends__">
- <title><link linkend="jam.language.rules.builtins.dependency_building._depends__"><literal>DEPENDS</literal>
- </link></title>
-<programlisting>rule DEPENDS ( <emphasis>targets1</emphasis> * : <emphasis>targets2</emphasis> * )
-</programlisting>
- <para>
- Builds a direct dependency: makes each of <emphasis>targets1</emphasis>
- depend on each of <emphasis>targets2</emphasis>. Generally, <emphasis>targets1</emphasis>
- will be rebuilt if <emphasis>targets2</emphasis> are themselves rebuilt
- or are newer than <emphasis>targets1</emphasis>.
- </para>
- </section>
- <section id="jam.language.rules.builtins.dependency_building._includes__">
- <title><link linkend="jam.language.rules.builtins.dependency_building._includes__"><literal>INCLUDES</literal>
- </link></title>
-<programlisting>rule INCLUDES ( <emphasis>targets1</emphasis> * : <emphasis>targets2</emphasis> * )
-</programlisting>
- <para>
- Builds a sibling dependency: makes any target that depends on any of
- <emphasis>targets1</emphasis> also depend on each of <emphasis>targets2</emphasis>.
- 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:
- </para>
-<programlisting>DEPENDS foo.o : foo.c ;
-INCLUDES foo.c : foo.h ;
-</programlisting>
- <para>
- &quot;<literal>foo.o</literal>&quot; depends on &quot;<literal>foo.c</literal>&quot;
- and &quot;<literal>foo.h</literal>&quot; in this example.
- </para>
- </section>
- </section>
- <section id="jam.language.rules.builtins.modifying_binding">
- <title><link linkend="jam.language.rules.builtins.modifying_binding">Modifying
- Binding</link></title>
- <para>
- The six rules <literal>ALWAYS</literal>, <literal>LEAVES</literal>,
- <literal>NOCARE</literal>, <literal>NOTFILE</literal>, <literal>NOUPDATE</literal>,
- and <literal>TEMPORARY</literal> modify the dependency graph so that
- <literal>b2</literal> treats the targets differently during its target
- binding phase. See Binding above. Normally, <literal>b2</literal> 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 the
- following rules:
- </para>
- <section id="jam.language.rules.builtins.modifying_binding._always__">
- <title><link linkend="jam.language.rules.builtins.modifying_binding._always__"><literal>ALWAYS</literal>
- </link></title>
-<programlisting>rule ALWAYS ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- Causes <emphasis>targets</emphasis> to be rebuilt regardless of whether
- they are up-to-date (they must still be in the dependency graph). This
- is used for the clean and uninstall targets, as they have no dependencies
- and would otherwise appear never to need building. It is best applied
- to targets that are also <literal>NOTFILE</literal> targets, but it
- can also be used to force a real file to be updated as well.
- </para>
- </section>
- <section id="jam.language.rules.builtins.modifying_binding._leaves__">
- <title><link linkend="jam.language.rules.builtins.modifying_binding._leaves__"><literal>LEAVES</literal>
- </link></title>
-<programlisting>rule LEAVES ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- Makes each of <emphasis>targets</emphasis> depend only on its leaf
- sources, and not on any intermediate targets. This makes it immune
- to its dependencies being updated, as the &quot;leaf&quot; dependencies
- are those without their own dependencies and without updating actions.
- This allows a target to be updated only if original source files change.
- </para>
- </section>
- <section id="jam.language.rules.builtins.modifying_binding._nocare__">
- <title><link linkend="jam.language.rules.builtins.modifying_binding._nocare__"><literal>NOCARE</literal>
- </link></title>
-<programlisting>rule NOCARE ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- Causes <literal>b2</literal> to ignore <emphasis>targets</emphasis>
- that neither can be found nor have updating actions to build them.
- Normally for such targets <literal>b2</literal> issues a warning and
- then skips other targets that depend on these missing targets. The
- <literal>HdrRule</literal> in <literal>Jambase</literal> uses <literal>NOCARE</literal>
- on the header file names found during header file scanning, to let
- <literal>b2</literal> know that the included files may not exist. For
- example, if an <code><phrase role="preprocessor">#include</phrase></code>
- is within an <code><phrase role="preprocessor">#ifdef</phrase></code>,
- the included file may not actually be around.
- </para>
- <warning>
- <para>
- For targets with build actions: if their build actions exit with
- a nonzero return code, dependent targets will still be built.
- </para>
- </warning>
- </section>
- <section id="jam.language.rules.builtins.modifying_binding._notfile__">
- <title><link linkend="jam.language.rules.builtins.modifying_binding._notfile__"><literal>NOTFILE</literal>
- </link></title>
-<programlisting>rule NOTFILE ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- Marks <emphasis>targets</emphasis> as pseudotargets and not real files.
- No timestamp is checked, and so the actions on such a target are only
- executed if the target's dependencies are updated, or if the target
- is also marked with <literal>ALWAYS</literal>. The default <literal>b2</literal>
- target &quot;<literal>all</literal>&quot; is a pseudotarget. In <literal>Jambase</literal>,
- <literal>NOTFILE</literal> is used to define several addition convenient
- pseudotargets.
- </para>
- </section>
- <section id="jam.language.rules.builtins.modifying_binding._noupdate__">
- <title><link linkend="jam.language.rules.builtins.modifying_binding._noupdate__"><literal>NOUPDATE</literal>
- </link></title>
-<programlisting>rule NOUPDATE ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- Causes the timestamps on <emphasis>targets</emphasis> to be ignored.
- This has two effects: first, once the target has been created it will
- never be updated; second, manually updating target will not cause other
- targets to be updated. In <literal>Jambase</literal>, for example,
- this rule is applied to directories by the <literal>MkDir</literal>
- rule, because <literal>MkDir</literal> only cares that the target directory
- exists, not when it has last been updated.
- </para>
- </section>
- <section id="jam.language.rules.builtins.modifying_binding._temporary__">
- <title><link linkend="jam.language.rules.builtins.modifying_binding._temporary__"><literal>TEMPORARY</literal>
- </link></title>
-<programlisting>rule TEMPORARY ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- Marks <emphasis>targets</emphasis> as temporary, allowing them to be
- removed after other targets that depend upon them have been updated.
- If a <literal>TEMPORARY</literal> target is missing, <literal>b2</literal>
- uses the timestamp of the target's parent. <literal>Jambase</literal>
- uses <literal>TEMPORARY</literal> to mark object files that are archived
- in a library after they are built, so that they can be deleted after
- they are archived.
- </para>
- </section>
- <section id="jam.language.rules.builtins.modifying_binding._fail_expected__">
- <title><link linkend="jam.language.rules.builtins.modifying_binding._fail_expected__"><literal>FAIL_EXPECTED</literal>
- </link></title>
-<programlisting>rule FAIL_EXPECTED ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- For handling targets whose build actions are expected to fail (e.g.
- when testing that assertions or compile-time type checking work properly),
- Boost Jam supplies the <literal>FAIL_EXPECTED</literal> rule in the
- same style as <literal>NOCARE</literal>, et. al. During target updating,
- the return code of the build actions for arguments to <literal>FAIL_EXPECTED</literal>
- is inverted: if it fails, building of dependent targets continues as
- though it succeeded. If it succeeds, dependent targets are skipped.
- </para>
- </section>
- <section id="jam.language.rules.builtins.modifying_binding._rmold__">
- <title><link linkend="jam.language.rules.builtins.modifying_binding._rmold__"><literal>RMOLD</literal>
- </link></title>
-<programlisting>rule RMOLD ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- <literal>B2</literal> 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 <literal>RMOLD</literal>
- rule causes its arguments to be removed if any of their dependencies
- fail to build.
- </para>
- </section>
- <section id="jam.language.rules.builtins.modifying_binding._isfile__">
- <title><link linkend="jam.language.rules.builtins.modifying_binding._isfile__"><literal>ISFILE</literal>
- </link></title>
-<programlisting>rule ISFILE ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- <literal>ISFILE</literal> marks targets as required to be files. This
- changes the way <literal>b2</literal> searches for the target such
- that it ignores matches for file system items that are not files, like
- directories. This makes it possible to avoid <code><phrase role="preprocessor">#include</phrase>
- <phrase role="string">&quot;exception&quot;</phrase></code> matching
- if one happens to have a directory named exception in the header search
- path.
- </para>
- <warning>
- <para>
- This is currently not fully implemented.
- </para>
- </warning>
- </section>
- </section>
- <section id="jam.language.rules.builtins.utility">
- <title><link linkend="jam.language.rules.builtins.utility">Utility</link></title>
- <para>
- The two rules <literal>ECHO</literal> and <literal>EXIT</literal> are
- utility rules, used only in <literal>b2</literal>'s parsing phase.
- </para>
- <section id="jam.language.rules.builtins.utility._echo__">
- <title><link linkend="jam.language.rules.builtins.utility._echo__"><literal>ECHO</literal>
- </link></title>
-<programlisting>rule ECHO ( <emphasis>args</emphasis> * )
-</programlisting>
- <para>
- Blurts out the message <emphasis>args</emphasis> to stdout.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._exit__">
- <title><link linkend="jam.language.rules.builtins.utility._exit__"><literal>EXIT</literal>
- </link></title>
-<programlisting>rule EXIT ( <emphasis>message</emphasis> * : <emphasis>result-value</emphasis> ? )
-</programlisting>
- <para>
- Blurts out the <emphasis>message</emphasis> to stdout and then exits
- with a failure status if no <emphasis>result-value</emphasis> is given,
- otherwise it exits with the given <emphasis>result-value</emphasis>.
- </para>
- <para>
- &quot;<literal>Echo</literal>&quot;, &quot;<literal>echo</literal>&quot;,
- &quot;<literal>Exit</literal>&quot;, and &quot;<literal>exit</literal>&quot;
- are accepted as aliases for <literal>ECHO</literal> and <literal>EXIT</literal>,
- since it is hard to tell that these are built-in rules and not part
- of the language, like &quot;<literal>include</literal>&quot;.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._glob__">
- <title><link linkend="jam.language.rules.builtins.utility._glob__"><literal>GLOB</literal>
- </link></title>
- <para>
- The <literal>GLOB</literal> rule does filename globbing.
- </para>
-<programlisting>rule GLOB ( <emphasis>directories</emphasis> * : <emphasis>patterns</emphasis> * : <emphasis>downcase-opt</emphasis> ? )
-</programlisting>
- <para>
- Using the same wildcards as for the patterns in the switch statement.
- It is invoked by being used as an argument to a rule invocation inside
- of &quot;=[ ]=&quot;. For example: &quot;<literal>FILES = [ GLOB dir1
- dir2 : *.c *.h ]</literal>&quot; sets <literal>FILES</literal> to the
- list of C source and header files in <literal>dir1</literal> and <literal>dir2</literal>.
- The resulting filenames are the full pathnames, including the directory,
- but the pattern is applied only to the file name without the directory.
- </para>
- <para>
- If <emphasis>downcase-opt</emphasis> is supplied, filenames are converted
- to all-lowercase before matching against the pattern; you can use this
- to do case-insensitive matching using lowercase patterns. The paths
- returned will still have mixed case if the OS supplies them. On Windows
- NT and Cygwin, and OpenVMS, filenames are always downcased before matching.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._glob_archive__">
- <title><link linkend="jam.language.rules.builtins.utility._glob_archive__"><literal>GLOB_ARCHIVE</literal>
- </link></title>
- <para>
- The <literal>GLOB_ARCHIVE</literal> rule does name globbing of object
- archive members.
- </para>
-<programlisting>rule GLOB_ARCHIVE ( <emphasis>archives</emphasis> * : <emphasis>member-patterns</emphasis> * : <emphasis>downcase-opt</emphasis> ? : <emphasis>symbol-patterns</emphasis> ? )
-</programlisting>
- <para>
- Similarly to <literal>GLOB</literal>, this rule is used to match names
- of member files in an archive (static object library). List of successfully
- matched members is returned or null otherwise. The resulting member
- names are qualified with pathname of the containing archive in the
- form <literal>archive-path(member-name)</literal>. Member patterns
- are for matching member name only; when no wildcards specified -- an
- exact match is assumed. Member names generally correspond to object
- file names and as such are platform-specific -- use of platform-defined
- object suffix in the matching patterns can allow for portability.
- </para>
- <para>
- If <emphasis>downcase-opt</emphasis> is supplied, the member names
- are converted to all-lowercase before matching against the pattern;
- you can use this to do case-insensitive matching using lowercase patterns.
- The paths returned will still have mixed case if the OS supplies them.
- On Windows NT, Cygwin, and OpenVMS, filenames are always downcased
- before matching.
- </para>
- <para>
- Additionally, members can be matched with symbol/function patterns
- on supported platforms (currently, OpenVMS only). In this case, members
- containing the matching symbols are returned. Member and symbol patterns
- are applied as OR conditions, with member patterns taking precedence.
- On unsupported platforms, null is returned when any symbol patterns
- are specified.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._match__">
- <title><link linkend="jam.language.rules.builtins.utility._match__"><literal>MATCH</literal>
- </link></title>
- <para>
- The <literal>MATCH</literal> rule does pattern matching.
- </para>
-<programlisting>rule MATCH ( <emphasis>regexps</emphasis> + : <emphasis>list</emphasis> * )
-</programlisting>
- <para>
- Matches the <literal>egrep</literal>(1) style regular expressions
- <emphasis>regexps</emphasis> against the strings in <emphasis>list</emphasis>.
- The result is a list of matching <literal>()</literal> subexpressions
- for each string in <emphasis>list</emphasis>, and for each regular
- expression in <emphasis>regexps</emphasis>.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._backtrace__">
- <title><link linkend="jam.language.rules.builtins.utility._backtrace__"><literal>BACKTRACE</literal>
- </link></title>
-<programlisting>rule BACKTRACE ( )
-</programlisting>
- <para>
- Returns a list of quadruples: <emphasis>filename</emphasis> <emphasis>line</emphasis>
- <emphasis>module</emphasis> <emphasis>rulename</emphasis>..., describing
- each shallower level of the call stack. This rule can be used to generate
- useful diagnostic messages from Jam rules.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._update__">
- <title><link linkend="jam.language.rules.builtins.utility._update__"><literal>UPDATE</literal>
- </link></title>
-<programlisting>rule UPDATE ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- 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. This is now enabled again but with additional changes
- to the <literal>UPDATE</literal> rule to allow for the flexibility
- of changing the list of targets to update. The UPDATE rule has two
- effects:
- </para>
- <orderedlist>
- <listitem>
- <simpara>
- It clears the list of targets to update, and
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- Causes the specified targets to be updated.
- </simpara>
- </listitem>
- </orderedlist>
- <para>
- If no target was specified with the <literal>UPDATE</literal> rule,
- no targets will be updated. To support changing of the update list
- in more useful ways, the rule also returns the targets previously in
- the update list. This makes it possible to add targets as such:
- </para>
-<programlisting>local previous-updates = [ UPDATE ] ;
-UPDATE $(previous-updates) a-new-target ;
-</programlisting>
- </section>
- <section id="jam.language.rules.builtins.utility._w32_getreg__">
- <title><link linkend="jam.language.rules.builtins.utility._w32_getreg__"><literal>W32_GETREG</literal>
- </link></title>
-<programlisting>rule W32_GETREG ( <emphasis>path</emphasis> : <emphasis>data</emphasis> ? )
-</programlisting>
- <para>
- Defined only for win32 platform. It reads the registry of Windows.
- '<emphasis>path</emphasis>' is the location of the information, and
- '<emphasis>data</emphasis>' is the name of the value which we want
- to get. If '<emphasis>data</emphasis>' is omitted, the default value
- of '<emphasis>path</emphasis>' will be returned. The '<emphasis>path</emphasis>'
- value must conform to MS key path format and must be prefixed with
- one of the predefined root keys. As usual,
- </para>
- <itemizedlist>
- <listitem>
- <simpara>
- '<literal>HKLM</literal>' is equivalent to '<literal>HKEY_LOCAL_MACHINE</literal>'.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- '<literal>HKCU</literal>' is equivalent to '<literal>HKEY_CURRENT_USER</literal>'.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- '<literal>HKCR</literal>' is equivalent to '<literal>HKEY_CLASSES_ROOT</literal>'.
- </simpara>
- </listitem>
- </itemizedlist>
- <para>
- Other predefined root keys are not supported.
- </para>
- <para>
- Currently supported data types : '<literal>REG_DWORD</literal>', '<literal>REG_SZ</literal>',
- '<literal>REG_EXPAND_SZ</literal>', '<literal>REG_MULTI_SZ</literal>'.
- The data with '<literal>REG_DWORD</literal>' type will be turned into
- a string, '<literal>REG_MULTI_SZ</literal>' into a list of strings,
- and for those with '<literal>REG_EXPAND_SZ</literal>' type environment
- variables in it will be replaced with their defined values. The data
- with '<literal>REG_SZ</literal>' type and other unsupported types will
- be put into a string without modification. If it can't receive the
- value of the data, it just return an empty list. For example,
- </para>
-<programlisting>local PSDK-location =
- [ W32_GETREG HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MicrosoftSDK\\Directories : &quot;Install Dir&quot; ] ;
-</programlisting>
- </section>
- <section id="jam.language.rules.builtins.utility._w32_getregnames__">
- <title><link linkend="jam.language.rules.builtins.utility._w32_getregnames__"><literal>W32_GETREGNAMES</literal>
- </link></title>
-<programlisting>rule W32_GETREGNAMES ( <emphasis>path</emphasis> : <emphasis>result-type</emphasis> )
-</programlisting>
- <para>
- Defined only for win32 platform. It reads the registry of Windows.
- '<emphasis>path</emphasis>' is the location of the information, and
- '<emphasis>result-type</emphasis>' is either '<literal>subkeys</literal>'
- or '<literal>values</literal>'. For more information on '<emphasis>path</emphasis>'
- format and constraints, please see <literal>W32_GETREG</literal>.
- </para>
- <para>
- Depending on '<emphasis>result-type</emphasis>', the rule returns one
- of the following:
- </para>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literal>subkeys</literal></term>
- <listitem>
- <para>
- Names of all direct subkeys of '<emphasis>path</emphasis>'.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>values</literal></term>
- <listitem>
- <para>
- Names of values contained in registry key given by '<emphasis>path</emphasis>'.
- The &quot;default&quot; value of the key appears in the returned
- list only if its value has been set in the registry.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>
- If '<emphasis>result-type</emphasis>' is not recognized, or requested
- data cannot be retrieved, the rule returns an empty list. Example:
- </para>
-<programlisting>local key = &quot;HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths&quot; ;
-local subkeys = [ W32_GETREGNAMES &quot;$(key)&quot; : subkeys ] ;
-for local subkey in $(subkeys)
-{
- local values = [ W32_GETREGNAMES &quot;$(key)\\$(subkey)&quot; : values ] ;
- for local value in $(values)
- {
- local data = [ W32_GETREG &quot;$(key)\\$(subkey)&quot; : &quot;$(value)&quot; ] ;
- ECHO &quot;Registry path: &quot; $(key)\\$(subkey) &quot;:&quot; $(value) &quot;=&quot; $(data) ;
- }
-}
-</programlisting>
- </section>
- <section id="jam.language.rules.builtins.utility._shell__">
- <title><link linkend="jam.language.rules.builtins.utility._shell__"><literal>SHELL</literal>
- </link></title>
-<programlisting>rule SHELL ( <emphasis>command</emphasis> : * )
-</programlisting>
- <para>
- <literal>SHELL</literal> executes <emphasis>command</emphasis>, and
- then returns the standard output of <emphasis>command</emphasis>.
- <literal>SHELL</literal> only works on platforms with a <literal>popen()</literal>
- function in the C library. On platforms without a working <literal>popen()</literal>
- function, <literal>SHELL</literal> is implemented as a no-op. <literal>SHELL</literal>
- works on Unix, MacOS X, and most Windows compilers. <literal>SHELL</literal>
- is a no-op on Metrowerks compilers under Windows. There is a variable
- set of allowed options as additional arguments:
- </para>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literal>exit-status</literal></term>
- <listitem>
- <para>
- In addition to the output the result status of the executed command
- is returned as a second element of the result.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>no-output</literal></term>
- <listitem>
- <para>
- Don't capture the output of the command. Instead an empty (&quot;&quot;)
- string value is returned in place of the output.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>strip-eol</literal></term>
- <listitem>
- <para>
- Remove trailing end-of-line character from output, if any.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>
- Because the Perforce/Jambase defines a <literal>SHELL</literal> rule
- which hides the builtin rule, <literal>COMMAND</literal> can be used
- as an alias for <literal>SHELL</literal> in such a case.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._md5__">
- <title><link linkend="jam.language.rules.builtins.utility._md5__"><literal>MD5</literal>
- </link></title>
-<programlisting>rule MD5 ( <emphasis>string</emphasis> )
-</programlisting>
- <para>
- <literal>MD5</literal> computes the MD5 hash of the string passed as
- paramater and returns it.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._split_by_characters__">
- <title><link linkend="jam.language.rules.builtins.utility._split_by_characters__"><literal>SPLIT_BY_CHARACTERS</literal>
- </link></title>
-<programlisting>rule SPLIT_BY_CHARACTERS ( <emphasis>string</emphasis> : <emphasis>delimiters</emphasis> )
-</programlisting>
- <para>
- <literal>SPLIT_BY_CHARACTERS</literal> splits the specified <emphasis>string</emphasis>
- on any delimiter character present in <emphasis>delimiters</emphasis>
- and returns the resulting list.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._precious__">
- <title><link linkend="jam.language.rules.builtins.utility._precious__"><literal>PRECIOUS</literal>
- </link></title>
-<programlisting>rule PRECIOUS ( <emphasis>targets</emphasis> * )
-</programlisting>
- <para>
- The <literal>PRECIOUS</literal> rule specifies that each of the targets
- passed as the arguments should not be removed even if the command updating
- that target fails.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._pad__">
- <title><link linkend="jam.language.rules.builtins.utility._pad__"><literal>PAD</literal>
- </link></title>
-<programlisting>rule PAD ( <emphasis>string</emphasis> : <emphasis>width</emphasis> )
-</programlisting>
- <para>
- If <emphasis>string</emphasis> is shorter than <emphasis>width</emphasis>
- characters, pads it with whitespace characters on the right, and returns
- the result. Otherwise, returns <emphasis>string</emphasis> unmodified.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._file_open__">
- <title><link linkend="jam.language.rules.builtins.utility._file_open__"><literal>FILE_OPEN</literal>
- </link></title>
-<programlisting>rule FILE_OPEN ( <emphasis>filename</emphasis> : <emphasis>mode</emphasis> )
-</programlisting>
- <para>
- The <literal>FILE_OPEN</literal> rule opens the specified file and
- returns a file descriptor. The <emphasis>mode</emphasis> parameter
- can be either &quot;w&quot; or &quot;r&quot;. Note that at present,
- only the <literal>UPDATE_NOW</literal> rule can use the resulting file
- descriptor number.
- </para>
- </section>
- <section id="jam.language.rules.builtins.utility._update_now__">
- <title><link linkend="jam.language.rules.builtins.utility._update_now__"><literal>UPDATE_NOW</literal>
- </link></title>
-<programlisting>rule UPDATE_NOW ( <emphasis>targets</emphasis> * : <emphasis>log</emphasis> ? : <emphasis>ignore-minus-n</emphasis> ? )
-</programlisting>
- <para>
- The <literal>UPDATE_NOW</literal> caused the specified targets to be
- updated immediately. If update was successfull, non-empty string is
- returned. The <emphasis>log</emphasis> parameter, if present, specifies
- a descriptor of a file where all output from building is redirected.
- If the <emphasis>ignore-minus-n</emphasis> parameter is specified,
- the targets are updated even if the <literal>-n</literal> parameter
- is specified on the command line.
- </para>
- </section>
- </section>
- </section>
- </section>
- <section id="jam.language.flow_of_control">
- <title><link linkend="jam.language.flow_of_control">Flow-of-Control</link></title>
- <para>
- <literal>B2</literal> has several simple flow-of-control statements:
- </para>
-<programlisting>for <emphasis>var</emphasis> in <emphasis>list</emphasis> { <emphasis>statements</emphasis> }
-</programlisting>
- <para>
- Executes <emphasis>statements</emphasis> for each element in <emphasis>list</emphasis>,
- setting the variable <emphasis>var</emphasis> to the element value.
- </para>
-<programlisting>if <emphasis>cond</emphasis> { <emphasis>statements</emphasis> }
-[ else { <emphasis>statements</emphasis> } ]
-</programlisting>
- <para>
- Does the obvious; the <literal>else</literal> clause is optional. <emphasis>cond</emphasis>
- is built of:
- </para>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literal><emphasis>a</emphasis></literal></term>
- <listitem>
- <para>
- true if any <emphasis>a</emphasis> element is a non-zero-length string
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal><emphasis>a</emphasis> = <emphasis>b</emphasis></literal></term>
- <listitem>
- <para>
- list <emphasis>a</emphasis> matches list <emphasis>b</emphasis> string-for-string
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal><emphasis>a</emphasis> != <emphasis>b</emphasis></literal></term>
- <listitem>
- <para>
- list <emphasis>a</emphasis> does not match list <emphasis>b</emphasis>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal><emphasis>a</emphasis> &lt; <emphasis>b</emphasis></literal></term>
- <listitem>
- <para>
- <emphasis>a[i]</emphasis> string is less than <emphasis>b[i]</emphasis>
- string, where <emphasis>i</emphasis> is first mismatched element in
- lists <emphasis>a</emphasis> and <emphasis>b</emphasis>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal><emphasis>a</emphasis> &lt;= <emphasis>b</emphasis></literal></term>
- <listitem>
- <para>
- every <emphasis>a</emphasis> string is less than or equal to its <emphasis>b</emphasis>
- counterpart
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal><emphasis>a</emphasis> &gt; <emphasis>b</emphasis></literal></term>
- <listitem>
- <para>
- <emphasis>a[i]</emphasis> string is greater than <emphasis>b[i]</emphasis>
- string, where <emphasis>i</emphasis> is first mismatched element
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal><emphasis>a</emphasis> &gt;= <emphasis>b</emphasis></literal></term>
- <listitem>
- <para>
- every <emphasis>a</emphasis> string is greater than or equal to its
- <emphasis>b</emphasis> counterpart
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal><emphasis>a</emphasis> in <emphasis>b</emphasis></literal></term>
- <listitem>
- <para>
- true if all elements of <emphasis>a</emphasis> can be found in <emphasis>b</emphasis>,
- or if <emphasis>a</emphasis> has no elements
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>! <emphasis>cond</emphasis></literal></term>
- <listitem>
- <para>
- condition not true
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal><emphasis>cond</emphasis> &amp;&amp; <emphasis>cond</emphasis></literal></term>
- <listitem>
- <para>
- conjunction
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal><emphasis>cond</emphasis> || <emphasis>cond</emphasis></literal></term>
- <listitem>
- <para>
- disjunction
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>( <emphasis>cond</emphasis> )</literal></term>
- <listitem>
- <para>
- precedence grouping
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-<programlisting>include <emphasis>file</emphasis> ;
-</programlisting>
- <para>
- Causes <literal>b2</literal> to read the named <emphasis>file</emphasis>.
- The <emphasis>file</emphasis> is bound like a regular target (see Binding
- above) but unlike a regular target the include <emphasis>file</emphasis>
- cannot be built.
- </para>
- <para>
- The include <emphasis>file</emphasis> 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, <literal>b2</literal> infers no scope
- boundaries from included files.
- </para>
-<programlisting>local <emphasis>vars</emphasis> [ = <emphasis>values</emphasis> ] ;
-</programlisting>
- <para>
- Creates new <emphasis>vars</emphasis> inside to the enclosing <literal>{}</literal>
- 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 <emphasis>vars</emphasis> are initialized to <emphasis>values</emphasis>
- if present, or left uninitialized otherwise.
- </para>
-<programlisting>return <emphasis>values</emphasis> ;
-</programlisting>
- <para>
- Within a rule body, the return statement sets the return value for an invocation
- of the rule and returns to the caller.
- </para>
-<programlisting>switch <emphasis>value</emphasis>
-{
- case <emphasis>pattern1</emphasis> : <emphasis>statements</emphasis> ;
- case <emphasis>pattern2</emphasis> : <emphasis>statements</emphasis> ;
- ...
-}
-</programlisting>
- <para>
- The switch statement executes zero or one of the enclosed <emphasis>statements</emphasis>,
- depending on which, if any, is the first case whose <emphasis>pattern</emphasis>
- matches <emphasis>value</emphasis>. The <emphasis>pattern</emphasis> values
- are not variable-expanded. The pattern values may include the following wildcards:
- </para>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literal>?</literal></term>
- <listitem>
- <para>
- match any single character
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>*</literal></term>
- <listitem>
- <para>
- match zero or more characters
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>[<emphasis>chars</emphasis>]</literal></term>
- <listitem>
- <para>
- match any single character in <emphasis>chars</emphasis>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>[^<emphasis>chars</emphasis>]</literal></term>
- <listitem>
- <para>
- match any single character not in <emphasis>chars</emphasis>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>\<emphasis>x</emphasis></literal></term>
- <listitem>
- <para>
- match <emphasis>x</emphasis> (escapes the other wildcards)
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-<programlisting>while <emphasis>cond</emphasis> { <emphasis>statements</emphasis> }
-</programlisting>
- <para>
- Repeatedly execute <emphasis>statements</emphasis> while <emphasis>cond</emphasis>
- remains true upon entry. (See the description of <emphasis>cond</emphasis>
- expression syntax under if, above).
- </para>
-<programlisting>break ;
-</programlisting>
- <para>
- Immediately exits the nearest enclosing while or for loop.
- </para>
-<programlisting>continue ;
-</programlisting>
- <para>
- Jumps to the top of the nearest enclosing while or for loop.
- </para>
- </section>
- <section id="jam.language.variables">
- <title><link linkend="jam.language.variables">Variables</link></title>
- <para>
- <literal>B2</literal> 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
- <literal>$(<emphasis>variable</emphasis>)</literal>.
- </para>
- <para>
- Variables are either global or target-specific. In the latter case, the variable
- takes on the given value only during the updating of the specific target.
- </para>
- <para>
- A variable is defined with:
- </para>
-<programlisting><emphasis>variable</emphasis> = <emphasis>elements</emphasis> ;
-<emphasis>variable</emphasis> += <emphasis>elements</emphasis> ;
-<emphasis>variable</emphasis> on <emphasis>targets</emphasis> = <emphasis>elements</emphasis> ;
-<emphasis>variable</emphasis> on <emphasis>targets</emphasis> += <emphasis>elements</emphasis> ;
-<emphasis>variable</emphasis> default = <emphasis>elements</emphasis> ;
-<emphasis>variable</emphasis> ?= <emphasis>elements</emphasis> ;
-</programlisting>
- <para>
- The first two forms set <emphasis>variable</emphasis> globally. The third
- and forth forms set a target-specific variable. The <literal>=</literal>
- operator replaces any previous elements of <emphasis>variable</emphasis>
- with <emphasis>elements</emphasis>; the <literal>+=</literal> operation adds
- <emphasis>elements</emphasis> to <emphasis>variable</emphasis>'s list of
- elements. The final two forms are synonymous: they set <emphasis>variable</emphasis>
- globally, but only if it was previously unset.
- </para>
- <para>
- Variables referenced in updating commands will be replaced with their values;
- target-specific values take precedence over global values. Variables passed
- as arguments (<literal>$(1)</literal> and <literal>$(2)</literal>) to actions
- are replaced with their bound values; the &quot;<literal>bind</literal>&quot;
- modifier can be used on actions to cause other variables to be replaced with
- bound values. See Action Modifiers above.
- </para>
- <para>
- <literal>B2</literal> variables are not re-exported to the environment of
- the shell that executes the updating actions, but the updating actions can
- reference <literal>b2</literal> variables with <literal>$(<emphasis>variable</emphasis>)</literal>.
- </para>
- <section id="jam.language.variables.expansion">
- <title><link linkend="jam.language.variables.expansion">Variable Expansion</link></title>
- <para>
- During parsing, <literal>b2</literal> 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 <literal>$(<emphasis>v</emphasis>)</literal> or <literal>$(<emphasis>vm</emphasis>)</literal>,
- where <emphasis>v</emphasis> is the variable name, and <emphasis>m</emphasis>
- are optional modifiers.
- </para>
- <para>
- 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.
- </para>
- <para>
- The result of a token after variable expansion is the <emphasis>product</emphasis>
- of the components of the token, where each component is a literal substring
- or a list substituting a variable reference. For example:
- </para>
-<programlisting>$(X) -&gt; a b c
-t$(X) -&gt; ta tb tc
-$(X)z -&gt; az bz cz
-$(X)-$(X) -&gt; a-a a-b a-c b-a b-b b-c c-a c-b c-c
-</programlisting>
- <para>
- The variable name and modifiers can themselves contain a variable reference,
- and this partakes of the product as well:
- </para>
-<programlisting>$(X) -&gt; a b c
-$(Y) -&gt; 1 2
-$(Z) -&gt; X Y
-$($(Z)) -&gt; a b c 1 2
-</programlisting>
- <para>
- Because of this product expansion, 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:
- </para>
-<programlisting>$(X) -&gt; a &quot;&quot;
-$(Y) -&gt; &quot;&quot; 1
-$(Z) -&gt;
--$(X)$(Y)- -&gt; -a- -a1- -- -1-
--$(X)$(Z)- -&gt;
-</programlisting>
- <para>
- 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. The modifiers are:
- </para>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literal>[<emphasis>n</emphasis>]</literal></term>
- <listitem>
- <para>
- Select element number <emphasis>n</emphasis> (starting at 1). If
- the variable contains fewer than <emphasis>n</emphasis> elements,
- the result is a zero-element list. <emphasis>n</emphasis> can be
- negative in which case the element number <emphasis>n</emphasis>
- from the last leftward is returned.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>[<emphasis>n</emphasis>-<emphasis>m</emphasis>]</literal></term>
- <listitem>
- <para>
- Select elements number <emphasis>n</emphasis> through <emphasis>m</emphasis>.
- <emphasis>n</emphasis> and <emphasis>m</emphasis> can be negative
- in which case they refer to elements counting from the last leftward.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>[<emphasis>n</emphasis>-]</literal></term>
- <listitem>
- <para>
- Select elements number <emphasis>n</emphasis> through the last.
- <emphasis>n</emphasis> can be negative in which case it refers to
- the element counting from the last leftward.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:B</literal></term>
- <listitem>
- <para>
- Select filename base.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:S</literal></term>
- <listitem>
- <para>
- Select (last) filename suffix.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:M</literal></term>
- <listitem>
- <para>
- Select archive member name.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:D</literal></term>
- <listitem>
- <para>
- Select directory path.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:P</literal></term>
- <listitem>
- <para>
- Select parent directory.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:G</literal></term>
- <listitem>
- <para>
- Select grist.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:U</literal></term>
- <listitem>
- <para>
- Replace lowercase characters with uppercase.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:L</literal></term>
- <listitem>
- <para>
- Replace uppercase characters with lowercase.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:T</literal></term>
- <listitem>
- <para>
- Converts all back-slashes (&quot;\&quot;) to forward slashes (&quot;/&quot;).
- For example
-<programlisting><phrase role="identifier">x</phrase> <phrase role="special">=</phrase> <phrase role="string">&quot;C:\\Program Files\\Borland&quot;</phrase> <phrase role="special">;</phrase> <phrase role="identifier">ECHO</phrase> <phrase role="error">$</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">:</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase> <phrase role="special">;</phrase>
-</programlisting>
- prints <literal>&quot;C:/Program Files/Borland&quot;</literal>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:W</literal></term>
- <listitem>
- <para>
- When invoking Windows-based tools from <ulink url="http://www.cygwin.com/">Cygwin</ulink>
- it can be important to pass them true windows-style paths. The <literal>:W</literal>
- modifier, <emphasis role="bold">under Cygwin only</emphasis>, turns
- a cygwin path into a Win32 path using the <ulink url="http://www.cygwin.com/cygwin-api/func-cygwin-conv-to-win32-path.html"><literal>cygwin_conv_to_win32_path</literal></ulink>
- function. For example
-<programlisting><phrase role="identifier">x</phrase> <phrase role="special">=</phrase> <phrase role="string">&quot;/cygdrive/c/Program Files/Borland&quot;</phrase> <phrase role="special">;</phrase> <phrase role="identifier">ECHO</phrase> <phrase role="error">$</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">:</phrase><phrase role="identifier">W</phrase><phrase role="special">)</phrase> <phrase role="special">;</phrase>
-</programlisting>
- prints <literal>&quot;C:\Program Files\Borland&quot;</literal> on
- Cygwin
- </para>
- <para>
- Similarly, when used on OpenVMS, the <literal>:W</literal> modifier
- translates a POSIX-style path into native VMS-style format using
- <literal>decc$to_vms</literal> CRTL function. This modifier is generally
- used inside action blocks to properly specify file paths in VMS-specific
- commands. For example
-<programlisting><phrase role="identifier">x</phrase> <phrase role="special">=</phrase> <phrase role="string">&quot;subdir/filename.c&quot;</phrase> <phrase role="special">;</phrase> <phrase role="identifier">ECHO</phrase> <phrase role="error">$</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">:</phrase><phrase role="identifier">W</phrase><phrase role="special">)</phrase> <phrase role="special">;</phrase>
-</programlisting>
- prints <literal>&quot;[.subdir]filename.c&quot;</literal> on OpenVMS
- </para>
- <para>
- On other platforms, the string is unchanged.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:<emphasis>chars</emphasis></literal></term>
- <listitem>
- <para>
- Select the components listed in <emphasis>chars</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:G=<emphasis>grist</emphasis></literal></term>
- <listitem>
- <para>
- Replace grist with <emphasis>grist</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:D=<emphasis>path</emphasis></literal></term>
- <listitem>
- <para>
- Replace directory with <emphasis>path</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:B=<emphasis>base</emphasis></literal></term>
- <listitem>
- <para>
- Replace the base part of file name with <emphasis>base</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:S=<emphasis>suf</emphasis></literal></term>
- <listitem>
- <para>
- Replace the suffix of file name with <emphasis>suf</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:M=<emphasis>mem</emphasis></literal></term>
- <listitem>
- <para>
- Replace the archive member name with <emphasis>mem</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:R=<emphasis>root</emphasis></literal></term>
- <listitem>
- <para>
- Prepend <emphasis>root</emphasis> to the whole file name, if not
- already rooted.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:E=<emphasis>value</emphasis></literal></term>
- <listitem>
- <para>
- Assign <emphasis>value</emphasis> to the variable if it is unset.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>:J=<emphasis>joinval</emphasis></literal></term>
- <listitem>
- <para>
- Concatentate list elements into single element, separated by <emphasis>joinval</emphasis>'.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>
- On VMS, <literal>$(var:P)</literal> is the parent directory of <literal>$(var:D)</literal>.
- </para>
- </section>
- <section id="jam.language.variables.local_for_loop_variables">
- <title><link linkend="jam.language.variables.local_for_loop_variables">Local
- For Loop Variables</link></title>
- <para>
- Boost Jam allows you to declare a local for loop control variable right
- in the loop:
- </para>
-<programlisting>x = 1 2 3 ;
-y = 4 5 6 ;
-for <emphasis role="bold">local</emphasis> y in $(x)
-{
- ECHO $(y) ; # prints &quot;1&quot;, &quot;2&quot;, or &quot;3&quot;
-}
-ECHO $(y) ; # prints &quot;4 5 6&quot;
-</programlisting>
- </section>
- <section id="jam.language.variables.atfile">
- <title><link linkend="jam.language.variables.atfile">Generated File Expansion</link></title>
- <para>
- During expansion of expressions <literal>b2</literal> also looks for subexpressions
- of the form <literal>@(filename:E=filecontents)</literal> and replaces
- the expression with <literal>filename</literal> after creating the given
- file with the contents set to <literal>filecontents</literal>. This is
- useful for creating compiler response files, and other &quot;internal&quot;
- files. The expansion works both during parsing and action execution. Hence
- it is possible to create files during any of the three build phases.
- </para>
- </section>
- <section id="jam.language.variables.builtins">
- <title><link linkend="jam.language.variables.builtins">Built-in Variables</link></title>
- <para>
- This section discusses variables that have special meaning to <literal>b2</literal>.
- All of these must be defined or used in the global module -- using those
- variables inside a named module will not have the desired effect. See
- <link linkend="jam.language.modules">Modules</link>.
- </para>
- <section id="jam.language.variables.builtins.search">
- <title><link linkend="jam.language.variables.builtins.search">SEARCH and
- LOCATE</link></title>
- <para>
- These two variables control the binding of file target names to locations
- in the file system. Generally, <literal>$(SEARCH)</literal> is used to
- find existing sources while <literal>$(LOCATE)</literal> is used to fix
- the location for built targets.
- </para>
- <para>
- 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 <literal>$(LOCATE)</literal> and <literal>$(SEARCH)</literal>
- alter this:
- </para>
- <itemizedlist>
- <listitem>
- <simpara>
- If <literal>$(LOCATE)</literal> is set then the target is bound relative
- to the first directory in <literal>$(LOCATE)</literal>. Only the
- first element is used for binding.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- If <literal>$(SEARCH)</literal> is set then the target is bound to
- the first directory in <literal>$(SEARCH)</literal> where the target
- file already exists.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- If the <literal>$(SEARCH)</literal> search fails, the target is bound
- relative to the current directory anyhow.
- </simpara>
- </listitem>
- </itemizedlist>
- <para>
- Both <literal>$(SEARCH)</literal> and <literal>$(LOCATE)</literal> should
- be set target-specific and not globally. If they were set globally,
- <literal>b2</literal> 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
- <literal>$(SEARCH)</literal> or <literal>$(LOCATE)</literal> directly.
- Almost all of the rules defined in Jambase set <literal>$(SEARCH)</literal>
- and <literal>$(LOCATE)</literal> to sensible values for sources they
- are looking for and targets they create, respectively.
- </para>
- </section>
- <section id="jam.language.variables.builtins.hdrscan">
- <title><link linkend="jam.language.variables.builtins.hdrscan">HDRSCAN
- and HDRRULE</link></title>
- <para>
- These two variables control header file scanning. <literal>$(HDRSCAN)</literal>
- is an <literal>egrep(1)</literal> pattern, with ()'s surrounding the
- file name, used to find file inclusion statements in source files. <literal>Jambase</literal>
- uses <literal>$(HDRPATTERN)</literal> as the pattern for <literal>$(HDRSCAN)</literal>.
- <literal>$(HDRRULE)</literal> 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. This is the only place where <literal>b2</literal> invokes
- a rule through a variable setting.
- </para>
- <para>
- Both <literal>$(HDRSCAN)</literal> and <literal>$(HDRRULE)</literal>
- 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.
- </para>
- <para>
- The scanning for header file inclusions is not exact, but it is at least
- dynamic, so there is no need to run something like <literal>makedepend(GNU)</literal>
- 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 <code><phrase role="preprocessor">#include</phrase></code>
- lines are inside <code><phrase role="preprocessor">#ifdefs</phrase></code>
- or other conditional logic. In <literal>Jambase</literal>, <literal>HdrRule</literal>
- applies the <literal>NOCARE</literal> rule to each header file found
- during scanning so that if the file isn't present yet doesn't cause the
- compilation to fail, <literal>b2</literal> won't care.
- </para>
- <para>
- 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 <literal>Jam</literal>
- language itself does).
- </para>
- </section>
- <section id="jam.language.variables.builtins.semaphores">
- <title><link linkend="jam.language.variables.builtins.semaphores">Semaphores</link></title>
- <para>
- It is sometimes desirable to disallow parallel execution of some actions.
- For example:
- </para>
- <itemizedlist>
- <listitem>
- <simpara>
- Old versions of yacc use files with fixed names. So, running two
- yacc actions is dangerous.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- One might want to perform parallel compiling, but not do parallel
- linking, because linking is i/o bound and only gets slower.
- </simpara>
- </listitem>
- </itemizedlist>
- <para>
- Craig McPeeters has extended Perforce Jam to solve such problems, and
- that extension was integrated in Boost.Jam.
- </para>
- <para>
- Any target can be assigned a <emphasis>semaphore</emphasis>, by setting
- a variable called <literal>SEMAPHORE</literal> on that target. The value
- of the variable is the semaphore name. It must be different from names
- of any declared target, but is arbitrary otherwise.
- </para>
- <para>
- The semantic of semaphores is that in a group of targets which have the
- same semaphore, only one can be updated at the moment, regardless of
- &quot;<literal>-j</literal>&quot; option.
- </para>
- </section>
- <section id="jam.language.variables.builtins.platform_identifier">
- <title><link linkend="jam.language.variables.builtins.platform_identifier">Platform
- Identifier</link></title>
- <para>
- A number of Jam built-in variables can be used to identify runtime platform:
- </para>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literal>OS</literal></term>
- <listitem>
- <para>
- OS identifier string
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>OSPLAT</literal></term>
- <listitem>
- <para>
- Underlying architecture, when applicable
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>MAC</literal></term>
- <listitem>
- <para>
- true on MAC platform
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>NT</literal></term>
- <listitem>
- <para>
- true on NT platform
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>OS2</literal></term>
- <listitem>
- <para>
- true on OS2 platform
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>UNIX</literal></term>
- <listitem>
- <para>
- true on Unix platforms
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>VMS</literal></term>
- <listitem>
- <para>
- true on VMS platform
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </section>
- <section id="jam.language.variables.builtins.jam_version">
- <title><link linkend="jam.language.variables.builtins.jam_version">Jam
- Version</link></title>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literal>JAMDATE</literal></term>
- <listitem>
- <para>
- Time and date at <literal>b2</literal> start-up as an ISO-8601
- UTC value.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>JAMUNAME</literal></term>
- <listitem>
- <para>
- Ouput of uname(1) command (Unix only)
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>JAMVERSION</literal></term>
- <listitem>
- <para>
- <literal>b2</literal> version, currently &quot;3.1.19&quot;
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>JAM_VERSION</literal></term>
- <listitem>
- <para>
- A predefined global variable with two elements indicates the version
- number of Boost Jam. Boost Jam versions start at &quot;<literal>03</literal>&quot;
- &quot;<literal>00</literal>&quot;. Earlier versions of <literal>Jam</literal>
- do not automatically define <literal>JAM_VERSION</literal>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </section>
- <section id="jam.language.variables.builtins.jamshell">
- <title><link linkend="jam.language.variables.builtins.jamshell">JAMSHELL</link></title>
- <para>
- When <literal>b2</literal> 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 <literal>$(JAMSHELL)</literal>.
- The default on Unix is, for example:
- </para>
-<programlisting>JAMSHELL = /bin/sh -c % ;
-</programlisting>
- <para>
- The <literal>%</literal> is replaced with the text of the action block.
- </para>
- <para>
- <literal>B2</literal> 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 <literal>$(JAMSHELL)</literal>
- to reference it.
- </para>
- <para>
- Just as <literal>b2</literal> expands a <literal>%</literal> to be the
- text of the rule's action block, it expands a <literal>!</literal> to
- be the multi-process slot number. The slot number varies between 1 and
- the number of concurrent jobs permitted by the <literal>-j</literal>
- flag given on the command line. Armed with this, it is possible to write
- a multiple host shell. For example:
- </para>
-<programlisting>#!/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 &quot;$2&quot;;;
-2|5) on blinken sh -c &quot;$2&quot;;;
-3|6) on nod sh -c &quot;$2&quot;;;
-*) eval &quot;$2&quot;;;
-esac
-</programlisting>
- </section>
- <section id="jam.language.variables.builtins.actionrule">
- <title><link linkend="jam.language.variables.builtins.actionrule"><literal>__TIMING_RULE__</literal>
- and <literal>__ACTION_RULE__</literal></link></title>
- <para>
- The <literal>__TIMING_RULE__</literal> and <literal>__ACTION_RULE__</literal>
- can be set to the name of a rule for <literal>b2</literal> to call <emphasis
- role="bold">after</emphasis> an action completes for a target. They both
- give diagnostic information about the action that completed. For <literal>__TIMING_RULE__</literal>
- the rule is called as:
- </para>
-<programlisting><phrase role="identifier">rule</phrase> <phrase role="identifier">timing</phrase><phrase role="special">-</phrase><phrase role="identifier">rule</phrase> <phrase role="special">(</phrase> <phrase role="identifier">args</phrase> <phrase role="special">*</phrase> <phrase role="special">:</phrase> <phrase role="identifier">target</phrase> <phrase role="special">:</phrase> <phrase role="identifier">start</phrase> <phrase role="identifier">end</phrase> <phrase role="identifier">user</phrase> <phrase role="identifier">system</phrase> <phrase role="special">)</phrase>
-</programlisting>
- <para>
- And <literal>__ACTION_RULE__</literal> is called as:
- </para>
-<programlisting><phrase role="identifier">rule</phrase> <phrase role="identifier">action</phrase><phrase role="special">-</phrase><phrase role="identifier">rule</phrase> <phrase role="special">(</phrase> <phrase role="identifier">args</phrase> <phrase role="special">*</phrase> <phrase role="special">:</phrase> <phrase role="identifier">target</phrase> <phrase role="special">:</phrase> <phrase role="identifier">command</phrase> <phrase role="identifier">status</phrase> <phrase role="identifier">start</phrase> <phrase role="identifier">end</phrase> <phrase role="identifier">user</phrase> <phrase role="identifier">system</phrase> <phrase role="special">:</phrase> <phrase role="identifier">output</phrase> <phrase role="special">?</phrase> <phrase role="special">)</phrase>
-</programlisting>
- <para>
- The arguments for both are:
- </para>
- <variablelist>
- <title></title>
- <varlistentry>
- <term><literal>args</literal></term>
- <listitem>
- <para>
- Any values following the rule name in the <literal>__TIMING_RULE__</literal>
- or <literal>__ACTION_RULE__</literal> are passed along here.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>target</literal></term>
- <listitem>
- <para>
- The <literal>b2</literal> target that was built.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>command</literal></term>
- <listitem>
- <para>
- The text of the executed command in the action body.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>status</literal></term>
- <listitem>
- <para>
- The integer result of the executed command.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>start</literal></term>
- <listitem>
- <para>
- The starting timestamp of the executed command as a ISO-8601 UTC
- value.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>end</literal></term>
- <listitem>
- <para>
- The completion timestamp of the executed command as a ISO-8601
- UTC value.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>user</literal></term>
- <listitem>
- <para>
- The number of user CPU seconds the executed command spent as a
- floating point value.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>system</literal></term>
- <listitem>
- <para>
- The number of system CPU seconds the executed command spent as
- a floating point value.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>output</literal></term>
- <listitem>
- <para>
- The output of the command as a single string. The content of the
- output reflects the use of the <literal>-pX</literal> option.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <note>
- <para>
- If both variables are set for a target both are called, first <literal>__TIMING_RULE__</literal>
- then <literal>__ACTION_RULE__</literal>.
- </para>
- </note>
- </section>
- </section>
- </section>
- <section id="jam.language.modules">
- <title><link linkend="jam.language.modules">Modules</link></title>
- <para>
- Boost Jam introduces support for modules, which provide some rudimentary
- namespace protection for rules and variables. A new keyword, &quot;<literal>module</literal>&quot;
- 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.
- </para>
- <section id="jam.language.modules.declaration">
- <title><link linkend="jam.language.modules.declaration">Declaration</link></title>
-<programlisting>module <emphasis>expression</emphasis> { ... }
-</programlisting>
- <para>
- Code within the <literal>{ ... }</literal> 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 <emphasis>module-name</emphasis>.<emphasis>rule-name</emphasis>,
- so within a module, other rules in that module may always be invoked without
- qualification:
- </para>
-<programlisting><emphasis role="bold">module my_module</emphasis>
-<emphasis role="bold">{</emphasis>
- rule salute ( x ) { ECHO $(x), world ; }
- rule greet ( ) { salute hello ; }
- greet ;
-<emphasis role="bold">}</emphasis>
-<emphasis role="bold">my_module.salute</emphasis> goodbye ;
-</programlisting>
- <para>
- 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:
- </para>
-<programlisting>module your_module
-{
- rule bedtime ( ) { <emphasis role="bold">my_module.salute</emphasis> goodnight ; }
-}
-</programlisting>
- </section>
- <section id="jam.language.modules.variable_scope">
- <title><link linkend="jam.language.modules.variable_scope">Variable Scope</link></title>
- <para>
- 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:
- </para>
-<programlisting>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 &quot;999&quot;
- }
-}
-module B
-{
- y = 2 ;
- rule f ( )
- {
- ECHO $(y) ; # always prints &quot;2&quot;
- A.g ;
- }
-}
-</programlisting>
- <para>
- The only way to access another module's variables is by entering that module:
- </para>
-<programlisting>rule peek ( module-name ? : variables + )
-{
- module $(module-name)
- {
- return $($(&gt;)) ;
- }
-}
-</programlisting>
- <para>
- Note that because existing variable bindings change whenever a new module
- scope is entered, argument bindings become unavailable. That explains the
- use of &quot;<literal>$(&gt;)</literal>&quot; in the peek rule above.
- </para>
- </section>
- <section id="jam.language.modules.local_rules">
- <title><link linkend="jam.language.modules.local_rules">Local Rules</link></title>
-<programlisting>local rule <emphasis>rulename</emphasis>...
-</programlisting>
- <para>
- 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:
- </para>
-<programlisting>[ RULENAMES <emphasis>module-name</emphasis> ]
-</programlisting>
- </section>
- <section id="jam.language.modules.the__rulenames__rule">
- <title><link linkend="jam.language.modules.the__rulenames__rule">The <literal>RULENAMES</literal>
- Rule</link></title>
-<programlisting>rule RULENAMES ( <emphasis>module</emphasis> ? )
-</programlisting>
- <para>
- Returns a list of the names of all non-local rules in the given module.
- If <emphasis>module</emphasis> is omitted, the names of all non-local rules
- in the global module are returned.
- </para>
- </section>
- <section id="jam.language.modules.the__varnames__rule">
- <title><link linkend="jam.language.modules.the__varnames__rule">The <literal>VARNAMES</literal>
- Rule</link></title>
-<programlisting>rule VARNAMES ( <emphasis>module</emphasis> ? )
-</programlisting>
- <para>
- Returns a list of the names of all variable bindings in the given module.
- If <emphasis>module</emphasis> is omitted, the names of all variable bindings
- in the global module are returned.
- </para>
- <note>
- <para>
- This includes any local variables in rules from the call stack which
- have not returned at the time of the <literal>VARNAMES</literal> invocation.
- </para>
- </note>
- </section>
- <section id="jam.language.modules.the__import__rule">
- <title><link linkend="jam.language.modules.the__import__rule">The <literal>IMPORT</literal>
- Rule</link></title>
- <para>
- <literal>IMPORT</literal> allows rule name aliasing across modules:
- </para>
-<programlisting>rule IMPORT ( <emphasis>source_module</emphasis> ? : <emphasis>source_rules</emphasis> *
- : <emphasis>target_module</emphasis> ? : <emphasis>target_rules</emphasis> * )
-</programlisting>
- <para>
- The <literal>IMPORT</literal> rule copies rules from the <emphasis>source_module</emphasis>
- into the <emphasis>target_module</emphasis> as local rules. If either
- <emphasis>source_module</emphasis> or <emphasis>target_module</emphasis>
- is not supplied, it refers to the global module. <emphasis>source_rules</emphasis>
- specifies which rules from the <emphasis>source_module</emphasis> to import;
- <emphasis>target_rules</emphasis> specifies the names to give those rules
- in <emphasis>target_module</emphasis>. If <emphasis>source_rules</emphasis>
- contains a name which doesn't correspond to a rule in <emphasis>source_module</emphasis>,
- or if it contains a different number of items than <emphasis>target_rules</emphasis>,
- an error is issued. For example,
- </para>
-<programlisting># 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 ] ;
-</programlisting>
- </section>
- <section id="jam.language.modules.the__export__rule">
- <title><link linkend="jam.language.modules.the__export__rule">The <literal>EXPORT</literal>
- Rule</link></title>
- <para>
- <literal>EXPORT</literal> allows rule name aliasing across modules:
- </para>
-<programlisting>rule EXPORT ( <emphasis>module</emphasis> ? : <emphasis>rules</emphasis> * )
-</programlisting>
- <para>
- The <literal>EXPORT</literal> rule marks <emphasis>rules</emphasis> from
- the <literal>source_module</literal> as non-local (and thus exportable).
- If an element of <emphasis>rules</emphasis> does not name a rule in <emphasis>module</emphasis>,
- an error is issued. For example,
- </para>
-<programlisting>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.
-</programlisting>
- </section>
- <section id="jam.language.modules.the__caller_module__rule">
- <title><link linkend="jam.language.modules.the__caller_module__rule">The
- <literal>CALLER_MODULE</literal> Rule</link></title>
-<programlisting>rule CALLER_MODULE ( <emphasis>levels</emphasis> ? )
-</programlisting>
- <para>
- <literal>CALLER_MODULE</literal> 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 &quot;{Y}
- {X}&quot;:
- </para>
-<programlisting>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)} ;
-</programlisting>
- </section>
- <section id="jam.language.modules.the__delete_module__rule">
- <title><link linkend="jam.language.modules.the__delete_module__rule">The
- <literal>DELETE_MODULE</literal> Rule</link></title>
-<programlisting>rule DELETE_MODULE ( <emphasis>module</emphasis> ? )
-</programlisting>
- <para>
- <literal>DELETE_MODULE</literal> removes all of the variable bindings and
- otherwise-unreferenced rules from the given module (or the global module,
- if no module is supplied), and returns their memory to the system.
- </para>
- <note>
- <para>
- Though it won't affect rules that are currently executing until they
- complete, <literal>DELETE_MODULE</literal> should be used with extreme
- care because it will wipe out any others and all variable (including
- locals in that module) immediately. Because of the way dynamic binding
- works, variables which are shadowed by locals will not be destroyed,
- so the results can be really unpredictable.
- </para>
- </note>
- </section>
- </section>
- </section>
- <section id="jam.miscellaneous">
- <title><link linkend="jam.miscellaneous">Miscellaneous</link></title>
- <section id="jam.miscellaneous.diagnostics">
- <title><link linkend="jam.miscellaneous.diagnostics">Diagnostics</link></title>
- <para>
- In addition to generic error messages, <literal>b2</literal> may emit one
- of the following:
- </para>
-<programlisting>warning: unknown rule X</programlisting>
- <para>
- A rule was invoked that has not been defined with an &quot;<literal>actions</literal>&quot;
- or &quot;<literal>rule</literal>&quot; statement.
- </para>
-<programlisting>using N temp target(s)</programlisting>
- <para>
- Targets marked as being temporary (but nonetheless present) have been found.
- </para>
-<programlisting>updating N target(s)</programlisting>
- <para>
- Targets are out-of-date and will be updated.
- </para>
-<programlisting>can't find N target(s)</programlisting>
- <para>
- Source files can't be found and there are no actions to create them.
- </para>
-<programlisting>can't make N target(s)</programlisting>
- <para>
- Due to sources not being found, other targets cannot be made.
- </para>
-<programlisting>warning: X depends on itself</programlisting>
- <para>
- A target depends on itself either directly or through its sources.
- </para>
-<programlisting>don't know how to make X</programlisting>
- <para>
- A target is not present and no actions have been defined to create it.
- </para>
-<programlisting>X skipped for lack of Y</programlisting>
- <para>
- A source failed to build, and thus a target cannot be built.
- </para>
-<programlisting>warning: using independent target X</programlisting>
- <para>
- A target that is not a dependency of any other target is being referenced
- with <literal>$(&lt;)</literal> or <literal>$(&gt;)</literal>.
- </para>
-<programlisting>X removed</programlisting>
- <para>
- <literal>B2</literal> removed a partially built target after being interrupted.
- </para>
- </section>
- <section id="jam.miscellaneous.bugs__limitations">
- <title><link linkend="jam.miscellaneous.bugs__limitations">Bugs, Limitations</link></title>
- <para>
- 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 <literal>yacc(1)</literal> does.
- </para>
- <para>
- A poorly set <literal>$(JAMSHELL)</literal> is likely to result in silent
- failure.
- </para>
- </section>
- <section id="jam.miscellaneous.fundamentals">
- <title><link linkend="jam.miscellaneous.fundamentals">Fundamentals</link></title>
- <para>
- This section is derived from the official Jam documentation and from experience
- using it and reading the Jambase rules. We repeat the information here mostly
- because it is essential to understanding and using Jam, but is not consolidated
- in a single place. Some of it is missing from the official documentation
- altogether. We hope it will be useful to anyone wishing to become familiar
- with Jam and the Boost build system.
- </para>
- <itemizedlist>
- <listitem>
- <simpara>
- Jam &quot;<literal>rules</literal>&quot; are actually simple procedural
- entities. Think of them as functions. Arguments are separated by colons.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- A Jam <emphasis role="bold">target</emphasis> is an abstract entity identified
- by an arbitrary string. The build-in <literal>DEPENDS</literal> rule
- creates a link in the dependency graph between the named targets.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- Note that the original Jam documentation for the built-in <literal>INCLUDES</literal>
- rule is incorrect: <literal>INCLUDES <emphasis>targets1</emphasis> :
- <emphasis>targets2</emphasis></literal> causes everything that depends
- on a member of <emphasis>targets1</emphasis> to depend on all members
- of <emphasis>targets2</emphasis>. It does this in an odd way, by tacking
- <emphasis>targets2</emphasis> onto a special tail section in the dependency
- list of everything in <emphasis>targets1</emphasis>. It seems to be OK
- to create circular dependencies this way; in fact, it appears to be the
- &quot;right thing to do&quot; when a single build action produces both
- <emphasis>targets1</emphasis> and <emphasis>targets2</emphasis>.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- When a rule is invoked, if there are <literal>actions</literal> declared
- with the same name as the rule, the actions are added to the updating
- actions for the target identified by the rule's first argument. It is
- actually possible to invoke an undeclared rule if corresponding actions
- are declared: the rule is treated as empty.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- Targets (other than <literal>NOTFILE</literal> targets) are associated
- with paths in the file system through a process called binding. Binding
- is a process of searching for a file with the same name as the target
- (sans grist), based on the settings of the target-specific <literal>SEARCH</literal>
- and <literal>LOCATE</literal> variables.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- In addition to local and global variables, jam allows you to set a variable
- <literal>on</literal> a target. Target-specific variable values can usually
- not be read, and take effect only in the following contexts:
- <itemizedlist>
- <listitem>
- <simpara>
- In updating actions, variable values are first looked up <literal>on</literal>
- the target named by the first argument (the target being updated).
- Because Jam builds its entire dependency tree before executing
- actions, Jam rules make target-specific variable settings as a
- way of supplying parameters to the corresponding actions.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- Binding is controlled <emphasis>entirely</emphasis> by the target-specific
- setting of the <literal>SEARCH</literal> and <literal>LOCATE</literal>
- variables, as described here.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- In the special rule used for header file scanning, variable values
- are first looked up <literal>on</literal> the target named by the
- rule's first argument (the source file being scanned).
- </simpara>
- </listitem>
- </itemizedlist>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- The &quot;bound value&quot; of a variable is the path associated with
- the target named by the variable. In build actions, the first two arguments
- are automatically replaced with their bound values. Target-specific variables
- can be selectively replaced by their bound values using the <literal>bind</literal>
- action modifier.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- Note that the term &quot;binding&quot; as used in the Jam documentation
- indicates a phase of processing that includes three sub-phases: <emphasis>binding</emphasis>
- (yes!), update determination, and header file scanning. The repetition
- of the term &quot;binding&quot; can lead to some confusion. In particular,
- the Modifying Binding section in the Jam documentation should probably
- be titled &quot;Modifying Update Determination&quot;.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- &quot;Grist&quot; is just a string prefix of the form &lt;<emphasis>characters</emphasis>&gt;.
- It is used in Jam to create unique target names based on simpler names.
- For example, the file name &quot;<literal>test.exe</literal>&quot; may
- be used by targets in separate subprojects, or for the debug and release
- variants of the &quot;same&quot; abstract target. Each distinct target
- bound to a file called &quot;test.exe&quot; has its own unique grist
- prefix. The Boost build system also takes full advantage of Jam's ability
- to divide strings on grist boundaries, sometimes concatenating multiple
- gristed elements at the beginning of a string. Grist is used instead
- of identifying targets with absolute paths for two reasons:
- <orderedlist>
- <listitem>
- <simpara>
- The location of targets cannot always be derived solely from what
- the user puts in a Jamfile, but sometimes depends also on the binding
- process. Some mechanism to distinctly identify targets with the
- same name is still needed.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- Grist allows us to use a uniform abstract identifier for each built
- target, regardless of target file location (as allowed by setting
- ALL_LOCATE_TARGET).
- </simpara>
- </listitem>
- </orderedlist>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- When grist is extracted from a name with $(var:G), the result includes
- the leading and trailing angle brackets. When grist is added to a name
- with $(var:G=expr), existing grist is first stripped. Then, if expr is
- non-empty, leading &lt;s and trailing &gt;s are added if necessary to
- form an expression of the form &lt;expr2&gt;; &lt;expr2&gt; is then prepended.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- When Jam is invoked it imports all environment variable settings into
- corresponding Jam variables, followed by all command-line (-s...) variable
- settings. Variables whose name ends in PATH, Path, or path are split
- into string lists on OS-specific path-list separator boundaries (e.g.
- &quot;:&quot; for UNIX and &quot;;&quot; for Windows). All other variables
- are split on space (&quot; &quot;) boundaries. Boost Jam modifies that
- behavior by allowing variables to be quoted.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- A variable whose value is an empty list or which consists entirely of
- empty strings has a negative logical value. Thus, for example, code like
- the following allows a sensible non-empty default which can easily be
- overridden by the user:
-<programlisting><phrase role="identifier">MESSAGE</phrase> <phrase role="special">?\=</phrase> <phrase role="identifier">starting</phrase> <phrase role="identifier">jam</phrase><phrase role="special">...</phrase> <phrase role="special">;</phrase>
-<phrase role="keyword">if</phrase> <phrase role="error">$</phrase><phrase role="special">(</phrase><phrase role="identifier">MESSAGE</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <phrase role="identifier">ECHO</phrase> <phrase role="identifier">The</phrase> <phrase role="identifier">message</phrase> <phrase role="identifier">is</phrase><phrase role="special">:</phrase> <phrase role="error">$</phrase><phrase role="special">(</phrase><phrase role="identifier">MESSAGE</phrase><phrase role="special">)</phrase> <phrase role="special">;</phrase> <phrase role="special">}</phrase>
-</programlisting>
- If the user wants a specific message, he invokes jam with <literal>&quot;-sMESSAGE=message
- text&quot;</literal>. If he wants no message, he invokes jam with <literal>-sMESSAGE=</literal>
- and nothing at all is printed.
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- The parsing of command line options in Jam can be rather unintuitive,
- with regards to how other Unix programs accept options. There are two
- variants accepted as valid for an option:
- <orderedlist>
- <listitem>
- <simpara>
- <literal>-xvalue</literal>, and
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- <literal>-x value</literal>.
- </simpara>
- </listitem>
- </orderedlist>
- </simpara>
- </listitem>
- </itemizedlist>
- </section>
- </section>
- <section id="jam.history">
- <title><link linkend="jam.history">History</link></title>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>3.1.18</term>
- <listitem>
- <para>
- After years of bjam developments.. This is going to be the last unbundled
- release of the 3.1.x series. From this point forward bjam will only be
- bundled as part of the larger Boost Build system. And hence will likely
- change name at some point. As a side effect of this move people will
- get more frequent release of bjam (or whatever it ends up being called).
- </para>
- <para>
- <itemizedlist><listitem>New built-ins, MD5, SPLIT_BY_CHARACTERS, PRECIOUS, PAD, FILE_OPEN, and
- UPDATE_NOW. -- <emphasis>Vladimir P.</emphasis> </listitem>
- <listitem>Ensure all file descriptors
- are closed when executing actions complete on *nix. -- <emphasis>Noel
- B.</emphasis> </listitem>
- <listitem>Fix warnings, patch from Mateusz Loskot. -- <emphasis>Vladimir
- P.</emphasis> </listitem>
- <listitem>Add KEEP_GOING var to programatically override the '-q'
- option. -- <emphasis>Vladimir P.</emphasis> </listitem>
- <listitem>Add more parameters, up to
- 19 from 9, to rule invocations. Patch from Jonathan Biggar. -- <emphasis>Vladimir
- P.</emphasis> </listitem>
- <listitem>Print failed command output even if the normally quite
- '-d0' option. -- <emphasis>Vladimir P.</emphasis> </listitem>
- <listitem>Build of bjam with
- vc10, aka Visual Studio 2010. -- <emphasis>Vladimir P.</emphasis> </listitem>
- <listitem>More
- macros for detection of OSPLAT, patch from John W. Bito. -- <emphasis>Vladimir
- P.</emphasis> </listitem>
- <listitem>Add PARALLELISM var to programatically override the '-j'
- option. -- <emphasis>Vladimir P.</emphasis> </listitem>
- <listitem>Tweak doc building to allow
- for PDF generation of docs. -- <emphasis>John M.</emphasis> </listitem>
-</itemizedlist>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>3.1.17</term>
- <listitem>
- <para>
- A year in the making this release has many stability improvements and
- various performance improvements. And because of the efforts of Jurko
- the code is considerably more readable!
- </para>
- <para>
- <itemizedlist><listitem>Reflect the results of calling bjam from Python. -- <emphasis>Rene R.</emphasis>
- </listitem>
- <listitem>For building on Windows: Rework how arguments are parsed and tested to
- fix handling of quoted arguments, options arguments, and arguments with
- &quot;=&quot;. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Try to work around at
- least one compiler bug with GCC and variable aliasing that causes crashes
- with hashing file cache entries. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Add
- -Wc,-fno-strict-aliasing for QCC/QNX to avoid the same aliasing crashes
- as in the general GCC 4.x series (thanks to Niklas Angare for the fix).
- -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>On Windows let the child bjam commands
- inherit stdin, as some commands assume it's available. -- <emphasis>Rene
- R.</emphasis> </listitem>
- <listitem>On Windows don't limit bjam output to ASCII as some tools
- output characters in extended character sets. -- <emphasis>Rene R.</emphasis>
- </listitem>
- <listitem>Isolate running of bjam tests to individual bjam instances to prevent
- possible spillover errors from one test affecting another test. Separate
- the bjam used to run the tests vs. the bjam being tested. And add automatic
- re-building of the bjam being tested. -- <emphasis>Rene R.</emphasis>
- </listitem>
- <listitem>Fix some possible overrun issues revealed by Fortify build. Thanks to
- Steven Robbins for pointing out the issues. -- <emphasis>Rene R.</emphasis>
- </listitem>
- <listitem>Handle \n and \r escape sequences. -- <emphasis>Vladimir P.</emphasis>
- </listitem>
- <listitem>Minor edits to remove -Wall warnings. -- <emphasis>Rene R.</emphasis>
- </listitem>
- <listitem>Dynamically adjust pwd buffer query size to allow for when PATH_MAX is
- default defined instead of being provided by the system C library. --
- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Minor perf improvement for bjam by replacing
- hash function with faster version. Only 1% diff for Boost tree. -- <emphasis>Rene
- R.</emphasis> </listitem>
- <listitem>Updated Boost Jam's error location reporting when parsing
- Jamfiles. Now it reports the correct error location information when
- encountering an unexpected EOF. It now also reports where an invalid
- lexical token being read started instead of finished which makes it much
- easier to find errors like unclosed quotes or curly braces. -- <emphasis>Jurko
- G.</emphasis> </listitem>
- <listitem>Removed the -xarch=generic architecture from build.jam
- as this option is unknown so the Sun compilers on Linux. -- <emphasis>Noel
- B.</emphasis> </listitem>
- <listitem>Fixed a bug with T_FATE_ISTMP getting reported as T_FATE_ISTMP
- &amp; T_FATE_NEEDTMP at the same time due to a missing break in a switch
- statement. -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Fixed a Boost Jam bug causing
- it to sometimes trigger actions depending on targets that have not been
- built yet. -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Added missing documentation
- for Boost Jam's :T variable expansion modifier which converts all back-slashes
- ('\') to forward slashed ('/'). -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Added
- Boost Jam support for executing command lines longer than 2047 characters
- (up to 8191) characters when running on Windows XP or later OS version.
- -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Fixed a Boost Jam bug on Windows causing
- its SHELL command not to work correctly with some commands containing
- quotes. -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Corrected a potential memory
- leak in Boost Jam's builtin_shell() function that would appear should
- Boost Jam ever start to release its allocated string objects. -- <emphasis>Jurko
- G.</emphasis> </listitem>
- <listitem>Made all Boost Jam's ECHO commands automatically flush
- the standard output to make that output more promptly displayed to the
- user. -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Made Boost Jam tests quote their
- bjam executable name when calling it allowing those executables to contain
- spaces in their name and/or path. -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Change
- execunix.c to always use fork() instead of vfork() on the Mac. This works
- around known issues with bjam on PPC under Tiger and a problem reported
- by Rene with bjam on x86 under Leopard. -- <emphasis>Noel B.</emphasis>
- </listitem>
- <listitem>Corrected a bug in Boost Jam's base Jambase script causing it to trim
- the error message displayed when its boost-build rule gets called multiple
- times. -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>When importing from Python into
- an module with empty string as name, import into root module. -- <emphasis>Vladimir
- P.</emphasis> </listitem>
- <listitem>Patch for the NORMALIZE_PATH builtin Boost Jam rule as
- well as an appropriate update for the path.jam Boost Build module where
- that rule was being used to implement path join and related operations.
- -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Fixed a bug causing Boost Jam not to
- handle target file names specified as both short and long file names
- correctly. -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Relaxed test, ignoring case
- of drive letter. -- <emphasis>Roland S.</emphasis> </listitem>
- <listitem>Implemented a patch
- contributed by Igor Nazarenko reimplementing the list_sort() function
- to use a C qsort() function instead of a hand-crafted merge-sort algorithm.
- Makes some list sortings (e.g. 1,2,1,2,1,2,1,2, ...) extremely faster,
- in turn significantly speeding up some project builds. -- <emphasis>Jurko
- G.</emphasis> </listitem>
- <listitem>Fixed a bug with bjam not handling the '' root Windows
- path correctly without its drive letter being specified. -- <emphasis>Jurko
- G.</emphasis> </listitem>
- <listitem>Solved the problem with child process returning the value
- 259 (Windows constant STILL_ACTIVE) causing bjam never to detect that
- it exited and therefore keep running in an endless loop. -- <emphasis>Jurko
- G.</emphasis> </listitem>
- <listitem>Solved the problem with bjam going into an active wait
- state, hogging up processor resources, when waiting for one of its child
- processes to terminate while not all of its available child process slots
- are being used. -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Solved a race condition
- between bjam's output reading/child process termination detection and
- the child process's output generation/termination which could have caused
- bjam not to collect the terminated process's final output. -- <emphasis>Jurko
- G.</emphasis> </listitem>
- <listitem>Change from vfork to fork for executing actions on Darwin
- to improve stability. -- <emphasis>Noel B.</emphasis> </listitem>
- <listitem>Code reformatting
- and cleanups. -- <emphasis>Jurko G.</emphasis> </listitem>
- <listitem>Implement ISFILE built-in.
- -- <emphasis>Vladimir P.</emphasis> </listitem>
-</itemizedlist>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>3.1.16</term>
- <listitem>
- <para>
- This is mostly a bug fix release.
- </para>
- <para>
- <itemizedlist><listitem>Work around some Windows CMD.EXE programs that will fail executing a
- totally empty batch file. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Add support
- for detection and building with <literal>vc9</literal>. -- <emphasis>John
- P.</emphasis> </listitem>
- <listitem>Plug memory leak when closing out actions. Thanks to Martin
- Kortmann for finding this. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Various improvements
- to <literal>__TIMING_RULE__</literal> and <literal>__ACTION_RULE__</literal>
- target variable hooks. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Change <literal>JAMDATE</literal>
- to use common ISO date format. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Add test
- for result status values of simple actions, i.e. empty actions. -- <emphasis>Rene
- R.</emphasis> </listitem>
- <listitem>Fix buffer overrun bug in expanding <literal>@()</literal>
- subexpressions. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Check empty string invariants,
- instead of assuming all strings are allocated. And reset strings when
- they are freed. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Add <literal>OSPLAT=PARISC</literal>
- for HP-UX PA-RISC. -- <emphasis>Boris G.</emphasis> </listitem>
- <listitem>Make quietly actions
- really quiet by not printing the command output. The output for the quietly
- actions is still available through <literal>__ACTION_RULE__</literal>.
- -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Switch intel-win32 to use static multi
- thread runtime since the single thread static runtime is no longer available.
- -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>When setting <literal>OSPLAT</literal>,
- check <literal>__ia64</literal> macro. -- <emphasis>Boris G.</emphasis>
- </listitem>
- <listitem>Get the unix timing working correctly. -- <emphasis>Noel B.</emphasis>
- </listitem>
- <listitem>Add <literal>-fno-strict-aliasing</literal> to compilation with gcc.
- Which works around GCC-4.2 crash problems. -- <emphasis>Boris G.</emphasis>
- </listitem>
- <listitem>Increased support for Python integration. -- <emphasis>Vladimir P.</emphasis>,
- <emphasis>Daniel W.</emphasis> </listitem>
- <listitem>Allow specifying options with quotes,
- i.e. <literal>--with-python=xyz</literal>, to work around the CMD shell
- using <literal>=</literal> as an argument separator. -- <emphasis>Rene
- R.</emphasis> </listitem>
- <listitem>Add values of variables specified with -s to .EVNRION module,
- so that we can override environment on command line. -- <emphasis>Vladimir
- P.</emphasis> </listitem>
- <listitem>Make NORMALIZE_PATH convert \ to /. -- <emphasis>Vladimir
- P.</emphasis> </listitem>
-</itemizedlist>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>3.1.15</term>
- <listitem>
- <para>
- This release sees a variety of fixes for long standing Perforce/Jam problems.
- Most of them relating to running actions in parallel with the -jN option.
- The end result of the changes is that running parallel actions is now
- reliably possible in Unix and Windows environments. Many thanks to Noel
- for joining the effort, to implement and fix the Unix side of stuff.
- </para>
- <para>
- <itemizedlist><listitem>Add support for building bjam with pgi and pathscale toolsets. -- <emphasis>Noel
- B.</emphasis> </listitem>
- <listitem>Implement running action commands through pipes (-p option)
- to fix jumbled output when using parallel execution with -j option. This
- is implemented for Unix variants, and Windows (Win32/NT). -- <emphasis>Rene
- R.</emphasis>, <emphasis>Noel B.</emphasis> </listitem>
- <listitem>Add &quot;sun&quot; as alias
- to Sun Workshop compiler tools. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Set MAXLINE
- in jam.h to 23k bytes for AIX. The piecemeal archive action was broken
- with the default MAXLINE of 102400. Because the AIX shell uses some of
- the 24k default buffer size for its own use, I reduced it to 23k. --
- <emphasis>Noel B.</emphasis> </listitem>
- <listitem>Make use of output dir options of msvc to
- not polute src dir with compiled files. -- <emphasis>Rene R.</emphasis>
- </listitem>
- <listitem>A small fix, so -d+2 will always show the &quot;real&quot; commands being
- executed instead of casually the name of a temporary batch file. --
- <emphasis>Roland S.</emphasis> </listitem>
- <listitem>Add test to check 'bjam -n'. -- <emphasis>Rene
- R.</emphasis> </listitem>
- <listitem>Add test to check 'bjam -d2'. -- <emphasis>Rene R.</emphasis>
- </listitem>
- <listitem>Bring back missing output of -n option. The -o option continues to be
- broken as it has been for a long time now because of the @ file feature.
- -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Update GC support to work with Boehm
- GC 7.0. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Revert the BOOST_BUILD_PATH change,
- since the directory passed to boost-build should be first in searched
- paths, else project local build system will not be picked correctly.
- The order had been changed to allow searching of alternate user-config.jam
- files from boost build. This better should be done with --user-config=
- switch or similar. -- <emphasis>Roland S.</emphasis> </listitem>
- <listitem>Initial support
- for defining action body from Python. -- <emphasis>Vladimir P.</emphasis>
- </listitem>
- <listitem>Implement @() expansion during parse phase. -- <emphasis>Rene R.</emphasis>
- </listitem>
- <listitem>Define OSPLAT var unconditionally, and more generically, when possible.
- -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Fix undeclared INT_MAX on some platforms,
- i.e. Linux. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Modified execunix.c to add
- support for terminating processes that consume too much cpu or that hang
- and fail to consume cpu at all. This in support of the bjam -lx option.
- -- <emphasis>Noel B.</emphasis> </listitem>
- <listitem>Add internal dependencies for multi-file
- generating actions to indicate that the targets all only appear when
- the first target appears. This fixes the long standing problem Perforce/Jam
- has with multi-file actions and parallel execution (-jN). -- <emphasis>Rene
- R.</emphasis> </listitem>
- <listitem>Add test of -l limit option now that it's implemented on
- windows and unix. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Add test for no-op
- @() expansion. -- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Handle invalid formats
- of @() as doing a straight substitution instead of erroring out. --
- <emphasis>Rene R.</emphasis> </listitem>
- <listitem>Various fixes to compile on SGI/Irix. --
- <emphasis>Noel B.</emphasis> </listitem>
- <listitem>Add output for when actions timeout with
- -lN option. -- <emphasis>Rene R.</emphasis>, <emphasis>Noel B.</emphasis>
- </listitem>
- <listitem>Add needed include (according to XOPEN) for definition of WIFEXITED and
- WEXITSTATUS. -- <emphasis>Markus S.</emphasis> </listitem>
-</itemizedlist>
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </section>
-</article>
diff --git a/tools/build/doc/bjam.qbk b/tools/build/doc/bjam.qbk
index 6b754d13de..27adf472a8 100644
--- a/tools/build/doc/bjam.qbk
+++ b/tools/build/doc/bjam.qbk
@@ -364,7 +364,7 @@ The arguments starting with the "=--option=" forms are passed to the =build.jam=
[[[literal --gc]]
[Enables use of the Boehm Garbage Collector. The build will look for the Boehm-GC source in a "boehm_gc" subdirectory from the =b2= sources.]]
[[[literal --duma]]
- [Enables use of the DUMA (Detect Uintended Memory Access) debugging memory allocator. The build expects to find the DUMA source files in a "duma" subdirectory from the =b2= sources.]]
+ [Enables use of the DUMA (Detect Unintended Memory Access) debugging memory allocator. The build expects to find the DUMA source files in a "duma" subdirectory from the =b2= sources.]]
[[[literal --toolset-root=/path/]]
[Indicates where the toolset used to build is located. This option is passed in by the bootstrap (=build.bat= or =build.sh=) script.]]
[[[literal --show-locate-target]]
diff --git a/tools/build/doc/src/faq.xml b/tools/build/doc/src/faq.xml
index 9a7f9c4586..3b6894b773 100644
--- a/tools/build/doc/src/faq.xml
+++ b/tools/build/doc/src/faq.xml
@@ -414,7 +414,7 @@ exe hello : hello.cpp /site-config//zlib ;
external libraries it becomes problematic to remember which libraries are
header only, and which ones you have to link to. However, with Boost.Build
a header-only library can be declared as Boost.Build target and all
- dependents can use such library without having to remeber whether it is a
+ dependents can use such library without having to remember whether it is a
header-only library or not.
</para>
diff --git a/tools/build/doc/src/overview.xml b/tools/build/doc/src/overview.xml
index 1c2310b966..37bae1c96e 100644
--- a/tools/build/doc/src/overview.xml
+++ b/tools/build/doc/src/overview.xml
@@ -107,7 +107,7 @@ a.o: a.c
<programlisting>
add_program ("a", "a.c")
</programlisting>
- This is a function call that creates the targets necessary to create a executable file
+ This is a function call that creates the targets necessary to create an executable file
from the source file <filename>a.c</filename>. Depending on configured properties,
different command lines may be used. However, <code>add_program</code> is higher-level,
but rather thin level. All targets are created immediately when the build description
@@ -675,7 +675,7 @@ b2 toolset=gcc variant=debug optimization=space
<listitem>
<para>Changes the build directories for all project roots being built. When
this option is specified, all Jamroot files must declare a project name.
- The build directory for the project root will be computed by concatanating
+ The build directory for the project root will be computed by concatenating
the value of the <option>--build-dir</option> option, the project name
specified in Jamroot, and the build dir specified in Jamroot
(or <literal>bin</literal>, if none is specified).
@@ -782,12 +782,12 @@ b2 toolset=gcc variant=debug optimization=space
<varlistentry>
<term><option>-d <replaceable>N</replaceable></option></term>
<listitem>
- <para>Enable cummulative debugging levels from 1 to n. Values are:
+ <para>Enable cumulative debugging levels from 1 to n. Values are:
<orderedlist>
<listitem>Show the actions taken for building targets, as they are executed (the default).</listitem>
<listitem>Show "quiet" actions and display all action text, as they are executed.</listitem>
<listitem>Show dependency analysis, and target/source timestamps/paths.</listitem>
- <listitem>Show arguments and timming of shell invocations.</listitem>
+ <listitem>Show arguments and timing of shell invocations.</listitem>
<listitem>Show rule invocations and variable expansions.</listitem>
<listitem>Show directory/header file/archive scans, and attempts at binding to targets.</listitem>
<listitem>Show variable settings.</listitem>
@@ -1595,7 +1595,7 @@ b2 app1 lib1//lib1 gcc debug optimization=full
<listitem><para>Selecting the main target alternative to use. For
each alternative we look how many properties are present both in
alternative's requirements, and in build request. The
- alternative with large number of matching properties is selected.
+ alternative with largest number of matching properties is selected.
</para></listitem>
<listitem><para>Determining "common" properties.
diff --git a/tools/build/doc/src/reference.xml b/tools/build/doc/src/reference.xml
index a66eb75a6d..7e4c4ec86e 100644
--- a/tools/build/doc/src/reference.xml
+++ b/tools/build/doc/src/reference.xml
@@ -50,7 +50,7 @@ boost-build build-system ;
automatically find the build system.</para>
<para>The default <filename>bootstrap.jam</filename>, after loading some standard
- definitions, loads two <filename>site-config.jam</filename> and <filename>user-config.jam</filename>.</para>
+ definitions, loads both <filename>site-config.jam</filename> and <filename>user-config.jam</filename>.</para>
</section>
@@ -165,7 +165,7 @@ lib tools : [ glob *.cpp ] ;
</programlisting>
It is possible to also pass a second argument&#x2014;the list of
exclude patterns. The result will then include the list of
- files patching any of include patterns, and not matching any
+ files matching any of include patterns, and not matching any
of the exclude patterns. For example:
<programlisting>
lib tools : [ glob *.cpp : file_to_exclude.cpp bad*.cpp ] ;
@@ -567,7 +567,7 @@ path-constant DATA : data/a.txt ;
<simpara>
The value of those features is passed without modification to the
corresponding tools. For <code>cflags</code> that is both the C and
- C++ compilers, for <code>cxxflags</code> that is the C++ compiler
+ C++ compilers, for <code>cxxflags</code> that is the C++ compiler,
and for <code>linkflags</code> that is the linker. The features are
handy when you are trying to do something special that cannot be
achieved by a higher-level feature in Boost.Build.
@@ -672,7 +672,7 @@ path-constant DATA : data/a.txt ;
<para><emphasis role="bold">Allowed values:</emphasis> <literal>on</literal>, <literal>off</literal>.</para>
<para>The <literal>debug-symbols</literal> feature specifies if
- produced object files, executables and libraries should include
+ produced object files, executables, and libraries should include
debug information.
Typically, the value of this feature is implicitly set by the
<literal>variant</literal> feature, but it can be explicitly
@@ -686,8 +686,8 @@ path-constant DATA : data/a.txt ;
<listitem>
<para><emphasis role="bold">Allowed values:</emphasis> <literal>on</literal>, <literal>off</literal>.</para>
- <para>The <literal>runtime-debugging</literal> feature specifies if
- produced object files, executables and libraries should include
+ <para>The <literal>runtime-debugging</literal> feature specifies
+ whether produced object files, executables, and libraries should include
behaviour useful only for debugging, such as asserts.
Typically, the value of this feature is implicitly set by the
<literal>variant</literal> feature, but it can be explicitly
@@ -711,7 +711,7 @@ path-constant DATA : data/a.txt ;
</para>
<para>The complete list of possible values for this feature is:
- aix, bsd, cygwin, darwin, freebsd, hpux, iphone, linux, netbsd,
+ aix, appletv, bsd, cygwin, darwin, freebsd, hpux, iphone, linux, netbsd,
openbsd, osf, qnx, qnxnto, sgi, solaris, unix, unixware, windows.
</para>
@@ -937,7 +937,7 @@ using gcc : &toolset_ops; ;</programlisting>
<para>Specifies the archiver command that is used to produce static
libraries. Normally, it is autodetected using gcc
<command>-print-prog-name</command> option or defaulted to <command>ar</command>,
- but in some cases you might want to override it, for example to expliitly
+ but in some cases you might want to override it, for example to explicitly
use a system version instead of one included with gcc.</para>
</listitem>
</varlistentry>
@@ -949,7 +949,7 @@ using gcc : &toolset_ops; ;</programlisting>
<para>Specifies the ranlib command that is used to generated symbol table
for static libraries. Normally, it is autodetected using gcc
<command>-print-prog-name</command> option or defaulted to <command>ranlib</command>,
- but in some cases you might want to override it, for example to expliitly
+ but in some cases you might want to override it, for example to explicitly
use a system version instead of one included with gcc.</para>
</listitem>
</varlistentry>
@@ -1021,6 +1021,9 @@ using gcc : &toolset_ops; ;</programlisting>
C++</ulink> command-line tools on Microsoft Windows. The supported
products and versions of command line tools are listed below:</para>
<itemizedlist>
+ <listitem><para>Visual Studio 2015&#x2014;14.0</para></listitem>
+ <listitem><para>Visual Studio 2013&#x2014;12.0</para></listitem>
+ <listitem><para>Visual Studio 2012&#x2014;11.0</para></listitem>
<listitem><para>Visual Studio 2010&#x2014;10.0</para></listitem>
<listitem><para>Visual Studio 2008&#x2014;9.0</para></listitem>
<listitem><para>Visual Studio 2005&#x2014;8.0</para></listitem>
@@ -2661,7 +2664,7 @@ exe hello : hello.cpp : &lt;os&gt;NT,&lt;toolset&gt;gcc:&lt;link&gt;static ;
target. The syntax is:</para>
<programlisting>
-target-id -&gt; (project-id | target-name | file-name )
+target-id -&gt; (target-name | file-name | project-id | directory-name)
| (project-id | directory-name) "//" target-name
project-id -&gt; path
target-name -&gt; path
@@ -2675,34 +2678,41 @@ directory-name -&gt; path
<itemizedlist>
<listitem>
<simpara>
- project id (at this point, all project ids start with slash).
+ name of target declared in current Jamfile (note that target
+ names may include slash).
</simpara>
</listitem>
<listitem>
<simpara>
- name of target declared in current Jamfile (note that target
- names may include slash).
+ a regular file, denoted by absolute name or name relative to
+ project's sources location.
</simpara>
</listitem>
<listitem>
<simpara>
- a regular file, denoted by absolute name or name relative to
- project's sources location.
+ project id (at this point, all project ids start with slash).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ the directory of another project, denoted by absolute name
+ or name relative to the current project's location.
</simpara>
</listitem>
</itemizedlist>
- To determine the real meaning a check is made if project-id
- by the specified name exists, and then if main target of that
- name exists. For example, valid target ids might be:
+ To determine the real meaning the possible interpretations
+ are checked in this order. For example, valid target ids might be:
<screen>
a -- target in current project
lib/b.cpp -- regular file
/boost/thread -- project "/boost/thread"
/home/ghost/build/lr_library//parser -- target in specific project
+../boost_1_61_0 -- project in specific directory
</screen>
</para>
diff --git a/tools/build/doc/src/tasks.xml b/tools/build/doc/src/tasks.xml
index 8ff82f0b81..48f611a28b 100644
--- a/tools/build/doc/src/tasks.xml
+++ b/tools/build/doc/src/tasks.xml
@@ -520,7 +520,7 @@ unit-test helpers_test
<para>
By default, the executable is run directly. Sometimes, it is
desirable to run the executable using some helper command. You
- should use the this property to specify the name of the helper
+ should use this property to specify the name of the helper
command. For example, if you write:
<programlisting>
unit-test helpers_test
@@ -575,7 +575,7 @@ unit-test helpers_test
Boost.Build's virtual targets. This is higher-level than the file names that
the <code language="jam">make</code> rule operates with and allows you to
create more than one target, create differently named targets depending on
- properties or use more than one tool.
+ properties, or use more than one tool.
</para>
<para>
@@ -764,7 +764,7 @@ exe main : main.cpp pch ;
"parser.y". The latter source is converted into "parser.c" and "parser.h".
Then, if "app.cpp" includes "parser.h", Boost.Build will detect this
dependency. Moreover, since "parser.h" will be generated into a build
- directory, the path to that directory will automatically added to include
+ directory, the path to that directory will automatically be added to the include
path.
</para>
@@ -800,14 +800,14 @@ using gcc : arm : arm-none-linux-gnueabi-g++ ;
</programlisting>
<para>
After that, if the host and target os are the same, for example Linux, you can
- just request that this compiler version to be used:
+ just request that this compiler version be used:
</para>
<screen>
b2 toolset=gcc-arm
</screen>
<para>
- If you want to target different operating system from the host, you need
+ If you want to target a different operating system from the host, you need
to additionally specify the value for the <code>target-os</code> feature, for
example:
</para>
@@ -823,7 +823,7 @@ b2 toolset=gcc-mingw <emphasis role="bold">target-os=windows</emphasis>
</para>
<para>
- When using the msvc compiler, it's only possible to cross-compiler to a 64-bit system
+ When using the msvc compiler, it's only possible to cross-compile to a 64-bit system
on a 32-bit host. Please see <xref linkend="v2.reference.tools.compiler.msvc.64"/> for
details.
</para>
diff --git a/tools/build/doc/src/tutorial.xml b/tools/build/doc/src/tutorial.xml
index 3227a67184..e36ac1402a 100644
--- a/tools/build/doc/src/tutorial.xml
+++ b/tools/build/doc/src/tutorial.xml
@@ -179,7 +179,7 @@ exe hello
See <xref linkend="bbv2.reference.features.attributes"/>
</para>
</footnote>
- augments) the build request.
+ augment) the build request.
</para>
<tip>
@@ -384,7 +384,7 @@ project
lib foo : foo.cpp ;</programlisting>
Usage requirements are applied not to the target being declared but to its
- dependants. In this case, <literal>&lt;include&gt;.</literal> will be
+ dependents. In this case, <literal>&lt;include&gt;.</literal> will be
applied to all targets that directly depend on <filename>foo</filename>.
</para>
@@ -417,7 +417,7 @@ exe app : app.cpp /library-example/foo//bar ;</programlisting>
<tip>
<para>If you want all applications in some project to link to a certain
- library, you can avoid having to specify it directly the sources of
+ library, you can avoid having to specify directly the sources of
every target by using the <varname>&lt;library&gt;</varname> property.
For example, if <filename>/boost/filesystem//fs</filename> should be
linked to all applications in your project, you can add
@@ -433,7 +433,7 @@ project
</section>
<section id="bbv2.tutorial.linkage">
- <title>Static and shared libaries</title>
+ <title>Static and shared libraries</title>
<para>
Libraries can be either <emphasis>static</emphasis>, which means they are
@@ -621,8 +621,8 @@ lib lib2
exe app : app.cpp ../util/lib2//lib2 ;</programlisting>
As with any target, the alternative selected depends on the properties
- propagated from <filename>lib2</filename>'s dependants. If we build the
- release and debug versions of <filename>app</filename> will be linked
+ propagated from <filename>lib2</filename>'s dependents. If we build the
+ release and debug versions of <filename>app</filename> it will be linked
with <filename>lib2_release.a</filename> and <filename>lib2_debug.a
</filename>, respectively.
</para>
diff --git a/tools/build/example/complex-testing/compile-fail.cpp b/tools/build/example/complex-testing/compile-fail.cpp
new file mode 100644
index 0000000000..a219fa5c67
--- /dev/null
+++ b/tools/build/example/complex-testing/compile-fail.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2014 Rene Rivera
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include <iostream>
+#include <cstdlib>
+
+int main()
+{
+ std::cout << "Bye!\n";
+ return EXIT_FAILURE
+}
diff --git a/tools/build/example/complex-testing/fail.cpp b/tools/build/example/complex-testing/fail.cpp
new file mode 100644
index 0000000000..9656611887
--- /dev/null
+++ b/tools/build/example/complex-testing/fail.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2014 Rene Rivera
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include <iostream>
+#include <cstdlib>
+
+int main()
+{
+ std::cout << "Bye!\n";
+ return EXIT_FAILURE;
+}
diff --git a/tools/build/example/complex-testing/jamroot.jam b/tools/build/example/complex-testing/jamroot.jam
new file mode 100644
index 0000000000..a5942a239d
--- /dev/null
+++ b/tools/build/example/complex-testing/jamroot.jam
@@ -0,0 +1,15 @@
+# Copyright 2016 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+using testing ;
+import property-set ;
+import path ;
+
+exe success : success.cpp ;
+
+run success : arg1 arg2 : : : success-a ;
+run success : arg3 arg4 : : : success-b ;
+
+run post.cpp : : success-a : : post-a ;
+run post.cpp : : success-b : : post-b ;
diff --git a/tools/build/example/complex-testing/post.cpp b/tools/build/example/complex-testing/post.cpp
new file mode 100644
index 0000000000..6282e8f247
--- /dev/null
+++ b/tools/build/example/complex-testing/post.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2014 Rene Rivera
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include <iostream>
+#include <cstdlib>
+
+int main(int argc, char *argv[])
+{
+ std::cout << argv[1] << "\n";
+ return EXIT_SUCCESS;
+}
diff --git a/tools/build/example/complex-testing/success.cpp b/tools/build/example/complex-testing/success.cpp
new file mode 100644
index 0000000000..a7e2b6ca0a
--- /dev/null
+++ b/tools/build/example/complex-testing/success.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2014 Rene Rivera
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include <iostream>
+#include <cstdlib>
+
+int main(int argc, char *argv[])
+{
+ std::cout << "Hi!\n";
+ return EXIT_SUCCESS;
+}
diff --git a/tools/build/example/time/jamroot.jam b/tools/build/example/time/jamroot.jam
new file mode 100644
index 0000000000..9419b44377
--- /dev/null
+++ b/tools/build/example/time/jamroot.jam
@@ -0,0 +1,13 @@
+import feature ;
+import toolset ;
+import os ;
+import testing ;
+
+path-constant HERE : . ;
+make main.cpp : main_cpp.pro : @do-something ;
+time main.time : main.cpp ;
+
+actions do-something
+{
+ sleep 2 && echo "$(<)" > "$(<)"
+}
diff --git a/tools/build/example/time/main_cpp.pro b/tools/build/example/time/main_cpp.pro
new file mode 100644
index 0000000000..237c8ce181
--- /dev/null
+++ b/tools/build/example/time/main_cpp.pro
@@ -0,0 +1 @@
+int main() {}
diff --git a/tools/build/example/try_compile/Jamroot.jam b/tools/build/example/try_compile/Jamroot.jam
new file mode 100644
index 0000000000..893a03fdc6
--- /dev/null
+++ b/tools/build/example/try_compile/Jamroot.jam
@@ -0,0 +1,29 @@
+
+# This example shows performing configure checks in Boost.Build,
+# e.g. to check for some system function or compiler quirk.
+
+# First, declare a metatarget that we'll try to build.
+obj foo : foo.cpp ;
+# Make it explicit so that it's only built if used by a configure check
+explicit foo ;
+
+# Declare a target that depends on configure check result.
+exe main
+ : main.cpp
+ # The check-target-builds invocation in requirements section will
+ # - build the specified metatarget
+ # - if it builds OK, add the properties in the second parameter
+ # - otherwise, add the properties in the third parameter
+ : [ check-target-builds foo : <define>FOO=1 : <define>FOO=0 ]
+ ;
+
+# To test this:
+#
+# 1. Build with "b2". You should see a "foo builds: yes" message, and running
+# the produced executable will show that FOO is set to 1.
+# 2. Modify foo.cpp to contain a compile error, rebuild with
+# "b2 -a --reconfigure". You should see a "foo builds: no" message, and running
+# the produced executable should show that FOO is now set to 0.
+#
+# The output from the check is not shown on the console, instead it is
+# redirected to the bin/config.log file
diff --git a/tools/build/example/try_compile/foo.cpp b/tools/build/example/try_compile/foo.cpp
new file mode 100644
index 0000000000..c9107f9372
--- /dev/null
+++ b/tools/build/example/try_compile/foo.cpp
@@ -0,0 +1,6 @@
+
+
+int foo()
+{
+ return 0;
+} \ No newline at end of file
diff --git a/tools/build/example/try_compile/main.cpp b/tools/build/example/try_compile/main.cpp
new file mode 100644
index 0000000000..12f64995b0
--- /dev/null
+++ b/tools/build/example/try_compile/main.cpp
@@ -0,0 +1,8 @@
+
+#include <iostream>
+using namespace std;
+
+int main()
+{
+ std::cout << "Foo: " << FOO << "\n";
+} \ No newline at end of file
diff --git a/tools/build/example/user-config.jam b/tools/build/example/user-config.jam
index fbbf13fd0c..df86176cd7 100644
--- a/tools/build/example/user-config.jam
+++ b/tools/build/example/user-config.jam
@@ -22,7 +22,7 @@
# This file uses Jam language syntax to describe available tools. Mostly,
# there are 'using' lines, that contain the name of the used tools, and
-# parameters to pass to those tools -- where paremeters are separated by
+# parameters to pass to those tools -- where parameters are separated by
# semicolons. Important syntax notes:
#
# - Both ':' and ';' must be separated from other tokens by whitespace
diff --git a/tools/build/index.html b/tools/build/index.html
index fd08ee93b8..a42dc05f93 100644
--- a/tools/build/index.html
+++ b/tools/build/index.html
@@ -37,8 +37,7 @@
<p>Boost.Build makes it easy to build C++ projects, everywhere.
<p>
- You
- name you executables and libraries and list their sources. Boost.Build
+ You name your executables and libraries and list their sources. Boost.Build
takes care about compiling your sources with right options, creating
static and shared libraries, making executables, and other chores &mdash;
whether you're using gcc, msvc, or a dozen more supported C++
diff --git a/tools/build/notes/hacking.txt b/tools/build/notes/hacking.txt
deleted file mode 100644
index 3c059173bd..0000000000
--- a/tools/build/notes/hacking.txt
+++ /dev/null
@@ -1,138 +0,0 @@
-Copyright 2003, 2006 Vladimir Prus
-Distributed under the Boost Software License, Version 1.0.
-(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-
- ----------------------------------
- Boost.Build contributor guidelines
- ----------------------------------
-
-Boost.Build is an open-source project. This means that we welcome and appreciate
-all contributions --- be it ideas, bug reports, or patches. This document
-contains guidelines which helps to assure that development goes on smoothly, and
-changes are made quickly.
-
-The guidelines are not mandatory, and you can decide for yourself which one to
-follow. But note, that 10 mins that you spare writing a comment, for example,
-might lead to significally longer delay for everyone.
-
-Before contributing, make sure you are subscribed to our mailing list
-
- boost-build@lists.boost.org
-
-Additional resources include
-
- - The issue tracker
- http://trac.lvk.cs.msu.su/boost.build/
-
- - mailing list:
- boost-build@lists.boost.org
- http://lists.boost.org/boost-build/
-
-
-BUGS and PATCHES
-
-Both bugs and patches can be send to our mailing list.
-
-When reporting a bug, please try to provide the following information.
-
- - What you did. A minimal reproducible testcase is very much appreciated.
- Shell script with some annotations is much better than verbose description
- of the problem. A regression test is the best (see test/test_system.html).
- - What you got.
- - What you expected.
- - What version of Boost.Build and Boost.Jam did you use. If possible,
- please try to test with the CVS HEAD state.
-
-When submitting a patch, please:
-
- - make a single patch for a single logical change
- - follow the policies and coding conventions below,
- - send patches in unified diff format,
- (using either "cvs diff -u" or "diff -u")
- - provide a log message together with the patch
- - put the patch and the log message as attachment to your email.
-
-The purpose of log message serves to communicate what was changed, and *why*.
-Without a good log message, you might spend a lot of time later, wondering where
-a strange piece of code came from and why it was necessary.
-
-The good log message mentions each changed file and each rule/method, saying
-what happend to it, and why. Consider, the following log message
-
- Better direct request handling.
-
- * new/build-request.jam
- (directly-requested-properties-adjuster): Redo.
-
- * new/targets.jam
- (main-target.generate-really): Adjust properties here.
-
- * new/virtual-target.jam
- (register-actual-name): New rule.
- (virtual-target.actualize-no-scanner): Call the above, to detected bugs,
- where two virtual target correspond to one Jam target name.
-
-The log messages for the last two files are good. They tell what was changed.
-The change to the first file is clearly undercommented.
-
-It's OK to use terse log messages for uninteresting changes, like ones induced
-by interface changes elsewhere.
-
-
-POLICIES.
-
-1. Testing.
-
-All serious changes must be tested. New rules must be tested by the module where
-they are declared. Test system (test/test_system.html) should be used to verify
-user-observable behaviour.
-
-2. Documentation.
-
-It turns out that it's hard to have too much comments, but it's easy to have too
-little. Please prepend each rule with a comment saying what the rule does and
-what arguments mean. Stop for a minute and consider if the comment makes sense
-for anybody else, and completely describes what the rules does. Generic phrases
-like "adjusts properties" are really not enough.
-
-When applicable, make changes to the user documentation as well.
-
-
-CODING CONVENTIONS.
-
- 1. All names of rules and variables are lowercase with "-" to separate
- words.
-
- rule call-me-ishmael ( ) ...
-
- 2. Names with dots in them are "intended globals". Ordinary globals use a
- dot prefix:
-
- .foobar
- $(.foobar)
-
- 3. Pseudofunctions or associations are <parameter>.<property>:
-
- $(argument).name = hello ;
- $($(argument).name)
-
- 4. Class attribute names are prefixed with "self.":
-
- self.x
- $(self.x)
-
- 5. Builtin rules are called via their ALL_UPPERCASE_NAMES:
-
- DEPENDS $(target) : $(sources) ;
-
- 6. Opening and closing braces go on separate lines:
-
- if $(a)
- {
- #
- }
- else
- {
- #
- }
diff --git a/tools/build/src/__init__.py b/tools/build/src/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/src/__init__.py
diff --git a/tools/build/src/build-system.jam b/tools/build/src/build-system.jam
index 76db2d3778..185526c702 100644
--- a/tools/build/src/build-system.jam
+++ b/tools/build/src/build-system.jam
@@ -971,7 +971,15 @@ local rule should-clean-project ( project )
DEPENDS all : $(actual-targets) ;
if UPDATE_NOW in [ RULENAMES ]
{
- local ok = [ UPDATE_NOW all $(.out-xml) ] ;
+ local ok = [ UPDATE_NOW all ] ;
+ # Force sequence updating of regular targets, then the xml
+ # log output target. To ensure the output records all built
+ # as otherwise if could execute out-of-sequence when
+ # doing parallel builds.
+ if $(.out-xml)
+ {
+ UPDATE_NOW $(.out-xml) : : ignore-minus-n ;
+ }
if $(.post-build-hook)
{
$(.post-build-hook) $(ok) ;
diff --git a/tools/build/src/build/build_request.py b/tools/build/src/build/build_request.py
index 1942516887..4fa54072f8 100644
--- a/tools/build/src/build/build_request.py
+++ b/tools/build/src/build/build_request.py
@@ -56,7 +56,7 @@ def __x_product_aux (property_sets, seen_features):
these_features = set()
for p in property_sets[0].non_free():
- these_features.add(p.feature())
+ these_features.add(p.feature)
# Note: the algorithm as implemented here, as in original Jam code, appears to
# detect conflicts based on features, not properties. For example, if command
diff --git a/tools/build/src/build/engine.py b/tools/build/src/build/engine.py
index 4c2c97eaf3..6e49a8b5ea 100644
--- a/tools/build/src/build/engine.py
+++ b/tools/build/src/build/engine.py
@@ -16,21 +16,23 @@ from b2.util import set_jam_action, is_iterable
class BjamAction(object):
"""Class representing bjam action defined from Python."""
- def __init__(self, action_name, function):
+ def __init__(self, action_name, function, has_command=False):
assert isinstance(action_name, basestring)
assert callable(function) or function is None
self.action_name = action_name
self.function = function
+ self.has_command = has_command
def __call__(self, targets, sources, property_set_):
assert is_iterable(targets)
assert is_iterable(sources)
assert isinstance(property_set_, property_set.PropertySet)
- # Bjam actions defined from Python have only the command
- # to execute, and no associated jam procedural code. So
- # passing 'property_set' to it is not necessary.
- bjam_interface.call("set-update-action", self.action_name,
- targets, sources, [])
+ if self.has_command:
+ # Bjam actions defined from Python have only the command
+ # to execute, and no associated jam procedural code. So
+ # passing 'property_set' to it is not necessary.
+ bjam_interface.call("set-update-action", self.action_name,
+ targets, sources, [])
if self.function:
self.function(targets, sources, property_set_)
@@ -134,8 +136,11 @@ class Engine:
assert isinstance(variable, basestring)
assert is_iterable(value)
- for target in targets:
- self.do_set_target_variable (target, variable, value, append)
+ if targets:
+ if append:
+ bjam_interface.call("set-target-variable", targets, variable, value, "true")
+ else:
+ bjam_interface.call("set-target-variable", targets, variable, value)
def set_update_action (self, action_name, targets, sources, properties=None):
""" Binds a target to the corresponding update action.
@@ -158,7 +163,7 @@ class Engine:
self.do_set_update_action (action_name, targets, sources, properties)
- def register_action (self, action_name, command, bound_list = [], flags = [],
+ def register_action (self, action_name, command='', bound_list = [], flags = [],
function = None):
"""Creates a new build engine action.
@@ -190,7 +195,8 @@ class Engine:
if command:
bjam_interface.define_action(action_name, command, bound_list, bjam_flags)
- self.actions[action_name] = BjamAction(action_name, function)
+ self.actions[action_name] = BjamAction(
+ action_name, function, has_command=bool(command))
def register_bjam_action (self, action_name, function=None):
"""Informs self that 'action_name' is declared in bjam.
@@ -206,7 +212,7 @@ class Engine:
# action is already registered.
assert isinstance(action_name, basestring)
assert function is None or callable(function)
- if not self.actions.has_key(action_name):
+ if action_name not in self.actions:
self.actions[action_name] = BjamNativeAction(action_name, function)
# Overridables
diff --git a/tools/build/src/build/errors.py b/tools/build/src/build/errors.py
index 69d8a37d30..dd517395f8 100644
--- a/tools/build/src/build/errors.py
+++ b/tools/build/src/build/errors.py
@@ -123,5 +123,13 @@ class Errors:
stack=traceback.extract_stack())
-
-
+def nearest_user_location():
+ """
+ Returns:
+ tuple: the filename and line number of the nearest user location
+ """
+ bt = bjam.backtrace()
+ if not bt:
+ return None
+ last = bt[-1]
+ return last[0], last[1]
diff --git a/tools/build/src/build/feature.py b/tools/build/src/build/feature.py
index 6cf81a1a1f..85f6579ca6 100644
--- a/tools/build/src/build/feature.py
+++ b/tools/build/src/build/feature.py
@@ -9,6 +9,7 @@
import re
+from b2.manager import get_manager
from b2.util import utility, bjam_signature, is_iterable_typed
import b2.util.set
from b2.util.utility import add_grist, get_grist, ungrist, replace_grist, to_seq
@@ -18,108 +19,79 @@ __re_split_subfeatures = re.compile ('<(.*):(.*)>')
__re_no_hyphen = re.compile ('^([^:]+)$')
__re_slash_or_backslash = re.compile (r'[\\/]')
-class Feature(object):
+VALID_ATTRIBUTES = {
+ 'implicit',
+ 'composite',
+ 'optional',
+ 'symmetric',
+ 'free',
+ 'incidental',
+ 'path',
+ 'dependency',
+ 'propagated',
+ 'link-incompatible',
+ 'subfeature',
+ 'order-sensitive'
+}
- # Map from string attribute names to integers bit flags.
- # This will be initialized after declaration of the class.
- _attribute_name_to_integer = {}
+class Feature(object):
def __init__(self, name, values, attributes):
assert isinstance(name, basestring)
assert is_iterable_typed(values, basestring)
assert is_iterable_typed(attributes, basestring)
- self._name = name
- self._values = values
- self._default = None
- self._attributes = 0
- for a in attributes:
- self._attributes = self._attributes | Feature._attribute_name_to_integer[a]
- self._attributes_string_list = attributes
- self._subfeatures = []
- self._parent = None
-
- def name(self):
- return self._name
-
- def values(self):
- return self._values
+ self.name = name
+ self.values = values
+ self.default = None
+ self.subfeatures = []
+ self.parent = None
+ self.attributes_string_list = []
+ self._hash = hash(self.name)
+
+ for attr in attributes:
+ self.attributes_string_list.append(attr)
+ attr = attr.replace("-", "_")
+ setattr(self, attr, True)
def add_values(self, values):
assert is_iterable_typed(values, basestring)
- self._values.extend(values)
-
- def attributes(self):
- return self._attributes
+ self.values.extend(values)
def set_default(self, value):
assert isinstance(value, basestring)
for attr in ('free', 'optional'):
- if getattr(self, attr)():
+ if getattr(self, attr):
get_manager().errors()('"{}" feature "<{}>" cannot have a default value.'
- .format(attr, self._name))
-
- self._default = value
-
- def default(self):
- return self._default
+ .format(attr, self.name))
- # FIXME: remove when we fully move to using classes for features/properties
- def attributes_string_list(self):
- return self._attributes_string_list
-
- def subfeatures(self):
- return self._subfeatures
+ self.default = value
def add_subfeature(self, name):
assert isinstance(name, Feature)
- self._subfeatures.append(name)
-
- def parent(self):
- """For subfeatures, return pair of (parent_feature, value).
-
- Value may be None if this subfeature is not specific to any
- value of the parent feature.
- """
- return self._parent
+ self.subfeatures.append(name)
def set_parent(self, feature, value):
assert isinstance(feature, Feature)
assert isinstance(value, basestring)
- self._parent = (feature, value)
+ self.parent = (feature, value)
+
+ def __hash__(self):
+ return self._hash
def __str__(self):
- return self._name
+ return self.name
def reset ():
""" Clear the module state. This is mainly for testing purposes.
"""
global __all_attributes, __all_features, __implicit_features, __composite_properties
- global __features_with_attributes, __subfeature_from_value, __all_top_features, __free_features
+ global __subfeature_from_value, __all_top_features, __free_features
global __all_subfeatures
- # The list with all attribute names.
- __all_attributes = [ 'implicit',
- 'composite',
- 'optional',
- 'symmetric',
- 'free',
- 'incidental',
- 'path',
- 'dependency',
- 'propagated',
- 'link-incompatible',
- 'subfeature',
- 'order-sensitive'
- ]
- i = 1
- for a in __all_attributes:
- setattr(Feature, a.upper(), i)
- Feature._attribute_name_to_integer[a] = i
- def probe(self, flag=i):
- return getattr(self, "_attributes") & flag
- setattr(Feature, a.replace("-", "_"), probe)
- i = i << 1
+ # sets the default value of False for each valid attribute
+ for attr in VALID_ATTRIBUTES:
+ setattr(Feature, attr.replace("-", "_"), False)
# A map containing all features. The key is the feature name.
# The value is an instance of Feature class.
@@ -135,10 +107,6 @@ def reset ():
# and the value is a list of Property instances
__composite_properties = {}
- __features_with_attributes = {}
- for attribute in __all_attributes:
- __features_with_attributes [attribute] = []
-
# Maps a value to the corresponding subfeature name.
__subfeature_from_value = {}
@@ -178,9 +146,6 @@ def feature (name, values, attributes = []):
# Temporary measure while we have not fully moved from 'gristed strings'
__all_features["<" + name + ">"] = feature
- for attribute in attributes:
- __features_with_attributes [attribute].append (name)
-
name = add_grist(name)
if 'subfeature' in attributes:
@@ -203,19 +168,18 @@ def set_default (feature, value):
value: the default value to assign
"""
f = __all_features[feature]
- attributes = f.attributes()
bad_attribute = None
- if attributes & Feature.FREE:
+ if f.free:
bad_attribute = "free"
- elif attributes & Feature.OPTIONAL:
+ elif f.optional:
bad_attribute = "optional"
if bad_attribute:
- raise InvalidValue ("%s property %s cannot have a default" % (bad_attribute, feature.name()))
+ raise InvalidValue ("%s property %s cannot have a default" % (bad_attribute, f.name))
- if not value in f.values():
- raise InvalidValue ("The specified default value, '%s' is invalid.\n" % value + "allowed values are: %s" % f.values())
+ if value not in f.values:
+ raise InvalidValue ("The specified default value, '%s' is invalid.\n" % value + "allowed values are: %s" % f.values)
f.set_default(value)
@@ -228,8 +192,8 @@ def defaults(features):
result = []
for f in features:
- if not f.free() and not f.optional() and f.default():
- result.append(property.Property(f, f.default()))
+ if not f.free and not f.optional and f.default:
+ result.append(property.Property(f, f.default))
return result
@@ -246,26 +210,26 @@ def attributes (feature):
""" Returns the attributes of the given feature.
"""
assert isinstance(feature, basestring)
- return __all_features[feature].attributes_string_list()
+ return __all_features[feature].attributes_string_list
def values (feature):
""" Return the values of the given feature.
"""
assert isinstance(feature, basestring)
validate_feature (feature)
- return __all_features[feature].values()
+ return __all_features[feature].values
def is_implicit_value (value_string):
""" Returns true iff 'value_string' is a value_string
of an implicit feature.
"""
assert isinstance(value_string, basestring)
- if __implicit_features.has_key(value_string):
+ if value_string in __implicit_features:
return __implicit_features[value_string]
v = value_string.split('-')
- if not __implicit_features.has_key(v[0]):
+ if v[0] not in __implicit_features:
return False
feature = __implicit_features[v[0]]
@@ -282,7 +246,7 @@ def implied_feature (implicit_value):
assert isinstance(implicit_value, basestring)
components = implicit_value.split('-')
- if not __implicit_features.has_key(components[0]):
+ if components[0] not in __implicit_features:
raise InvalidValue ("'%s' is not a value of an implicit feature" % implicit_value)
return __implicit_features[components[0]]
@@ -318,11 +282,12 @@ def validate_feature (name):
""" Checks if all name is a valid feature. Otherwise, raises an exception.
"""
assert isinstance(name, basestring)
- if not __all_features.has_key(name):
+ if name not in __all_features:
raise InvalidFeature ("'%s' is not a valid feature name" % name)
else:
return __all_features[name]
+
# Uses Property
def __expand_subfeatures_aux (property_, dont_validate = False):
""" Helper for expand_subfeatures.
@@ -343,8 +308,8 @@ def __expand_subfeatures_aux (property_, dont_validate = False):
assert isinstance(property_, property.Property)
assert isinstance(dont_validate, int) # matches bools
- f = property_.feature()
- v = property_.value()
+ f = property_.feature
+ v = property_.value
if not dont_validate:
validate_value_string(f, v)
@@ -394,7 +359,7 @@ def expand_subfeatures(properties, dont_validate = False):
result = []
for p in properties:
# Don't expand subfeatures in subfeatures
- if p.feature().subfeature():
+ if p.feature.subfeature:
result.append (p)
else:
result.extend(__expand_subfeatures_aux (p, dont_validate))
@@ -420,7 +385,7 @@ def expand_subfeatures(properties, dont_validate = False):
# Now, the specific rule must be called, depending on the desired operation:
# extend_feature
# extend_subfeature
-
+@bjam_signature([['name'], ['values', '*']])
def extend (name, values):
""" Adds the given values to the given feature.
"""
@@ -430,14 +395,14 @@ def extend (name, values):
__validate_feature (name)
feature = __all_features [name]
- if feature.implicit():
+ if feature.implicit:
for v in values:
- if __implicit_features.has_key(v):
+ if v in __implicit_features:
raise BaseException ("'%s' is already associated with the feature '%s'" % (v, __implicit_features [v]))
__implicit_features[v] = feature
- if values and not feature.values() and not(feature.free() or feature.optional()):
+ if values and not feature.values and not(feature.free or feature.optional):
# This is the first value specified for this feature,
# take it as default value
feature.set_default(values[0])
@@ -449,20 +414,20 @@ def validate_value_string (f, value_string):
"""
assert isinstance(f, Feature)
assert isinstance(value_string, basestring)
- if f.free() or value_string in f.values():
+ if f.free or value_string in f.values:
return
values = [value_string]
- if f.subfeatures():
- if not value_string in f.values() and \
- not value_string in f.subfeatures():
+ if f.subfeatures:
+ if not value_string in f.values and \
+ not value_string in f.subfeatures:
values = value_string.split('-')
# An empty value is allowed for optional features
- if not values[0] in f.values() and \
- (values[0] or not f.optional()):
- raise InvalidValue ("'%s' is not a known value of feature '%s'\nlegal values: '%s'" % (values [0], f.name(), f.values()))
+ if not values[0] in f.values and \
+ (values[0] or not f.optional):
+ raise InvalidValue ("'%s' is not a known value of feature '%s'\nlegal values: '%s'" % (values [0], f.name, f.values))
for v in values [1:]:
# this will validate any subfeature values in value-string
@@ -503,11 +468,11 @@ def extend_subfeature (feature_name, value_string, subfeature_name, subvalues):
if value_string == None: value_string = ''
- if not __subfeature_from_value.has_key(feature):
- __subfeature_from_value [feature] = {}
+ if feature not in __subfeature_from_value:
+ __subfeature_from_value[feature] = {}
- if not __subfeature_from_value[feature].has_key(value_string):
- __subfeature_from_value [feature][value_string] = {}
+ if value_string not in __subfeature_from_value[feature]:
+ __subfeature_from_value[feature][value_string] = {}
for subvalue in subvalues:
__subfeature_from_value [feature][value_string][subvalue] = subfeature
@@ -529,7 +494,7 @@ def subfeature (feature_name, value_string, subfeature, subvalues, attributes =
# Add grist to the subfeature name if a value-string was supplied
subfeature_name = __get_subfeature_name (subfeature, value_string)
- if subfeature_name in __all_features[feature_name].subfeatures():
+ if subfeature_name in __all_features[feature_name].subfeatures:
message = "'%s' already declared as a subfeature of '%s'" % (subfeature, feature_name)
message += " specific to '%s'" % value_string
raise BaseException (message)
@@ -554,17 +519,17 @@ def compose (composite_property_s, component_properties_s):
component_properties_s = to_seq (component_properties_s)
composite_property = property.create_from_string(composite_property_s)
- f = composite_property.feature()
+ f = composite_property.feature
if len(component_properties_s) > 0 and isinstance(component_properties_s[0], property.Property):
component_properties = component_properties_s
else:
component_properties = [property.create_from_string(p) for p in component_properties_s]
- if not f.composite():
+ if not f.composite:
raise BaseException ("'%s' is not a composite feature" % f)
- if __composite_properties.has_key(property):
+ if property in __composite_properties:
raise BaseException ('components of "%s" already set: %s' % (composite_property, str (__composite_properties[composite_property])))
if composite_property in component_properties:
@@ -578,7 +543,7 @@ def expand_composite(property_):
from .property import Property
assert isinstance(property_, Property)
result = [ property_ ]
- if __composite_properties.has_key(property_):
+ if property_ in __composite_properties:
for p in __composite_properties[property_]:
result.extend(expand_composite(p))
return result
@@ -608,7 +573,7 @@ def expand_composites (properties):
if __debug__:
from .property import Property
assert is_iterable_typed(properties, Property)
- explicit_features = set(p.feature() for p in properties)
+ explicit_features = set(p.feature for p in properties)
result = []
@@ -618,23 +583,23 @@ def expand_composites (properties):
for x in expanded:
if not x in result:
- f = x.feature()
+ f = x.feature
- if f.free():
+ if f.free:
result.append (x)
elif not x in properties: # x is the result of expansion
if not f in explicit_features: # not explicitly-specified
- if any(r.feature() == f for r in result):
+ if any(r.feature == f for r in result):
raise FeatureConflict(
"expansions of composite features result in "
"conflicting values for '%s'\nvalues: '%s'\none contributing composite property was '%s'" %
- (f.name(), [r.value() for r in result if r.feature() == f] + [x.value()], p))
+ (f.name, [r.value for r in result if r.feature == f] + [x.value], p))
else:
result.append (x)
- elif any(r.feature() == f for r in result):
+ elif any(r.feature == f for r in result):
raise FeatureConflict ("explicitly-specified values of non-free feature '%s' conflict\n"
"existing values: '%s'\nvalue from expanding '%s': '%s'" % (f,
- [r.value() for r in result if r.feature() == f], p, x.value()))
+ [r.value for r in result if r.feature == f], p, x.value))
else:
result.append (x)
@@ -651,20 +616,20 @@ def is_subfeature_of (parent_property, f):
assert isinstance(parent_property, Property)
assert isinstance(f, Feature)
- if not f.subfeature():
+ if not f.subfeature:
return False
- p = f.parent()
+ p = f.parent
if not p:
return False
parent_feature = p[0]
parent_value = p[1]
- if parent_feature != parent_property.feature():
+ if parent_feature != parent_property.feature:
return False
- if parent_value and parent_value != parent_property.value():
+ if parent_value and parent_value != parent_property.value:
return False
return True
@@ -676,7 +641,7 @@ def __is_subproperty_of (parent_property, p):
from .property import Property
assert isinstance(parent_property, Property)
assert isinstance(p, Property)
- return is_subfeature_of (parent_property, p.feature())
+ return is_subfeature_of (parent_property, p.feature)
# Returns true iff the subvalue is valid for the feature. When the
@@ -735,28 +700,23 @@ def add_defaults (properties):
if __debug__:
from .property import Property
assert is_iterable_typed(properties, Property)
+ # create a copy since properties will be modified
+ result = list(properties)
- result = [x for x in properties]
-
- handled_features = set()
- for p in properties:
- # We don't add default for conditional properties. We don't want
- # <variant>debug:<define>DEBUG to be takes as specified value for <variant>
- if not p.condition():
- handled_features.add(p.feature())
+ # We don't add default for conditional properties. We don't want
+ # <variant>debug:<define>DEBUG to be takes as specified value for <variant>
+ handled_features = set(p.feature for p in properties if not p.condition)
missing_top = [f for f in __all_top_features if not f in handled_features]
more = defaults(missing_top)
result.extend(more)
- for p in more:
- handled_features.add(p.feature())
+ handled_features.update(p.feature for p in more)
# Add defaults for subfeatures of features which are present
for p in result[:]:
- s = p.feature().subfeatures()
- more = defaults([s for s in p.feature().subfeatures() if not s in handled_features])
- for p in more:
- handled_features.add(p.feature())
+ subfeatures = [s for s in p.feature.subfeatures if not s in handled_features]
+ more = defaults(__select_subfeatures(p, subfeatures))
+ handled_features.update(h.feature for h in more)
result.extend(more)
return result
@@ -775,29 +735,33 @@ def minimize (properties):
assert is_iterable_typed(properties, Property)
# remove properties implied by composite features
components = []
+ component_features = set()
for property in properties:
- if __composite_properties.has_key (property):
- components.extend(__composite_properties[property])
+ if property in __composite_properties:
+ cs = __composite_properties[property]
+ components.extend(cs)
+ component_features.update(c.feature for c in cs)
+
properties = b2.util.set.difference (properties, components)
# handle subfeatures and implicit features
# move subfeatures to the end of the list
- properties = [p for p in properties if not p.feature().subfeature()] +\
- [p for p in properties if p.feature().subfeature()]
+ properties = [p for p in properties if not p.feature.subfeature] +\
+ [p for p in properties if p.feature.subfeature]
result = []
while properties:
p = properties[0]
- f = p.feature()
+ f = p.feature
# locate all subproperties of $(x[1]) in the property set
- subproperties = __select_subproperties (p, properties)
+ subproperties = [x for x in properties if is_subfeature_of(p, x.feature)]
if subproperties:
# reconstitute the joined property name
subproperties.sort ()
- joined = b2.build.property.Property(p.feature(), p.value() + '-' + '-'.join ([sp.value() for sp in subproperties]))
+ joined = b2.build.property.Property(p.feature, p.value + '-' + '-'.join ([sp.value for sp in subproperties]))
result.append(joined)
properties = b2.util.set.difference(properties[1:], subproperties)
@@ -811,12 +775,8 @@ def minimize (properties):
# have been eliminated, any remaining property whose
# feature is the same as a component of a composite in the
# set must have a non-redundant value.
- if p.value() != f.default() or f.symmetric():
+ if p.value != f.default or f.symmetric or f in component_features:
result.append (p)
- #\
- #or get_grist (fullp) in get_grist (components):
- # FIXME: restore above
-
properties = properties[1:]
@@ -872,18 +832,18 @@ def compress_subproperties (properties):
matched_subs = set()
all_subs = set()
for p in properties:
- f = p.feature()
+ f = p.feature
- if not f.subfeature():
- subs = __select_subproperties (p, properties)
+ if not f.subfeature:
+ subs = [x for x in properties if is_subfeature_of(p, x.feature)]
if subs:
matched_subs.update(subs)
- subvalues = '-'.join (sub.value() for sub in subs)
+ subvalues = '-'.join (sub.value for sub in subs)
result.append(Property(
- p.feature(), p.value() + '-' + subvalues,
- p.condition()))
+ p.feature, p.value + '-' + subvalues,
+ p.condition))
else:
result.append(p)
@@ -920,7 +880,7 @@ def __validate_feature_attributes (name, attributes):
assert isinstance(name, basestring)
assert is_iterable_typed(attributes, basestring)
for attribute in attributes:
- if not attribute in __all_attributes:
+ if attribute not in VALID_ATTRIBUTES:
raise InvalidAttribute ("unknown attributes: '%s' in feature declaration: '%s'" % (str (b2.util.set.difference (attributes, __all_attributes)), name))
if name in __all_features:
@@ -935,7 +895,7 @@ def __validate_feature (feature):
""" Generates an error if the feature is unknown.
"""
assert isinstance(feature, basestring)
- if not __all_features.has_key (feature):
+ if feature not in __all_features:
raise BaseException ('unknown feature "%s"' % feature)
diff --git a/tools/build/src/build/generators.py b/tools/build/src/build/generators.py
index f1c5145560..a4a39d94dd 100644
--- a/tools/build/src/build/generators.py
+++ b/tools/build/src/build/generators.py
@@ -53,9 +53,10 @@ import os.path
from virtual_target import Subvariant
from . import virtual_target, type, property_set, property
+from b2.exceptions import BaseBoostBuildException
from b2.util.logger import *
from b2.util.utility import *
-from b2.util import set as set_, is_iterable_typed, is_iterable
+from b2.util import set as set_, is_iterable_typed, is_iterable, bjam_signature
from b2.util.sequence import unique
import b2.util.sequence as sequence
from b2.manager import get_manager
@@ -138,7 +139,7 @@ def invalidate_extendable_viable_source_target_type_cache():
__vstg_cached_generators = []
for g in generators_with_cached_source_types:
- if __viable_source_types_cache.has_key(g):
+ if g in __viable_source_types_cache:
if __viable_source_types_cache[g] == ["*"]:
__vstg_cached_generators.append(g)
else:
@@ -148,7 +149,7 @@ def invalidate_extendable_viable_source_target_type_cache():
types_with_cached_sources_types = __vst_cached_types
__vst_cached_types = []
for t in types_with_cached_sources_types:
- if __viable_source_types_cache.has_key(t):
+ if t in __viable_source_types_cache:
if __viable_source_types_cache[t] == ["*"]:
__vst_cached_types.append(t)
else:
@@ -158,6 +159,13 @@ def dout(message):
if debug():
print __indent + message
+
+class InvalidTargetSource(BaseBoostBuildException):
+ """
+ Should be raised when a target contains a source that is invalid.
+ """
+
+
class Generator:
""" Creates a generator.
manager: the build manager.
@@ -336,11 +344,16 @@ class Generator:
assert isinstance(name, basestring) or name is None
assert isinstance(prop_set, property_set.PropertySet)
assert is_iterable_typed(sources, virtual_target.VirtualTarget)
-
if project.manager ().logger ().on ():
project.manager ().logger ().log (__name__, " generator '%s'" % self.id_)
project.manager ().logger ().log (__name__, " composing: '%s'" % self.composing_)
+ if not sources:
+ s = 'An empty source list was passed in to the "{}" generator'.format(self.id_)
+ if name:
+ s += ' for target "{}"'.format(name)
+ raise InvalidTargetSource(s)
+
if not self.composing_ and len (sources) > 1 and len (self.source_types_) > 1:
raise BaseException ("Unsupported source/source_type combination")
@@ -368,24 +381,22 @@ class Generator:
assert isinstance(prop_set, property_set.PropertySet)
assert is_iterable_typed(sources, virtual_target.VirtualTarget)
# consumed: Targets that this generator will consume directly.
- # bypassed: Targets that can't be consumed and will be returned as-is.
if self.composing_:
- (consumed, bypassed) = self.convert_multiple_sources_to_consumable_types (project, prop_set, sources)
+ consumed = self.convert_multiple_sources_to_consumable_types (project, prop_set, sources)
else:
- (consumed, bypassed) = self.convert_to_consumable_types (project, name, prop_set, sources)
+ consumed = self.convert_to_consumable_types (project, name, prop_set, sources)
result = []
if consumed:
result = self.construct_result (consumed, project, name, prop_set)
- result.extend (bypassed)
if result:
if project.manager ().logger ().on ():
project.manager ().logger ().log (__name__, " SUCCESS: ", result)
else:
- project.manager ().logger ().log (__name__, " FAILURE")
+ project.manager ().logger ().log (__name__, " FAILURE")
return result
@@ -412,12 +423,9 @@ class Generator:
if len (self.source_types_) < 2 and not self.composing_:
for r in consumed:
- result.extend (self.generated_targets ([r], prop_set, project, name))
-
- else:
-
- if consumed:
- result.extend (self.generated_targets (consumed, prop_set, project, name))
+ result.extend(self.generated_targets([r], prop_set, project, name))
+ elif consumed:
+ result.extend(self.generated_targets(consumed, prop_set, project, name))
return result
@@ -527,7 +535,6 @@ class Generator:
Returns a pair:
consumed: all targets that can be consumed.
- bypassed: all targets that cannot be consumed.
"""
if __debug__:
from .targets import ProjectTarget
@@ -537,7 +544,6 @@ class Generator:
assert is_iterable_typed(sources, virtual_target.VirtualTarget)
assert isinstance(only_one, bool)
consumed = []
- bypassed = []
missing_types = []
if len (sources) > 1:
@@ -574,59 +580,45 @@ class Generator:
if t.type() in missing_types:
consumed.append(t)
- else:
- bypassed.append(t)
-
consumed = unique(consumed)
- bypassed = unique(bypassed)
-
- # remove elements of 'bypassed' that are in 'consumed'
- # Suppose the target type of current generator, X is produced from
- # X_1 and X_2, which are produced from Y by one generator.
- # When creating X_1 from Y, X_2 will be added to 'bypassed'
- # Likewise, when creating X_2 from Y, X_1 will be added to 'bypassed'
- # But they are also in 'consumed'. We have to remove them from
- # bypassed, so that generators up the call stack don't try to convert
- # them.
-
- # In this particular case, X_1 instance in 'consumed' and X_1 instance
- # in 'bypassed' will be the same: because they have the same source and
- # action name, and 'virtual-target.register' won't allow two different
- # instances. Therefore, it's OK to use 'set.difference'.
-
- bypassed = set.difference(bypassed, consumed)
-
- return (consumed, bypassed)
+ return consumed
def convert_multiple_sources_to_consumable_types (self, project, prop_set, sources):
""" Converts several files to consumable types.
"""
- consumed = []
- bypassed = []
if __debug__:
from .targets import ProjectTarget
assert isinstance(project, ProjectTarget)
assert isinstance(prop_set, property_set.PropertySet)
assert is_iterable_typed(sources, virtual_target.VirtualTarget)
+ if not self.source_types_:
+ return list(sources)
- assert isinstance(project, ProjectTarget)
- assert isinstance(prop_set, property_set.PropertySet)
- assert is_iterable_typed(sources, virtual_target.VirtualTarget)
- # We process each source one-by-one, trying to convert it to
- # a usable type.
- for s in sources:
- # TODO: need to check for failure on each source.
- (c, b) = self.convert_to_consumable_types (project, None, prop_set, [s], True)
- if not c:
- project.manager ().logger ().log (__name__, " failed to convert ", s)
+ acceptable_types = set()
+ for t in self.source_types_:
+ acceptable_types.update(type.all_derived(t))
+
+ result = []
+ for source in sources:
+ if source.type() not in acceptable_types:
+ transformed = construct_types(
+ project, None,self.source_types_, prop_set, [source])
+ # construct_types returns [prop_set, [targets]]
+ for t in transformed[1]:
+ if t.type() in self.source_types_:
+ result.append(t)
+ if not transformed:
+ project.manager().logger().log(__name__, " failed to convert ", source)
+ else:
+ result.append(source)
+
+ result = sequence.unique(result, stable=True)
+ return result
- consumed.extend (c)
- bypassed.extend (b)
- return (consumed, bypassed)
def consume_directly (self, source):
assert isinstance(source, virtual_target.VirtualTarget)
@@ -642,7 +634,7 @@ class Generator:
for st in source_types:
# The 'source' if of right type already)
if real_source_type == st or type.is_derived (real_source_type, st):
- consumed.append (source)
+ consumed = [source]
else:
missing_types.append (st)
@@ -726,6 +718,7 @@ def check_register_types(fn):
return wrapper
+@bjam_signature([['id'], ['source_types', '*'], ['target_types', '*'], ['requirements', '*']])
@check_register_types
def register_standard (id, source_types, target_types, requirements = []):
""" Creates new instance of the 'generator' class and registers it.
@@ -831,7 +824,7 @@ def viable_source_types (target_type):
""" Helper rule, caches the result of '__viable_source_types_real'.
"""
assert isinstance(target_type, basestring)
- if not __viable_source_types_cache.has_key(target_type):
+ if target_type not in __viable_source_types_cache:
__vst_cached_types.append(target_type)
__viable_source_types_cache [target_type] = __viable_source_types_real (target_type)
return __viable_source_types_cache [target_type]
@@ -867,7 +860,7 @@ def viable_source_types_for_generator (generator):
""" Caches the result of 'viable_source_types_for_generator'.
"""
assert isinstance(generator, Generator)
- if not __viable_source_types_cache.has_key(generator):
+ if generator not in __viable_source_types_cache:
__vstg_cached_generators.append(generator)
__viable_source_types_cache[generator] = viable_source_types_for_generator_real (generator)
diff --git a/tools/build/src/build/project.ann.py b/tools/build/src/build/project.ann.py
deleted file mode 100644
index 349f549550..0000000000
--- a/tools/build/src/build/project.ann.py
+++ /dev/null
@@ -1,996 +0,0 @@
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 1) # Status: being ported by Vladimir Prus
-ddc17f01 (vladimir_prus 2007-10-26 14:57:56 +0000 2) # Base revision: 40480
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 3)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 4) # Copyright 2002, 2003 Dave Abrahams
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 5) # Copyright 2002, 2005, 2006 Rene Rivera
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 6) # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 7) # Distributed under the Boost Software License, Version 1.0.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 8) # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 9)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 10) # Implements project representation and loading.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 11) # Each project is represented by
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 12) # - a module where all the Jamfile content live.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 13) # - an instance of 'project-attributes' class.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 14) # (given module name, can be obtained by 'attributes' rule)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 15) # - an instance of 'project-target' class (from targets.jam)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 16) # (given a module name, can be obtained by 'target' rule)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 17) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 18) # Typically, projects are created as result of loading Jamfile, which is
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 19) # do by rules 'load' and 'initialize', below. First, module for Jamfile
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 20) # is loaded and new project-attributes instance is created. Some rules
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 21) # necessary for project are added to the module (see 'project-rules' module)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 22) # at the bottom of this file.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 23) # Default project attributes are set (inheriting attributes of parent project, if
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 24) # it exists). After that, Jamfile is read. It can declare its own attributes,
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 25) # via 'project' rule, which will be combined with already set attributes.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 26) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 27) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 28) # The 'project' rule can also declare project id, which will be associated with
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 29) # the project module.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 30) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 31) # There can also be 'standalone' projects. They are created by calling 'initialize'
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 32) # on arbitrary module, and not specifying location. After the call, the module can
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 33) # call 'project' rule, declare main target and behave as regular projects. However,
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 34) # since it's not associated with any location, it's better declare only prebuilt
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 35) # targets.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 36) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 37) # The list of all loaded Jamfile is stored in variable .project-locations. It's possible
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 38) # to obtain module name for a location using 'module-name' rule. The standalone projects
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 39) # are not recorded, the only way to use them is by project id.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 40)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 41) import b2.util.path
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 42) from b2.build import property_set, property
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 43) from b2.build.errors import ExceptionWithUserContext
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 44) import b2.build.targets
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 45)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 46) import bjam
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 47)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 48) import re
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 49) import sys
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 50) import os
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 51) import string
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 52) import imp
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 53) import traceback
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 54)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 55) class ProjectRegistry:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 56)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 57) def __init__(self, manager, global_build_dir):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 58) self.manager = manager
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 59) self.global_build_dir = None
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 60) self.project_rules_ = ProjectRules(self)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 61)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 62) # The target corresponding to the project being loaded now
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 63) self.current_project = None
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 64)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 65) # The set of names of loaded project modules
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 66) self.jamfile_modules = {}
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 67)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 68) # Mapping from location to module name
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 69) self.location2module = {}
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 70)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 71) # Mapping from project id to project module
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 72) self.id2module = {}
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 73)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 74) # Map from Jamfile directory to parent Jamfile/Jamroot
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 75) # location.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 76) self.dir2parent_jamfile = {}
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 77)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 78) # Map from directory to the name of Jamfile in
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 79) # that directory (or None).
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 80) self.dir2jamfile = {}
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 81)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 82) # Map from project module to attributes object.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 83) self.module2attributes = {}
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 84)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 85) # Map from project module to target for the project
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 86) self.module2target = {}
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 87)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 88) # Map from names to Python modules, for modules loaded
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 89) # via 'using' and 'import' rules in Jamfiles.
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 90) self.loaded_tool_modules_ = {}
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 91)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 92) # Map from project target to the list of
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 93) # (id,location) pairs corresponding to all 'use-project'
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 94) # invocations.
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 95) # TODO: should not have a global map, keep this
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 96) # in ProjectTarget.
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 97) self.used_projects = {}
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 98)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 99) self.saved_current_project = []
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 100)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 101) self.JAMROOT = self.manager.getenv("JAMROOT");
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 102)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 103) # Note the use of character groups, as opposed to listing
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 104) # 'Jamroot' and 'jamroot'. With the latter, we'd get duplicate
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 105) # matches on windows and would have to eliminate duplicates.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 106) if not self.JAMROOT:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 107) self.JAMROOT = ["project-root.jam", "[Jj]amroot", "[Jj]amroot.jam"]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 108)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 109) # Default patterns to search for the Jamfiles to use for build
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 110) # declarations.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 111) self.JAMFILE = self.manager.getenv("JAMFILE")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 112)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 113) if not self.JAMFILE:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 114) self.JAMFILE = ["[Bb]uild.jam", "[Jj]amfile.v2", "[Jj]amfile",
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 115) "[Jj]amfile.jam"]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 116)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 117)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 118) def load (self, jamfile_location):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 119) """Loads jamfile at the given location. After loading, project global
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 120) file and jamfile needed by the loaded one will be loaded recursively.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 121) If the jamfile at that location is loaded already, does nothing.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 122) Returns the project module for the Jamfile."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 123)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 124) absolute = os.path.join(os.getcwd(), jamfile_location)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 125) absolute = os.path.normpath(absolute)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 126) jamfile_location = b2.util.path.relpath(os.getcwd(), absolute)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 127)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 128) if "--debug-loading" in self.manager.argv():
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 129) print "Loading Jamfile at '%s'" % jamfile_location
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 130)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 131)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 132) mname = self.module_name(jamfile_location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 133) # If Jamfile is already loaded, don't try again.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 134) if not mname in self.jamfile_modules:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 135)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 136) self.load_jamfile(jamfile_location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 137)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 138) # We want to make sure that child project are loaded only
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 139) # after parent projects. In particular, because parent projects
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 140) # define attributes whch are inherited by children, and we don't
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 141) # want children to be loaded before parents has defined everything.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 142) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 143) # While "build-project" and "use-project" can potentially refer
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 144) # to child projects from parent projects, we don't immediately
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 145) # load child projects when seing those attributes. Instead,
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 146) # we record the minimal information that will be used only later.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 147)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 148) self.load_used_projects(mname)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 149)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 150) return mname
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 151)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 152) def load_used_projects(self, module_name):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 153) # local used = [ modules.peek $(module-name) : .used-projects ] ;
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 154) used = self.used_projects[module_name]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 155)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 156) location = self.attribute(module_name, "location")
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 157) for u in used:
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 158) id = u[0]
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 159) where = u[1]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 160)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 161) self.use(id, os.path.join(location, where))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 162)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 163) def load_parent(self, location):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 164) """Loads parent of Jamfile at 'location'.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 165) Issues an error if nothing is found."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 166)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 167) found = b2.util.path.glob_in_parents(
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 168) location, self.JAMROOT + self.JAMFILE)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 169)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 170) if not found:
-1674e2d9 (jhunold 2008-08-08 19:52:05 +0000 171) print "error: Could not find parent for project at '%s'" % location
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 172) print "error: Did not find Jamfile or project-root.jam in any parent directory."
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 173) sys.exit(1)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 174)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 175) return self.load(os.path.dirname(found[0]))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 176)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 177) def act_as_jamfile(self, module, location):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 178) """Makes the specified 'module' act as if it were a regularly loaded Jamfile
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 179) at 'location'. If Jamfile is already located for that location, it's an
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 180) error."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 181)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 182) if self.module_name(location) in self.jamfile_modules:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 183) self.manager.errors()(
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 184) "Jamfile was already loaded for '%s'" % location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 185)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 186) # Set up non-default mapping from location to module.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 187) self.location2module[location] = module
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 188)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 189) # Add the location to the list of project locations
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 190) # so that we don't try to load Jamfile in future
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 191) self.jamfile_modules.append(location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 192)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 193) self.initialize(module, location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 194)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 195) def find(self, name, current_location):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 196) """Given 'name' which can be project-id or plain directory name,
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 197) return project module corresponding to that id or directory.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 198) Returns nothing of project is not found."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 199)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 200) project_module = None
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 201)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 202) # Try interpreting name as project id.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 203) if name[0] == '/':
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 204) project_module = self.id2module.get(name)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 205)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 206) if not project_module:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 207) location = os.path.join(current_location, name)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 208) # If no project is registered for the given location, try to
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 209) # load it. First see if we have Jamfile. If not we might have project
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 210) # root, willing to act as Jamfile. In that case, project-root
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 211) # must be placed in the directory referred by id.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 212)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 213) project_module = self.module_name(location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 214) if not project_module in self.jamfile_modules and \
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 215) b2.util.path.glob([location], self.JAMROOT + self.JAMFILE):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 216) project_module = self.load(location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 217)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 218) return project_module
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 219)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 220) def module_name(self, jamfile_location):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 221) """Returns the name of module corresponding to 'jamfile-location'.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 222) If no module corresponds to location yet, associates default
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 223) module name with that location."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 224) module = self.location2module.get(jamfile_location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 225) if not module:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 226) # Root the path, so that locations are always umbiguious.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 227) # Without this, we can't decide if '../../exe/program1' and '.'
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 228) # are the same paths, or not.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 229) jamfile_location = os.path.realpath(
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 230) os.path.join(os.getcwd(), jamfile_location))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 231) module = "Jamfile<%s>" % jamfile_location
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 232) self.location2module[jamfile_location] = module
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 233) return module
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 234)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 235) def find_jamfile (self, dir, parent_root=0, no_errors=0):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 236) """Find the Jamfile at the given location. This returns the
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 237) exact names of all the Jamfiles in the given directory. The optional
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 238) parent-root argument causes this to search not the given directory
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 239) but the ones above it up to the directory given in it."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 240)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 241) # Glob for all the possible Jamfiles according to the match pattern.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 242) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 243) jamfile_glob = None
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 244) if parent_root:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 245) parent = self.dir2parent_jamfile.get(dir)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 246) if not parent:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 247) parent = b2.util.path.glob_in_parents(dir,
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 248) self.JAMFILE)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 249) self.dir2parent_jamfile[dir] = parent
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 250) jamfile_glob = parent
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 251) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 252) jamfile = self.dir2jamfile.get(dir)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 253) if not jamfile:
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 254) jamfile = b2.util.path.glob([dir], self.JAMFILE)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 255) self.dir2jamfile[dir] = jamfile
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 256) jamfile_glob = jamfile
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 257)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 258) if len(jamfile_glob):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 259) # Multiple Jamfiles found in the same place. Warn about this.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 260) # And ensure we use only one of them.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 261) # As a temporary convenience measure, if there's Jamfile.v2 amount
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 262) # found files, suppress the warning and use it.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 263) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 264) pattern = "(.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam)"
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 265) v2_jamfiles = [x for x in jamfile_glob if re.match(pattern, x)]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 266) if len(v2_jamfiles) == 1:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 267) jamfile_glob = v2_jamfiles
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 268) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 269) print """warning: Found multiple Jamfiles at '%s'!
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 270) Loading the first one: '%s'.""" % (dir, jamfile_glob[0])
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 271)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 272) # Could not find it, error.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 273) if not no_errors and not jamfile_glob:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 274) self.manager.errors()(
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 275) """Unable to load Jamfile.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 276) Could not find a Jamfile in directory '%s'
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 277) Attempted to find it with pattern '%s'.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 278) Please consult the documentation at 'http://boost.org/b2.'."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 279) % (dir, string.join(self.JAMFILE)))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 280)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 281) return jamfile_glob[0]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 282)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 283) def load_jamfile(self, dir):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 284) """Load a Jamfile at the given directory. Returns nothing.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 285) Will attempt to load the file as indicated by the JAMFILE patterns.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 286) Effect of calling this rule twice with the same 'dir' is underfined."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 287)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 288) # See if the Jamfile is where it should be.
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 289) jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 290) if not jamfile_to_load:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 291) jamfile_to_load = self.find_jamfile(dir)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 292) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 293) jamfile_to_load = jamfile_to_load[0]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 294)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 295) # The module of the jamfile.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 296) dir = os.path.realpath(os.path.dirname(jamfile_to_load))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 297)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 298) jamfile_module = self.module_name (dir)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 299)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 300) # Initialize the jamfile module before loading.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 301) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 302) self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 303)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 304) saved_project = self.current_project
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 305)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 306) self.used_projects[jamfile_module] = []
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 307)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 308) # Now load the Jamfile in it's own context.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 309) # Initialization might have load parent Jamfiles, which might have
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 310) # loaded the current Jamfile with use-project. Do a final check to make
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 311) # sure it's not loaded already.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 312) if not jamfile_module in self.jamfile_modules:
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 313) self.jamfile_modules[jamfile_module] = True
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 314)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 315) # FIXME:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 316) # mark-as-user $(jamfile-module) ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 317)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 318) bjam.call("load", jamfile_module, jamfile_to_load)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 319) basename = os.path.basename(jamfile_to_load)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 320)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 321) # Now do some checks
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 322) if self.current_project != saved_project:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 323) self.manager.errors()(
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 324) """The value of the .current-project variable
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 325) has magically changed after loading a Jamfile.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 326) This means some of the targets might be defined a the wrong project.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 327) after loading %s
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 328) expected value %s
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 329) actual value %s""" % (jamfile_module, saved_project, self.current_project))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 330)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 331) if self.global_build_dir:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 332) id = self.attribute(jamfile_module, "id")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 333) project_root = self.attribute(jamfile_module, "project-root")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 334) location = self.attribute(jamfile_module, "location")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 335)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 336) if location and project_root == dir:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 337) # This is Jamroot
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 338) if not id:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 339) # FIXME: go via errors module, so that contexts are
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 340) # shown?
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 341) print "warning: the --build-dir option was specified"
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 342) print "warning: but Jamroot at '%s'" % dir
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 343) print "warning: specified no project id"
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 344) print "warning: the --build-dir option will be ignored"
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 345)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 346)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 347) def load_standalone(self, jamfile_module, file):
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 348) """Loads 'file' as standalone project that has no location
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 349) associated with it. This is mostly useful for user-config.jam,
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 350) which should be able to define targets, but although it has
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 351) some location in filesystem, we don't want any build to
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 352) happen in user's HOME, for example.
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 353)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 354) The caller is required to never call this method twice on
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 355) the same file.
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 356) """
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 357)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 358) self.initialize(jamfile_module)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 359) self.used_projects[jamfile_module] = []
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 360) bjam.call("load", jamfile_module, file)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 361) self.load_used_projects(jamfile_module)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 362)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 363) def is_jamroot(self, basename):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 364) match = [ pat for pat in self.JAMROOT if re.match(pat, basename)]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 365) if match:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 366) return 1
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 367) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 368) return 0
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 369)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 370) def initialize(self, module_name, location=None, basename=None):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 371) """Initialize the module for a project.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 372)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 373) module-name is the name of the project module.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 374) location is the location (directory) of the project to initialize.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 375) If not specified, stanalone project will be initialized
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 376) """
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 377)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 378) if "--debug-loading" in self.manager.argv():
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 379) print "Initializing project '%s'" % module_name
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 380)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 381) # TODO: need to consider if standalone projects can do anything but defining
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 382) # prebuilt targets. If so, we need to give more sensible "location", so that
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 383) # source paths are correct.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 384) if not location:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 385) location = ""
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 386) else:
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 387) location = b2.util.path.relpath(os.getcwd(), location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 388)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 389) attributes = ProjectAttributes(self.manager, location, module_name)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 390) self.module2attributes[module_name] = attributes
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 391)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 392) if location:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 393) attributes.set("source-location", location, exact=1)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 394) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 395) attributes.set("source-location", "", exact=1)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 396)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 397) attributes.set("requirements", property_set.empty(), exact=True)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 398) attributes.set("usage-requirements", property_set.empty(), exact=True)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 399) attributes.set("default-build", [], exact=True)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 400) attributes.set("projects-to-build", [], exact=True)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 401) attributes.set("project-root", None, exact=True)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 402) attributes.set("build-dir", None, exact=True)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 403)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 404) self.project_rules_.init_project(module_name)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 405)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 406) jamroot = False
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 407)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 408) parent_module = None;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 409) if module_name == "site-config":
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 410) # No parent
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 411) pass
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 412) elif module_name == "user-config":
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 413) parent_module = "site-config"
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 414) elif location and not self.is_jamroot(basename):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 415) # We search for parent/project-root only if jamfile was specified
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 416) # --- i.e
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 417) # if the project is not standalone.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 418) parent_module = self.load_parent(location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 419) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 420) # It's either jamroot, or standalone project.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 421) # If it's jamroot, inherit from user-config.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 422) if location:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 423) parent_module = "user-config" ;
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 424) jamroot = True ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 425)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 426) if parent_module:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 427) self.inherit_attributes(module_name, parent_module)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 428) attributes.set("parent-module", parent_module, exact=1)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 429)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 430) if jamroot:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 431) attributes.set("project-root", location, exact=1)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 432)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 433) parent = None
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 434) if parent_module:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 435) parent = self.target(parent_module)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 436)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 437) if not self.module2target.has_key(module_name):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 438) target = b2.build.targets.ProjectTarget(self.manager,
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 439) module_name, module_name, parent,
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 440) self.attribute(module_name,"requirements"),
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 441) # FIXME: why we need to pass this? It's not
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 442) # passed in jam code.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 443) self.attribute(module_name, "default-build"))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 444) self.module2target[module_name] = target
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 445)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 446) self.current_project = self.target(module_name)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 447)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 448) def inherit_attributes(self, project_module, parent_module):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 449) """Make 'project-module' inherit attributes of project
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 450) root and parent module."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 451)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 452) attributes = self.module2attributes[project_module]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 453) pattributes = self.module2attributes[parent_module]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 454)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 455) # Parent module might be locationless user-config.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 456) # FIXME:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 457) #if [ modules.binding $(parent-module) ]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 458) #{
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 459) # $(attributes).set parent : [ path.parent
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 460) # [ path.make [ modules.binding $(parent-module) ] ] ] ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 461) # }
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 462)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 463) attributes.set("project-root", pattributes.get("project-root"), exact=True)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 464) attributes.set("default-build", pattributes.get("default-build"), exact=True)
-49c03622 (jhunold 2008-07-23 09:57:41 +0000 465) attributes.set("requirements", pattributes.get("requirements"), exact=True)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 466) attributes.set("usage-requirements",
-cde6f09a (vladimir_prus 2007-10-19 23:12:33 +0000 467) pattributes.get("usage-requirements"), exact=1)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 468)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 469) parent_build_dir = pattributes.get("build-dir")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 470)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 471) if parent_build_dir:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 472) # Have to compute relative path from parent dir to our dir
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 473) # Convert both paths to absolute, since we cannot
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 474) # find relative path from ".." to "."
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 475)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 476) location = attributes.get("location")
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 477) parent_location = pattributes.get("location")
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 478)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 479) our_dir = os.path.join(os.getcwd(), location)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 480) parent_dir = os.path.join(os.getcwd(), parent_location)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 481)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 482) build_dir = os.path.join(parent_build_dir,
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 483) b2.util.path.relpath(parent_dir,
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 484) our_dir))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 485)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 486) def register_id(self, id, module):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 487) """Associate the given id with the given project module."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 488) self.id2module[id] = module
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 489)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 490) def current(self):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 491) """Returns the project which is currently being loaded."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 492) return self.current_project
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 493)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 494) def push_current(self, project):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 495) """Temporary changes the current project to 'project'. Should
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 496) be followed by 'pop-current'."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 497) self.saved_current_project.append(self.current_project)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 498) self.current_project = project
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 499)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 500) def pop_current(self):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 501) self.current_project = self.saved_current_project[-1]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 502) del self.saved_current_project[-1]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 503)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 504) def attributes(self, project):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 505) """Returns the project-attribute instance for the
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 506) specified jamfile module."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 507) return self.module2attributes[project]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 508)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 509) def attribute(self, project, attribute):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 510) """Returns the value of the specified attribute in the
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 511) specified jamfile module."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 512) return self.module2attributes[project].get(attribute)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 513)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 514) def target(self, project_module):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 515) """Returns the project target corresponding to the 'project-module'."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 516) if not self.module2target[project_module]:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 517) self.module2target[project_module] = \
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 518) ProjectTarget(project_module, project_module,
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 519) self.attribute(project_module, "requirements"))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 520)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 521) return self.module2target[project_module]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 522)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 523) def use(self, id, location):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 524) # Use/load a project.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 525) saved_project = self.current_project
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 526) project_module = self.load(location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 527) declared_id = self.attribute(project_module, "id")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 528)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 529) if not declared_id or declared_id != id:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 530) # The project at 'location' either have no id or
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 531) # that id is not equal to the 'id' parameter.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 532) if self.id2module[id] and self.id2module[id] != project_module:
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 533) self.manager.errors()(
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 534) """Attempt to redeclare already existing project id '%s'""" % id)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 535) self.id2module[id] = project_module
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 536)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 537) self.current_module = saved_project
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 538)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 539) def add_rule(self, name, callable):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 540) """Makes rule 'name' available to all subsequently loaded Jamfiles.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 541)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 542) Calling that rule wil relay to 'callable'."""
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 543) self.project_rules_.add_rule(name, callable)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 544)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 545) def project_rules(self):
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 546) return self.project_rules_
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 547)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 548) def glob_internal(self, project, wildcards, excludes, rule_name):
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 549) location = project.get("source-location")
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 550)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 551) result = []
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 552) callable = b2.util.path.__dict__[rule_name]
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 553)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 554) paths = callable(location, wildcards, excludes)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 555) has_dir = 0
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 556) for w in wildcards:
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 557) if os.path.dirname(w):
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 558) has_dir = 1
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 559) break
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 560)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 561) if has_dir or rule_name != "glob":
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 562) # The paths we've found are relative to current directory,
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 563) # but the names specified in sources list are assumed to
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 564) # be relative to source directory of the corresponding
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 565) # prject. So, just make the name absolute.
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 566) result = [os.path.join(os.getcwd(), p) for p in paths]
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 567) else:
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 568) # There were not directory in wildcard, so the files are all
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 569) # in the source directory of the project. Just drop the
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 570) # directory, instead of making paths absolute.
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 571) result = [os.path.basename(p) for p in paths]
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 572)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 573) return result
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 574)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 575) def load_module(self, name, extra_path=None):
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 576) """Classic Boost.Build 'modules' are in fact global variables.
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 577) Therefore, try to find an already loaded Python module called 'name' in sys.modules.
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 578) If the module ist not loaded, find it Boost.Build search
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 579) path and load it. The new module is not entered in sys.modules.
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 580) The motivation here is to have disjoint namespace of modules
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 581) loaded via 'import/using' in Jamfile, and ordinary Python
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 582) modules. We don't want 'using foo' in Jamfile to load ordinary
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 583) Python module 'foo' which is going to not work. And we
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 584) also don't want 'import foo' in regular Python module to
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 585) accidentally grab module named foo that is internal to
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 586) Boost.Build and intended to provide interface to Jamfiles."""
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 587)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 588) existing = self.loaded_tool_modules_.get(name)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 589) if existing:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 590) return existing
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 591)
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 592) modules = sys.modules
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 593) for class_name in modules:
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 594) if name in class_name:
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 595) module = modules[class_name]
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 596) self.loaded_tool_modules_[name] = module
-53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 597) return module
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 598)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 599) path = extra_path
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 600) if not path:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 601) path = []
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 602) path.extend(self.manager.b2.path())
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 603) location = None
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 604) for p in path:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 605) l = os.path.join(p, name + ".py")
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 606) if os.path.exists(l):
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 607) location = l
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 608) break
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 609)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 610) if not location:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 611) self.manager.errors()("Cannot find module '%s'" % name)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 612)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 613) mname = "__build_build_temporary__"
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 614) file = open(location)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 615) try:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 616) # TODO: this means we'll never make use of .pyc module,
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 617) # which might be a problem, or not.
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 618) module = imp.load_module(mname, file, os.path.basename(location),
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 619) (".py", "r", imp.PY_SOURCE))
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 620) del sys.modules[mname]
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 621) self.loaded_tool_modules_[name] = module
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 622) return module
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 623) finally:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 624) file.close()
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 625)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 626)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 627)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 628) # FIXME:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 629) # Defines a Boost.Build extension project. Such extensions usually
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 630) # contain library targets and features that can be used by many people.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 631) # Even though extensions are really projects, they can be initialize as
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 632) # a module would be with the "using" (project.project-rules.using)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 633) # mechanism.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 634) #rule extension ( id : options * : * )
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 635) #{
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 636) # # The caller is a standalone module for the extension.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 637) # local mod = [ CALLER_MODULE ] ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 638) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 639) # # We need to do the rest within the extension module.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 640) # module $(mod)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 641) # {
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 642) # import path ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 643) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 644) # # Find the root project.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 645) # local root-project = [ project.current ] ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 646) # root-project = [ $(root-project).project-module ] ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 647) # while
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 648) # [ project.attribute $(root-project) parent-module ] &&
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 649) # [ project.attribute $(root-project) parent-module ] != user-config
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 650) # {
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 651) # root-project = [ project.attribute $(root-project) parent-module ] ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 652) # }
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 653) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 654) # # Create the project data, and bring in the project rules
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 655) # # into the module.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 656) # project.initialize $(__name__) :
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 657) # [ path.join [ project.attribute $(root-project) location ] ext $(1:L) ] ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 658) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 659) # # Create the project itself, i.e. the attributes.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 660) # # All extensions are created in the "/ext" project space.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 661) # project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 662) # local attributes = [ project.attributes $(__name__) ] ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 663) #
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 664) # # Inherit from the root project of whomever is defining us.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 665) # project.inherit-attributes $(__name__) : $(root-project) ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 666) # $(attributes).set parent-module : $(root-project) : exact ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 667) # }
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 668) #}
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 669)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 670)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 671) class ProjectAttributes:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 672) """Class keeping all the attributes of a project.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 673)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 674) The standard attributes are 'id', "location", "project-root", "parent"
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 675) "requirements", "default-build", "source-location" and "projects-to-build".
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 676) """
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 677)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 678) def __init__(self, manager, location, project_module):
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 679) self.manager = manager
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 680) self.location = location
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 681) self.project_module = project_module
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 682) self.attributes = {}
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 683) self.usage_requirements = None
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 684)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 685) def set(self, attribute, specification, exact):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 686) """Set the named attribute from the specification given by the user.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 687) The value actually set may be different."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 688)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 689) if exact:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 690) self.__dict__[attribute] = specification
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 691)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 692) elif attribute == "requirements":
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 693) self.requirements = property_set.refine_from_user_input(
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 694) self.requirements, specification,
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 695) self.project_module, self.location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 696)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 697) elif attribute == "usage-requirements":
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 698) unconditional = []
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 699) for p in specification:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 700) split = property.split_conditional(p)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 701) if split:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 702) unconditional.append(split[1])
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 703) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 704) unconditional.append(p)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 705)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 706) non_free = property.remove("free", unconditional)
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 707) if non_free:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 708) pass
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 709) # FIXME:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 710) #errors.error "usage-requirements" $(specification) "have non-free properties" $(non-free) ;
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 711)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 712) t = property.translate_paths(specification, self.location)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 713)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 714) existing = self.__dict__.get("usage-requirements")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 715) if existing:
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 716) new = property_set.create(existing.raw() + t)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 717) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 718) new = property_set.create(t)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 719) self.__dict__["usage-requirements"] = new
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 720)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 721)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 722) elif attribute == "default-build":
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 723) self.__dict__["default-build"] = property_set.create(specification)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 724)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 725) elif attribute == "source-location":
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 726) source_location = []
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 727) for path in specification:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 728) source_location += os.path.join(self.location, path)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 729) self.__dict__["source-location"] = source_location
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 730)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 731) elif attribute == "build-dir":
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 732) self.__dict__["build-dir"] = os.path.join(self.location, specification)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 733)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 734) elif not attribute in ["id", "default-build", "location",
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 735) "source-location", "parent",
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 736) "projects-to-build", "project-root"]:
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 737) self.manager.errors()(
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 738) """Invalid project attribute '%s' specified
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 739) for project at '%s'""" % (attribute, self.location))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 740) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 741) self.__dict__[attribute] = specification
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 742)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 743) def get(self, attribute):
-cde6f09a (vladimir_prus 2007-10-19 23:12:33 +0000 744) return self.__dict__[attribute]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 745)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 746) def dump(self):
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 747) """Prints the project attributes."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 748) id = self.get("id")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 749) if not id:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 750) id = "(none)"
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 751) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 752) id = id[0]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 753)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 754) parent = self.get("parent")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 755) if not parent:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 756) parent = "(none)"
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 757) else:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 758) parent = parent[0]
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 759)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 760) print "'%s'" % id
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 761) print "Parent project:%s", parent
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 762) print "Requirements:%s", self.get("requirements")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 763) print "Default build:%s", string.join(self.get("debuild-build"))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 764) print "Source location:%s", string.join(self.get("source-location"))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 765) print "Projects to build:%s", string.join(self.get("projects-to-build").sort());
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 766)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 767) class ProjectRules:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 768) """Class keeping all rules that are made available to Jamfile."""
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 769)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 770) def __init__(self, registry):
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 771) self.registry = registry
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 772) self.manager_ = registry.manager
-38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 773) self.rules = {}
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 774) self.local_names = [x for x in self.__class__.__dict__
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 775) if x not in ["__init__", "init_project", "add_rule",
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 776) "error_reporting_wrapper", "add_rule_for_type"]]
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 777) self.all_names_ = [x for x in self.local_names]
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 778)
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 779) def add_rule_for_type(self, type):
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 780) rule_name = type.lower();
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 781)
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 782) def xpto (name, sources, requirements = [], default_build = None, usage_requirements = []):
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 783) return self.manager_.targets().create_typed_target(
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 784) type, self.registry.current(), name[0], sources,
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 785) requirements, default_build, usage_requirements)
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 786)
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 787) self.add_rule(type.lower(), xpto)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 788)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 789) def add_rule(self, name, callable):
-38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 790) self.rules[name] = callable
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 791) self.all_names_.append(name)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 792)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 793) def all_names(self):
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 794) return self.all_names_
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 795)
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 796) def call_and_report_errors(self, callable, *args):
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 797) result = None
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 798) try:
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 799) self.manager_.errors().push_jamfile_context()
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 800) result = callable(*args)
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 801) except ExceptionWithUserContext, e:
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 802) e.report()
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 803) except Exception, e:
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 804) try:
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 805) self.manager_.errors().handle_stray_exception (e)
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 806) except ExceptionWithUserContext, e:
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 807) e.report()
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 808) finally:
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 809) self.manager_.errors().pop_jamfile_context()
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 810)
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 811) return result
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 812)
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 813) def make_wrapper(self, callable):
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 814) """Given a free-standing function 'callable', return a new
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 815) callable that will call 'callable' and report all exceptins,
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 816) using 'call_and_report_errors'."""
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 817) def wrapper(*args):
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 818) self.call_and_report_errors(callable, *args)
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 819) return wrapper
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 820)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 821) def init_project(self, project_module):
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 822)
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 823) for n in self.local_names:
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 824) # Using 'getattr' here gives us a bound method,
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 825) # while using self.__dict__[r] would give unbound one.
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 826) v = getattr(self, n)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 827) if callable(v):
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 828) if n == "import_":
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 829) n = "import"
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 830) else:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 831) n = string.replace(n, "_", "-")
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 832)
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 833) bjam.import_rule(project_module, n,
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 834) self.make_wrapper(v))
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 835)
-38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 836) for n in self.rules:
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 837) bjam.import_rule(project_module, n,
-0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 838) self.make_wrapper(self.rules[n]))
-38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 839)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 840) def project(self, *args):
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 841)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 842) jamfile_module = self.registry.current().project_module()
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 843) attributes = self.registry.attributes(jamfile_module)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 844)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 845) id = None
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 846) if args and args[0]:
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 847) id = args[0][0]
-092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 848) args = args[1:]
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 849)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 850) if id:
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 851) if id[0] != '/':
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 852) id = '/' + id
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 853) self.registry.register_id (id, jamfile_module)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 854)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 855) explicit_build_dir = None
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 856) for a in args:
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 857) if a:
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 858) attributes.set(a[0], a[1:], exact=0)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 859) if a[0] == "build-dir":
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 860) explicit_build_dir = a[1]
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 861)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 862) # If '--build-dir' is specified, change the build dir for the project.
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 863) if self.registry.global_build_dir:
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 864)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 865) location = attributes.get("location")
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 866) # Project with empty location is 'standalone' project, like
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 867) # user-config, or qt. It has no build dir.
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 868) # If we try to set build dir for user-config, we'll then
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 869) # try to inherit it, with either weird, or wrong consequences.
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 870) if location and location == attributes.get("project-root"):
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 871) # This is Jamroot.
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 872) if id:
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 873) if explicit_build_dir and os.path.isabs(explicit_build_dir):
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 874) self.register.manager.errors()(
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 875) """Absolute directory specified via 'build-dir' project attribute
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 876) Don't know how to combine that with the --build-dir option.""")
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 877)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 878) rid = id
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 879) if rid[0] == '/':
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 880) rid = rid[1:]
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 881)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 882) p = os.path.join(self.registry.global_build_dir,
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 883) rid, explicit_build_dir)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 884) attributes.set("build-dir", p, exact=1)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 885) elif explicit_build_dir:
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 886) self.registry.manager.errors()(
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 887) """When --build-dir is specified, the 'build-project'
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 888) attribute is allowed only for top-level 'project' invocations""")
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 889)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 890) def constant(self, name, value):
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 891) """Declare and set a project global constant.
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 892) Project global constants are normal variables but should
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 893) not be changed. They are applied to every child Jamfile."""
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 894) m = "Jamfile</home/ghost/Work/Boost/boost-svn/tools/build/v2_python/python/tests/bjam/make>"
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 895) self.registry.current().add_constant(name[0], value)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 896)
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 897) def path_constant(self, name, value):
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 898) """Declare and set a project global constant, whose value is a path. The
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 899) path is adjusted to be relative to the invocation directory. The given
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 900) value path is taken to be either absolute, or relative to this project
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 901) root."""
-0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 902) self.registry.current().add_constant(name[0], value, path=1)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 903)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 904) def use_project(self, id, where):
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 905) # See comment in 'load' for explanation why we record the
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 906) # parameters as opposed to loading the project now.
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 907) m = self.registry.current().project_module();
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 908) self.registry.used_projects[m].append((id, where))
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 909)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 910) def build_project(self, dir):
-1674e2d9 (jhunold 2008-08-08 19:52:05 +0000 911) assert(isinstance(dir, list))
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 912) jamfile_module = self.registry.current().project_module()
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 913) attributes = self.registry.attributes(jamfile_module)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 914) now = attributes.get("projects-to-build")
-1674e2d9 (jhunold 2008-08-08 19:52:05 +0000 915) attributes.set("projects-to-build", now + dir, exact=True)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 916)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 917) def explicit(self, target_names):
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 918) t = self.registry.current()
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 919) for n in target_names:
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 920) t.mark_target_as_explicit(n)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 921)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 922) def glob(self, wildcards, excludes=None):
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 923) return self.registry.glob_internal(self.registry.current(),
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 924) wildcards, excludes, "glob")
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 925)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 926) def glob_tree(self, wildcards, excludes=None):
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 927) bad = 0
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 928) for p in wildcards:
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 929) if os.path.dirname(p):
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 930) bad = 1
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 931)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 932) if excludes:
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 933) for p in excludes:
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 934) if os.path.dirname(p):
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 935) bad = 1
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 936)
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 937) if bad:
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 938) self.registry.manager().errors()(
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 939) "The patterns to 'glob-tree' may not include directory")
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 940) return self.registry.glob_internal(self.registry.current(),
-2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 941) wildcards, excludes, "glob_tree")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 942)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 943)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 944) def using(self, toolset, *args):
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 945) # The module referred by 'using' can be placed in
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 946) # the same directory as Jamfile, and the user
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 947) # will expect the module to be found even though
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 948) # the directory is not in BOOST_BUILD_PATH.
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 949) # So temporary change the search path.
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 950) jamfile_module = self.registry.current().project_module()
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 951) attributes = self.registry.attributes(jamfile_module)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 952) location = attributes.get("location")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 953)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 954) m = self.registry.load_module(toolset[0], [location])
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 955) if not m.__dict__.has_key("init"):
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 956) self.registry.manager.errors()(
-7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 957) "Tool module '%s' does not define the 'init' method" % toolset[0])
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 958) m.init(*args)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 959)
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 960)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 961) def import_(self, name, names_to_import=None, local_names=None):
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 962)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 963) name = name[0]
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 964) jamfile_module = self.registry.current().project_module()
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 965) attributes = self.registry.attributes(jamfile_module)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 966) location = attributes.get("location")
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 967)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 968) m = self.registry.load_module(name, [location])
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 969)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 970) for f in m.__dict__:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 971) v = m.__dict__[f]
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 972) if callable(v):
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 973) bjam.import_rule(jamfile_module, name + "." + f, v)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 974)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 975) if names_to_import:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 976) if not local_names:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 977) local_names = names_to_import
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 978)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 979) if len(names_to_import) != len(local_names):
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 980) self.registry.manager.errors()(
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 981) """The number of names to import and local names do not match.""")
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 982)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 983) for n, l in zip(names_to_import, local_names):
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 984) bjam.import_rule(jamfile_module, l, m.__dict__[n])
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 985)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 986) def conditional(self, condition, requirements):
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 987) """Calculates conditional requirements for multiple requirements
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 988) at once. This is a shorthand to be reduce duplication and to
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 989) keep an inline declarative syntax. For example:
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 990)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 991) lib x : x.cpp : [ conditional <toolset>gcc <variant>debug :
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 992) <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ;
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 993) """
-f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 994)
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 995) c = string.join(condition, ",")
-f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 996) return [c + ":" + r for r in requirements]
diff --git a/tools/build/src/build/project.py b/tools/build/src/build/project.py
index ea8fe0106e..9ec2ccb79e 100644
--- a/tools/build/src/build/project.py
+++ b/tools/build/src/build/project.py
@@ -184,7 +184,7 @@ class ProjectRegistry:
if not found:
print "error: Could not find parent for project at '%s'" % location
- print "error: Did not find Jamfile or project-root.jam in any parent directory."
+ print "error: Did not find Jamfile.jam or Jamroot.jam in any parent directory."
sys.exit(1)
return self.load(os.path.dirname(found[0]))
@@ -298,16 +298,17 @@ Please consult the documentation at 'http://boost.org/boost-build2'."""
# See if the Jamfile is where it should be.
is_jamroot = False
jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT)
- if not jamfile_to_load:
- jamfile_to_load = self.find_jamfile(dir)
- else:
+ if jamfile_to_load:
if len(jamfile_to_load) > 1:
- get_manager().errors()("Multiple Jamfiles found at '%s'\n" +\
- "Filenames are: %s"
- % (dir, [os.path.basename(j) for j in jamfile_to_load]))
-
+ get_manager().errors()(
+ "Multiple Jamfiles found at '{}'\n"
+ "Filenames are: {}"
+ .format(dir, ' '.join(os.path.basename(j) for j in jamfile_to_load))
+ )
is_jamroot = True
jamfile_to_load = jamfile_to_load[0]
+ else:
+ jamfile_to_load = self.find_jamfile(dir)
dir = os.path.dirname(jamfile_to_load)
if not dir:
@@ -321,47 +322,67 @@ Please consult the documentation at 'http://boost.org/boost-build2'."""
# same project we're loading now. Checking inside .jamfile-modules
# prevents that second attempt from messing up.
if not jamfile_module in self.jamfile_modules:
- self.jamfile_modules[jamfile_module] = True
-
+ previous_project = self.current_project
# Initialize the jamfile module before loading.
- #
self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load))
- saved_project = self.current_project
-
- bjam.call("load", jamfile_module, jamfile_to_load)
- basename = os.path.basename(jamfile_to_load)
-
- if is_jamroot:
- jamfile = self.find_jamfile(dir, no_errors=True)
- if jamfile:
- bjam.call("load", jamfile_module, jamfile)
+ if not jamfile_module in self.jamfile_modules:
+ saved_project = self.current_project
+ self.jamfile_modules[jamfile_module] = True
+
+ bjam.call("load", jamfile_module, jamfile_to_load)
+
+ if is_jamroot:
+ jamfile = self.find_jamfile(dir, no_errors=True)
+ if jamfile:
+ bjam.call("load", jamfile_module, jamfile)
+
+ # Now do some checks
+ if self.current_project != saved_project:
+ from textwrap import dedent
+ self.manager.errors()(dedent(
+ """
+ The value of the .current-project variable has magically changed
+ after loading a Jamfile. This means some of the targets might be
+ defined a the wrong project.
+ after loading %s
+ expected value %s
+ actual value %s
+ """
+ % (jamfile_module, saved_project, self.current_project)
+ ))
+
+ self.end_load(previous_project)
+
+ if self.global_build_dir:
+ id = self.attributeDefault(jamfile_module, "id", None)
+ project_root = self.attribute(jamfile_module, "project-root")
+ location = self.attribute(jamfile_module, "location")
+
+ if location and project_root == dir:
+ # This is Jamroot
+ if not id:
+ # FIXME: go via errors module, so that contexts are
+ # shown?
+ print "warning: the --build-dir option was specified"
+ print "warning: but Jamroot at '%s'" % dir
+ print "warning: specified no project id"
+ print "warning: the --build-dir option will be ignored"
+
+ def end_load(self, previous_project=None):
+ if not self.current_project:
+ self.manager.errors()(
+ 'Ending project loading requested when there was no project currently '
+ 'being loaded.'
+ )
- # Now do some checks
- if self.current_project != saved_project:
+ if not previous_project and self.saved_current_project:
self.manager.errors()(
-"""The value of the .current-project variable
-has magically changed after loading a Jamfile.
-This means some of the targets might be defined a the wrong project.
-after loading %s
-expected value %s
-actual value %s""" % (jamfile_module, saved_project, self.current_project))
-
- if self.global_build_dir:
- id = self.attributeDefault(jamfile_module, "id", None)
- project_root = self.attribute(jamfile_module, "project-root")
- location = self.attribute(jamfile_module, "location")
-
- if location and project_root == dir:
- # This is Jamroot
- if not id:
- # FIXME: go via errors module, so that contexts are
- # shown?
- print "warning: the --build-dir option was specified"
- print "warning: but Jamroot at '%s'" % dir
- print "warning: specified no project id"
- print "warning: the --build-dir option will be ignored"
+ 'Ending project loading requested with no "previous project" when there '
+ 'other projects still being loaded recursively.'
+ )
+ self.current_project = previous_project
def load_standalone(self, jamfile_module, file):
"""Loads 'file' as standalone project that has no location
@@ -388,51 +409,20 @@ actual value %s""" % (jamfile_module, saved_project, self.current_project))
else:
return 0
- def initialize(self, module_name, location=None, basename=None):
+ def initialize(self, module_name, location=None, basename=None, standalone_path=''):
"""Initialize the module for a project.
module-name is the name of the project module.
location is the location (directory) of the project to initialize.
If not specified, standalone project will be initialized
+ standalone_path is the path to the source-location.
+ this should only be called from the python side.
"""
assert isinstance(module_name, basestring)
assert isinstance(location, basestring) or location is None
assert isinstance(basename, basestring) or basename is None
- if "--debug-loading" in self.manager.argv():
- print "Initializing project '%s'" % module_name
-
- # TODO: need to consider if standalone projects can do anything but defining
- # prebuilt targets. If so, we need to give more sensible "location", so that
- # source paths are correct.
- if not location:
- location = ""
-
- attributes = ProjectAttributes(self.manager, location, module_name)
- self.module2attributes[module_name] = attributes
-
- python_standalone = False
- if location:
- attributes.set("source-location", [location], exact=1)
- elif not module_name in ["test-config", "site-config", "user-config", "project-config"]:
- # This is a standalone project with known location. Set source location
- # so that it can declare targets. This is intended so that you can put
- # a .jam file in your sources and use it via 'using'. Standard modules
- # (in 'tools' subdir) may not assume source dir is set.
- attributes.set("source-location", self.loaded_tool_module_path_[module_name], exact=1)
- python_standalone = True
-
- attributes.set("requirements", property_set.empty(), exact=True)
- attributes.set("usage-requirements", property_set.empty(), exact=True)
- attributes.set("default-build", property_set.empty(), exact=True)
- attributes.set("projects-to-build", [], exact=True)
- attributes.set("project-root", None, exact=True)
- attributes.set("build-dir", None, exact=True)
-
- self.project_rules_.init_project(module_name, python_standalone)
-
jamroot = False
-
- parent_module = None;
+ parent_module = None
if module_name == "test-config":
# No parent
pass
@@ -447,37 +437,74 @@ actual value %s""" % (jamfile_module, saved_project, self.current_project))
# --- i.e
# if the project is not standalone.
parent_module = self.load_parent(location)
- else:
+ elif location:
# It's either jamroot, or standalone project.
# If it's jamroot, inherit from user-config.
- if location:
- # If project-config module exist, inherit from it.
- if self.module2attributes.has_key("project-config"):
- parent_module = "project-config"
- else:
- parent_module = "user-config" ;
-
- jamroot = True ;
+ # If project-config module exist, inherit from it.
+ parent_module = 'user-config'
+ if 'project-config' in self.module2attributes:
+ parent_module = 'project-config'
+ jamroot = True
- if parent_module:
- self.inherit_attributes(module_name, parent_module)
- attributes.set("parent-module", parent_module, exact=1)
-
- if jamroot:
- attributes.set("project-root", location, exact=1)
+ # TODO: need to consider if standalone projects can do anything but defining
+ # prebuilt targets. If so, we need to give more sensible "location", so that
+ # source paths are correct.
+ if not location:
+ location = ""
- parent = None
- if parent_module:
- parent = self.target(parent_module)
+ # the call to load_parent() above can end up loading this module again
+ # make sure we don't reinitialize the module's attributes
+ if module_name not in self.module2attributes:
+ if "--debug-loading" in self.manager.argv():
+ print "Initializing project '%s'" % module_name
+ attributes = ProjectAttributes(self.manager, location, module_name)
+ self.module2attributes[module_name] = attributes
- if not self.module2target.has_key(module_name):
- target = b2.build.targets.ProjectTarget(self.manager,
- module_name, module_name, parent,
- self.attribute(module_name, "requirements"),
- # FIXME: why we need to pass this? It's not
- # passed in jam code.
- self.attribute(module_name, "default-build"))
- self.module2target[module_name] = target
+ python_standalone = False
+ if location:
+ attributes.set("source-location", [location], exact=1)
+ elif not module_name in ["test-config", "site-config", "user-config", "project-config"]:
+ # This is a standalone project with known location. Set source location
+ # so that it can declare targets. This is intended so that you can put
+ # a .jam file in your sources and use it via 'using'. Standard modules
+ # (in 'tools' subdir) may not assume source dir is set.
+ source_location = standalone_path
+ if not source_location:
+ source_location = self.loaded_tool_module_path_.get(module_name)
+ if not source_location:
+ self.manager.errors()('Standalone module path not found for "{}"'
+ .format(module_name))
+ attributes.set("source-location", [source_location], exact=1)
+ python_standalone = True
+
+ attributes.set("requirements", property_set.empty(), exact=True)
+ attributes.set("usage-requirements", property_set.empty(), exact=True)
+ attributes.set("default-build", property_set.empty(), exact=True)
+ attributes.set("projects-to-build", [], exact=True)
+ attributes.set("project-root", None, exact=True)
+ attributes.set("build-dir", None, exact=True)
+
+ self.project_rules_.init_project(module_name, python_standalone)
+
+ if parent_module:
+ self.inherit_attributes(module_name, parent_module)
+ attributes.set("parent-module", parent_module, exact=1)
+
+ if jamroot:
+ attributes.set("project-root", location, exact=1)
+
+ parent = None
+ if parent_module:
+ parent = self.target(parent_module)
+
+ if module_name not in self.module2target:
+ target = b2.build.targets.ProjectTarget(self.manager,
+ module_name, module_name, parent,
+ self.attribute(module_name, "requirements"),
+ # FIXME: why we need to pass this? It's not
+ # passed in jam code.
+ self.attribute(module_name, "default-build"))
+ self.module2target[module_name] = target
self.current_project = self.target(module_name)
@@ -529,6 +556,11 @@ actual value %s""" % (jamfile_module, saved_project, self.current_project))
def current(self):
"""Returns the project which is currently being loaded."""
+ if not self.current_project:
+ get_manager().errors()(
+ 'Reference to the project currently being loaded requested '
+ 'when there was no project module being loaded.'
+ )
return self.current_project
def set_current(self, c):
@@ -547,8 +579,10 @@ actual value %s""" % (jamfile_module, saved_project, self.current_project))
self.current_project = project
def pop_current(self):
- self.current_project = self.saved_current_project[-1]
- del self.saved_current_project[-1]
+ if self.saved_current_project:
+ self.current_project = self.saved_current_project.pop()
+ else:
+ self.current_project = None
def attributes(self, project):
"""Returns the project-attribute instance for the
@@ -564,7 +598,7 @@ actual value %s""" % (jamfile_module, saved_project, self.current_project))
try:
return self.module2attributes[project].get(attribute)
except:
- raise BaseException("No attribute '%s' for project" % (attribute, project))
+ raise BaseException("No attribute '%s' for project %s" % (attribute, project))
def attributeDefault(self, project, attribute, default):
"""Returns the value of the specified attribute in the
@@ -577,7 +611,7 @@ actual value %s""" % (jamfile_module, saved_project, self.current_project))
def target(self, project_module):
"""Returns the project target corresponding to the 'project-module'."""
assert isinstance(project_module, basestring)
- if not self.module2target.has_key(project_module):
+ if project_module not in self.module2target:
self.module2target[project_module] = \
b2.build.targets.ProjectTarget(project_module, project_module,
self.attribute(project_module, "requirements"))
@@ -595,12 +629,12 @@ actual value %s""" % (jamfile_module, saved_project, self.current_project))
if not declared_id or declared_id != id:
# The project at 'location' either have no id or
# that id is not equal to the 'id' parameter.
- if self.id2module.has_key(id) and self.id2module[id] != project_module:
+ if id in self.id2module and self.id2module[id] != project_module:
self.manager.errors()(
"""Attempt to redeclare already existing project id '%s' at location '%s'""" % (id, location))
self.id2module[id] = project_module
- self.current_module = saved_project
+ self.current_project = saved_project
def add_rule(self, name, callable_):
"""Makes rule 'name' available to all subsequently loaded Jamfiles.
@@ -725,15 +759,21 @@ actual value %s""" % (jamfile_module, saved_project, self.current_project))
# find_module is used so that the pyc's can be used.
# an ImportError is raised if not found
f, location, description = imp.find_module(name, paths)
+ except ImportError:
+ # if the module is not found in the b2 package,
+ # this error will be handled later
+ pass
+ else:
+ # we've found the module, now let's try loading it.
+ # it's possible that the module itself contains an ImportError
+ # which is why we're loading it in this else clause so that the
+ # proper error message is shown to the end user.
+ # TODO: does this module name really need to be mangled like this?
mname = name + "__for_jamfile"
self.loaded_tool_module_path_[mname] = location
module = imp.load_module(mname, f, location, description)
self.loaded_tool_modules_[name] = module
return module
- except ImportError:
- # if the module is not found in the b2 package,
- # this error will be handled later
- pass
# the cache is created here due to possibly importing packages
# that end up calling get_manager() which might fail
@@ -750,12 +790,17 @@ actual value %s""" % (jamfile_module, saved_project, self.current_project))
# the module exists within the BOOST_BUILD_PATH,
# load it.
elif mname:
- # __import__ can be used here since the module
- # is guaranteed to be found under the `b2` namespace.
+ # in some cases, self.loaded_tool_module_path_ needs to
+ # have the path to the file during the import
+ # (project.initialize() for example),
+ # so the path needs to be set *before* importing the module.
+ path = os.path.join(b2.__path__[0], *mname.split('.')[1:])
+ self.loaded_tool_module_path_[mname] = path
+ # mname is guaranteed to be importable since it was
+ # found within the cache
__import__(mname)
module = sys.modules[mname]
self.loaded_tool_modules_[name] = module
- self.loaded_tool_module_path_[mname] = module.__file__
return module
self.manager.errors()("Cannot find module '%s'" % name)
@@ -1104,8 +1149,8 @@ attribute is allowed only for top-level 'project' invocations""")
assert is_iterable_typed(name, basestring)
assert is_iterable_typed(value, basestring)
if len(value) > 1:
- self.registry.manager.error()("path constant should have one element")
- self.registry.current().add_constant(name[0], value[0], path=1)
+ self.registry.manager.errors()("path constant should have one element")
+ self.registry.current().add_constant(name[0], value, path=1)
def use_project(self, id, where):
# See comment in 'load' for explanation why we record the
@@ -1128,7 +1173,7 @@ attribute is allowed only for top-level 'project' invocations""")
def always(self, target_names):
assert is_iterable_typed(target_names, basestring)
- self.registry.current().mark_targets_as_alays(target_names)
+ self.registry.current().mark_targets_as_always(target_names)
def glob(self, wildcards, excludes=None):
assert is_iterable_typed(wildcards, basestring)
@@ -1167,7 +1212,7 @@ attribute is allowed only for top-level 'project' invocations""")
location = current.get('location')
m = self.registry.load_module(toolset[0], [location])
- if not m.__dict__.has_key("init"):
+ if "init" not in m.__dict__:
self.registry.manager.errors()(
"Tool module '%s' does not define the 'init' method" % toolset[0])
m.init(*args)
diff --git a/tools/build/src/build/property.py b/tools/build/src/build/property.py
index 11a18ff385..dff82865c2 100644
--- a/tools/build/src/build/property.py
+++ b/tools/build/src/build/property.py
@@ -9,12 +9,15 @@
import re
import sys
+from functools import total_ordering
+
from b2.util.utility import *
from b2.build import feature
from b2.util import sequence, qualify_jam_action, is_iterable_typed
import b2.util.set
from b2.manager import get_manager
+
__re_two_ampersands = re.compile ('&&')
__re_comma = re.compile (',')
__re_split_condition = re.compile ('(.*):(<.*)')
@@ -23,50 +26,138 @@ __re_colon = re.compile (':')
__re_has_condition = re.compile (r':<')
__re_separate_condition_and_property = re.compile (r'(.*):(<.*)')
-__not_applicable_feature='not-applicable-in-this-context'
-feature.feature(__not_applicable_feature, [], ['free'])
+_not_applicable_feature='not-applicable-in-this-context'
+feature.feature(_not_applicable_feature, [], ['free'])
__abbreviated_paths = False
-class Property(object):
- __slots__ = ('_feature', '_value', '_condition')
+class PropertyMeta(type):
+ """
+ This class exists to implement the isinstance() and issubclass()
+ hooks for the Property class. Since we've introduce the concept of
+ a LazyProperty, isinstance(p, Property) will fail when p is a LazyProperty.
+ Implementing both __instancecheck__ and __subclasscheck__ will allow
+ LazyProperty instances to pass the isinstance() and issubclass check for
+ the Property class.
+
+ Additionally, the __call__ method intercepts the call to the Property
+ constructor to ensure that calling Property with the same arguments
+ will always return the same Property instance.
+ """
+ _registry = {}
+ current_id = 1
+
+ def __call__(mcs, f, value, condition=None):
+ """
+ This intercepts the call to the Property() constructor.
- def __init__(self, f, value, condition = []):
- if type(f) == type(""):
+ This exists so that the same arguments will always return the same Property
+ instance. This allows us to give each instance a unique ID.
+ """
+ from b2.build.feature import Feature
+ if not isinstance(f, Feature):
f = feature.get(f)
- # At present, single property has a single value.
- assert type(value) != type([])
- assert(f.free() or value.find(':') == -1)
- self._feature = f
- self._value = value
- self._condition = condition
+ if condition is None:
+ condition = []
+ key = (f, value) + tuple(sorted(condition))
+ if key not in mcs._registry:
+ instance = super(PropertyMeta, mcs).__call__(f, value, condition)
+ mcs._registry[key] = instance
+ return mcs._registry[key]
+
+ @staticmethod
+ def check(obj):
+ return (hasattr(obj, 'feature') and
+ hasattr(obj, 'value') and
+ hasattr(obj, 'condition'))
- def feature(self):
- return self._feature
+ def __instancecheck__(self, instance):
+ return self.check(instance)
- def value(self):
- return self._value
+ def __subclasscheck__(self, subclass):
+ return self.check(subclass)
+
+
+@total_ordering
+class Property(object):
- def condition(self):
- return self._condition
+ __slots__ = ('feature', 'value', 'condition', '_to_raw', '_hash', 'id')
+ __metaclass__ = PropertyMeta
+
+ def __init__(self, f, value, condition=None):
+ assert(f.free or ':' not in value)
+ if condition is None:
+ condition = []
+
+ self.feature = f
+ self.value = value
+ self.condition = condition
+ self._hash = hash((self.feature, self.value) + tuple(sorted(self.condition)))
+ self.id = PropertyMeta.current_id
+ # increment the id counter.
+ # this allows us to take a list of Property
+ # instances and use their unique integer ID
+ # to create a key for PropertySet caching. This is
+ # much faster than string comparison.
+ PropertyMeta.current_id += 1
+
+ condition_str = ''
+ if condition:
+ condition_str = ",".join(str(p) for p in self.condition) + ':'
+
+ self._to_raw = '{}<{}>{}'.format(condition_str, f.name, value)
def to_raw(self):
- result = "<" + self._feature.name() + ">" + str(self._value)
- if self._condition:
- result = ",".join(str(p) for p in self._condition) + ':' + result
- return result
+ return self._to_raw
def __str__(self):
- return self.to_raw()
+
+ return self._to_raw
+
+ def __hash__(self):
+ return self._hash
+
+ def __eq__(self, other):
+ return self._hash == other._hash
+
+ def __lt__(self, other):
+ return (self.feature.name, self.value) < (other.feature.name, other.value)
+
+
+@total_ordering
+class LazyProperty(object):
+ def __init__(self, feature_name, value, condition=None):
+ if condition is None:
+ condition = []
+
+ self.__property = Property(
+ feature.get(_not_applicable_feature), feature_name + value, condition=condition)
+ self.__name = feature_name
+ self.__value = value
+ self.__condition = condition
+ self.__feature = None
+
+ def __getattr__(self, item):
+ if self.__feature is None:
+ try:
+ self.__feature = feature.get(self.__name)
+ self.__property = Property(self.__feature, self.__value, self.__condition)
+ except KeyError:
+ pass
+ return getattr(self.__property, item)
def __hash__(self):
- # FIXME: consider if this class should be value-is-identity one
- return hash((self._feature, self._value, tuple(self._condition)))
+ return hash(self.__property)
+
+ def __str__(self):
+ return self.__property._to_raw
+
+ def __eq__(self, other):
+ return self.__property == other
- def __cmp__(self, other):
- return cmp((self._feature.name(), self._value, self._condition),
- (other._feature.name(), other._value, other._condition))
+ def __lt__(self, other):
+ return (self.feature.name, self.value) < (other.feature.name, other.value)
def create_from_string(s, allow_condition=False,allow_missing_value=False):
@@ -89,17 +180,24 @@ def create_from_string(s, allow_condition=False,allow_missing_value=False):
# FIXME: break dependency cycle
from b2.manager import get_manager
+ if condition:
+ condition = [create_from_string(x) for x in condition.split(',')]
+
feature_name = get_grist(s)
if not feature_name:
if feature.is_implicit_value(s):
f = feature.implied_feature(s)
value = s
+ p = Property(f, value, condition=condition)
else:
raise get_manager().errors()("Invalid property '%s' -- unknown feature" % s)
else:
+ value = get_value(s)
+ if not value and not allow_missing_value:
+ get_manager().errors()("Invalid property '%s' -- no value specified" % s)
+
if feature.valid(feature_name):
- f = feature.get(feature_name)
- value = get_value(s)
+ p = Property(feature.get(feature_name), value, condition=condition)
else:
# In case feature name is not known, it is wrong to do a hard error.
# Feature sets change depending on the toolset. So e.g.
@@ -112,17 +210,9 @@ def create_from_string(s, allow_condition=False,allow_missing_value=False):
# The underlying cause for this problem is that python port Property
# is more strict than its Jam counterpart and must always reference
# a valid feature.
- f = feature.get(__not_applicable_feature)
- value = s
+ p = LazyProperty(feature_name, value, condition=condition)
- if not value and not allow_missing_value:
- get_manager().errors()("Invalid property '%s' -- no value specified" % s)
-
-
- if condition:
- condition = [create_from_string(x) for x in condition.split(',')]
-
- return Property(f, value, condition)
+ return p
def create_from_strings(string_list, allow_condition=False):
assert is_iterable_typed(string_list, basestring)
@@ -141,6 +231,9 @@ reset ()
def set_abbreviated_paths(on=True):
global __abbreviated_paths
+ if on == 'off':
+ on = False
+ on = bool(on)
__abbreviated_paths = on
@@ -199,19 +292,19 @@ def refine (properties, requirements):
# Record them so that we can handle 'properties'.
for r in requirements:
# Don't consider conditional requirements.
- if not r.condition():
- required[r.feature()] = r
+ if not r.condition:
+ required[r.feature] = r
for p in properties:
# Skip conditional properties
- if p.condition():
+ if p.condition:
result.add(p)
# No processing for free properties
- elif p.feature().free():
+ elif p.feature.free:
result.add(p)
else:
- if required.has_key(p.feature()):
- result.add(required[p.feature()])
+ if p.feature in required:
+ result.add(required[p.feature])
else:
result.add(p)
@@ -222,17 +315,18 @@ def translate_paths (properties, path):
The property values are assumed to be in system-specific form, and
will be translated into normalized form.
"""
+ assert is_iterable_typed(properties, Property)
result = []
for p in properties:
- if p.feature().path():
- values = __re_two_ampersands.split(p.value())
+ if p.feature.path:
+ values = __re_two_ampersands.split(p.value)
- new_value = "&&".join(os.path.join(path, v) for v in values)
+ new_value = "&&".join(os.path.normpath(os.path.join(path, v)) for v in values)
- if new_value != p.value():
- result.append(Property(p.feature(), new_value, p.condition()))
+ if new_value != p.value:
+ result.append(Property(p.feature, new_value, p.condition))
else:
result.append(p)
@@ -250,10 +344,10 @@ def translate_indirect(properties, context_module):
assert isinstance(context_module, basestring)
result = []
for p in properties:
- if p.value()[0] == '@':
- q = qualify_jam_action(p.value()[1:], context_module)
+ if p.value[0] == '@':
+ q = qualify_jam_action(p.value[1:], context_module)
get_manager().engine().register_bjam_action(q)
- result.append(Property(p.feature(), '@' + q, p.condition()))
+ result.append(Property(p.feature, '@' + q, p.condition))
else:
result.append(p)
@@ -274,22 +368,25 @@ def expand_subfeatures_in_conditions (properties):
result = []
for p in properties:
- if not p.condition():
+ if not p.condition:
result.append(p)
else:
expanded = []
- for c in p.condition():
-
- if c.feature().name().startswith("toolset") or c.feature().name() == "os":
- # It common that condition includes a toolset which
- # was never defined, or mentiones subfeatures which
- # were never defined. In that case, validation will
- # only produce an spirious error, so don't validate.
- expanded.extend(feature.expand_subfeatures ([c], True))
- else:
- expanded.extend(feature.expand_subfeatures([c]))
-
- result.append(Property(p.feature(), p.value(), expanded))
+ for c in p.condition:
+ # It common that condition includes a toolset which
+ # was never defined, or mentiones subfeatures which
+ # were never defined. In that case, validation will
+ # only produce an spirious error, so don't validate.
+ expanded.extend(feature.expand_subfeatures ([c], True))
+
+ # we need to keep LazyProperties lazy
+ if isinstance(p, LazyProperty):
+ value = p.value
+ feature_name = get_grist(value)
+ value = value.replace(feature_name, '')
+ result.append(LazyProperty(feature_name, value, condition=expanded))
+ else:
+ result.append(Property(p.feature, p.value, expanded))
return result
@@ -341,7 +438,7 @@ def evaluate_conditionals_in_context (properties, context):
conditional = []
for p in properties:
- if p.condition():
+ if p.condition:
conditional.append (p)
else:
base.append (p)
@@ -351,8 +448,8 @@ def evaluate_conditionals_in_context (properties, context):
# Evaluate condition
# FIXME: probably inefficient
- if all(x in context for x in p.condition()):
- result.append(Property(p.feature(), p.value()))
+ if all(x in context for x in p.condition):
+ result.append(Property(p.feature, p.value))
return result
@@ -389,8 +486,8 @@ def __validate1 (property):
assert isinstance(property, Property)
msg = None
- if not property.feature().free():
- feature.validate_value_string (property.feature(), property.value())
+ if not property.feature.free:
+ feature.validate_value_string (property.feature, property.value)
###################################################################
@@ -460,10 +557,10 @@ def translate_dependencies(properties, project_id, location):
result = []
for p in properties:
- if not p.feature().dependency():
+ if not p.feature.dependency:
result.append(p)
else:
- v = p.value()
+ v = p.value
m = re.match("(.*)//(.*)", v)
if m:
rooted = m.group(1)
@@ -473,12 +570,12 @@ def translate_dependencies(properties, project_id, location):
else:
rooted = os.path.join(os.getcwd(), location, rooted)
- result.append(Property(p.feature(), rooted + "//" + m.group(2), p.condition()))
+ result.append(Property(p.feature, rooted + "//" + m.group(2), p.condition))
elif os.path.isabs(v):
result.append(p)
else:
- result.append(Property(p.feature(), project_id + "//" + v, p.condition()))
+ result.append(Property(p.feature, project_id + "//" + v, p.condition))
return result
diff --git a/tools/build/src/build/property_set.py b/tools/build/src/build/property_set.py
index 494a5b1b70..3fc86de27b 100644
--- a/tools/build/src/build/property_set.py
+++ b/tools/build/src/build/property_set.py
@@ -44,14 +44,18 @@ def create (raw_properties = []):
x = raw_properties
else:
x = [property.create_from_string(ps) for ps in raw_properties]
- x.sort()
- x = unique(x, stable=True)
- # FIXME: can we do better, e.g. by directly computing
- # hash value of the list?
- key = tuple(x)
-
- if not __cache.has_key (key):
+ # These two lines of code are optimized to the current state
+ # of the Property class. Since this function acts as the caching
+ # frontend to the PropertySet class modifying these two lines
+ # could have a severe performance penalty. Be careful.
+ # It would be faster to sort by p.id, but some projects may rely
+ # on the fact that the properties are ordered alphabetically. So,
+ # we maintain alphabetical sorting so as to maintain backward compatibility.
+ x = sorted(set(x), key=lambda p: (p.feature.name, p.value, p.condition))
+ key = tuple(p.id for p in x)
+
+ if key not in __cache:
__cache [key] = PropertySet(x)
return __cache [key]
@@ -154,16 +158,13 @@ class PropertySet:
- several operations, like and refine and as_path are provided. They all use
caching whenever possible.
"""
- def __init__ (self, properties = []):
+ def __init__ (self, properties=None):
+ if properties is None:
+ properties = []
assert is_iterable_typed(properties, property.Property)
- raw_properties = []
- for p in properties:
- raw_properties.append(p.to_raw())
-
self.all_ = properties
- self.all_raw_ = raw_properties
- self.all_set_ = set(properties)
+ self._all_set = {p.id for p in properties}
self.incidental_ = []
self.free_ = []
@@ -207,39 +208,42 @@ class PropertySet:
# A cache for already evaluated sets.
self.evaluated_ = {}
- for p in raw_properties:
- if not get_grist (p):
- raise BaseException ("Invalid property: '%s'" % p)
-
- att = feature.attributes (get_grist (p))
-
- if 'propagated' in att:
- self.propagated_.append (p)
-
- if 'link_incompatible' in att:
- self.link_incompatible.append (p)
+ # stores the list of LazyProperty instances.
+ # these are being kept separate from the normal
+ # Property instances so that when this PropertySet
+ # tries to return one of its attributes, it
+ # will then try to evaluate the LazyProperty instances
+ # first before returning.
+ self.lazy_properties = []
for p in properties:
-
+ f = p.feature
+ if isinstance(p, property.LazyProperty):
+ self.lazy_properties.append(p)
# A feature can be both incidental and free,
# in which case we add it to incidental.
- if p.feature().incidental():
+ elif f.incidental:
self.incidental_.append(p)
- elif p.feature().free():
+ elif f.free:
self.free_.append(p)
else:
self.base_.append(p)
- if p.condition():
+ if p.condition:
self.conditional_.append(p)
else:
self.non_conditional_.append(p)
- if p.feature().dependency():
+ if f.dependency:
self.dependency_.append (p)
- else:
+ elif not isinstance(p, property.LazyProperty):
self.non_dependency_.append (p)
+ if f.propagated:
+ self.propagated_.append(p)
+ if f.link_incompatible:
+ self.link_incompatible.append(p)
+
def all(self):
return self.all_
@@ -247,33 +251,48 @@ class PropertySet:
def raw (self):
""" Returns the list of stored properties.
"""
- return self.all_raw_
+ # create a new list due to the LazyProperties.
+ # this gives them a chance to evaluate to their
+ # true Property(). This approach is being
+ # taken since calculations should not be using
+ # PropertySet.raw()
+ return [p._to_raw for p in self.all_]
def __str__(self):
- return ' '.join(str(p) for p in self.all_)
+ return ' '.join(p._to_raw for p in self.all_)
def base (self):
""" Returns properties that are neither incidental nor free.
"""
- return self.base_
+ result = [p for p in self.lazy_properties
+ if not(p.feature.incidental or p.feature.free)]
+ result.extend(self.base_)
+ return result
def free (self):
""" Returns free properties which are not dependency properties.
"""
- return self.free_
+ result = [p for p in self.lazy_properties
+ if not p.feature.incidental and p.feature.free]
+ result.extend(self.free_)
+ return result
def non_free(self):
- return self.base_ + self.incidental_
+ return self.base() + self.incidental()
def dependency (self):
""" Returns dependency properties.
"""
+ result = [p for p in self.lazy_properties if p.feature.dependency]
+ result.extend(self.dependency_)
return self.dependency_
def non_dependency (self):
""" Returns properties that are not dependencies.
"""
- return self.non_dependency_
+ result = [p for p in self.lazy_properties if not p.feature.dependency]
+ result.extend(self.non_dependency_)
+ return result
def conditional (self):
""" Returns conditional properties.
@@ -288,13 +307,15 @@ class PropertySet:
def incidental (self):
""" Returns incidental properties.
"""
- return self.incidental_
+ result = [p for p in self.lazy_properties if p.feature.incidental]
+ result.extend(self.incidental_)
+ return result
def refine (self, requirements):
""" Refines this set's properties using the requirements passed as an argument.
"""
assert isinstance(requirements, PropertySet)
- if not self.refined_.has_key (requirements):
+ if requirements not in self.refined_:
r = property.refine(self.all_, requirements.all_)
self.refined_[requirements] = create(r)
@@ -317,7 +338,7 @@ class PropertySet:
if not context:
context = self
- if not self.evaluated_.has_key(context):
+ if context not in self.evaluated_:
# FIXME: figure why the call messes up first parameter
self.evaluated_[context] = create(
property.evaluate_conditionals_in_context(self.all(), context))
@@ -342,13 +363,13 @@ class PropertySet:
def path_order (p1, p2):
- i1 = p1.feature().implicit()
- i2 = p2.feature().implicit()
+ i1 = p1.feature.implicit
+ i2 = p2.feature.implicit
if i1 != i2:
return i2 - i1
else:
- return cmp(p1.feature().name(), p2.feature().name())
+ return cmp(p1.feature.name, p2.feature.name)
# trim redundancy
properties = feature.minimize(self.base_)
@@ -358,15 +379,16 @@ class PropertySet:
components = []
for p in properties:
- if p.feature().implicit():
- components.append(p.value())
+ f = p.feature
+ if f.implicit:
+ components.append(p.value)
else:
- value = p.feature().name() + "-" + p.value()
+ value = f.name.replace(':', '-') + "-" + p.value
if property.get_abbreviated_paths():
value = abbreviate_dashed(value)
components.append(value)
- self.as_path_ = '/'.join (components)
+ self.as_path_ = '/'.join(components)
return self.as_path_
@@ -421,7 +443,7 @@ class PropertySet:
plus the ones of the property set passed as argument.
"""
assert isinstance(ps, PropertySet)
- if not self.added_.has_key(ps):
+ if ps not in self.added_:
self.added_[ps] = create(self.all_ + ps.all())
return self.added_[ps]
@@ -441,13 +463,13 @@ class PropertySet:
feature = b2.build.feature.get(feature)
assert isinstance(feature, b2.build.feature.Feature)
- if not self.feature_map_:
+ if self.feature_map_ is None:
self.feature_map_ = {}
for v in self.all_:
- if not self.feature_map_.has_key(v.feature()):
- self.feature_map_[v.feature()] = []
- self.feature_map_[v.feature()].append(v.value())
+ if v.feature not in self.feature_map_:
+ self.feature_map_[v.feature] = []
+ self.feature_map_[v.feature].append(v.value)
return self.feature_map_.get(feature, [])
@@ -460,12 +482,12 @@ class PropertySet:
result = []
for p in self.all_:
- if p.feature() == feature:
+ if p.feature == feature:
result.append(p)
return result
def __contains__(self, item):
- return item in self.all_set_
+ return item.id in self._all_set
def hash(p):
m = hashlib.md5()
diff --git a/tools/build/src/build/scanner.py b/tools/build/src/build/scanner.py
index ada5d83252..ec3b31b400 100644
--- a/tools/build/src/build/scanner.py
+++ b/tools/build/src/build/scanner.py
@@ -28,11 +28,9 @@
# but different instances, and lead in unneeded duplication of
# actual targets. However, actions can also create scanners in a special
# way, instead of relying on just target type.
-
import property
import bjam
import os
-from b2.exceptions import *
from b2.manager import get_manager
from b2.util import is_iterable_typed
@@ -65,7 +63,7 @@ def register(scanner_class, relevant_properties):
def registered(scanner_class):
""" Returns true iff a scanner of that class is registered
"""
- return __scanners.has_key(str(scanner_class))
+ return str(scanner_class) in __scanners
def get(scanner_class, properties):
""" Returns an instance of previously registered scanner
@@ -83,7 +81,7 @@ def get(scanner_class, properties):
scanner_id = scanner_name + '.' + '-'.join(r)
- if not __scanner_cache.has_key(scanner_id):
+ if scanner_id not in __scanner_cache:
__scanner_cache[scanner_id] = scanner_class(r)
return __scanner_cache[scanner_id]
@@ -99,7 +97,7 @@ class Scanner:
"""
raise BaseException ("method must be overriden")
- def process (self, target, matches):
+ def process (self, target, matches, binding):
""" Establish necessary relationship between targets,
given actual target beeing scanned, and a list of
pattern matches in that file.
@@ -141,7 +139,7 @@ class ScannerRegistry:
assert isinstance(vtarget, basestring)
engine = self.manager_.engine()
engine.set_target_variable(target, "HDRSCAN", scanner.pattern())
- if not self.exported_scanners_.has_key(scanner):
+ if scanner not in self.exported_scanners_:
exported_name = "scanner_" + str(self.count_)
self.count_ = self.count_ + 1
self.exported_scanners_[scanner] = exported_name
diff --git a/tools/build/src/build/targets.py b/tools/build/src/build/targets.py
index 043d906660..6f71177c31 100644
--- a/tools/build/src/build/targets.py
+++ b/tools/build/src/build/targets.py
@@ -82,6 +82,7 @@ from virtual_target import Subvariant
from b2.exceptions import *
from b2.util.sequence import unique
from b2.util import path, bjam_signature, safe_isinstance, is_iterable_typed
+from b2.build import errors
from b2.build.errors import user_error_checkpoint
import b2.build.build_request as build_request
@@ -155,6 +156,8 @@ class TargetRegistry:
'project' is the project where the main taret is to be declared."""
assert is_iterable_typed(specification, basestring)
assert isinstance(project, ProjectTarget)
+ # create a copy since the list is being modified
+ specification = list(specification)
specification.extend(toolset.requirements())
requirements = property_set.refine_from_user_input(
@@ -202,7 +205,7 @@ class TargetRegistry:
""" Helper rules to detect cycles in main target references.
"""
assert isinstance(main_target_instance, MainTarget)
- if self.targets_being_built_.has_key(id(main_target_instance)):
+ if id(main_target_instance) in self.targets_being_built_:
names = []
for t in self.targets_being_built_.values() + [main_target_instance]:
names.append (t.full_name())
@@ -213,7 +216,7 @@ class TargetRegistry:
def end_building (self, main_target_instance):
assert isinstance(main_target_instance, MainTarget)
- assert (self.targets_being_built_.has_key (id (main_target_instance)))
+ assert (id(main_target_instance) in self.targets_being_built_)
del self.targets_being_built_ [id (main_target_instance)]
def create_typed_target (self, type, project, name, sources, requirements, default_build, usage_requirements):
@@ -308,6 +311,7 @@ class AbstractTarget:
self.name_ = name
self.project_ = project
+ self.location_ = errors.nearest_user_location()
def manager (self):
return self.manager_
@@ -499,7 +503,7 @@ class ProjectTarget (AbstractTarget):
if not self.built_main_targets_:
self.build_main_targets()
- return self.main_target_.has_key(name)
+ return name in self.main_target_
def create_main_target (self, name):
""" Returns a 'MainTarget' class instance corresponding to the 'name'.
@@ -527,8 +531,16 @@ class ProjectTarget (AbstractTarget):
target_part = None
if split:
- project_part = split.group (1)
- target_part = split.group (2)
+ project_part = split.group(1)
+ target_part = split.group(2)
+ if not target_part:
+ get_manager().errors()(
+ 'Project ID, "{}", is not a valid target reference. There should '
+ 'be either a target name after the "//" or the "//" should be removed '
+ 'from the target reference.'
+ .format(id)
+ )
+
project_registry = self.project_.manager ().projects ()
@@ -595,7 +607,7 @@ class ProjectTarget (AbstractTarget):
for a in self.alternatives_:
name = a.name ()
- if not self.main_target_.has_key (name):
+ if name not in self.main_target_:
t = MainTarget (name, self.project_)
self.main_target_ [name] = t
@@ -613,7 +625,7 @@ class ProjectTarget (AbstractTarget):
to the location of project.
"""
assert isinstance(name, basestring)
- assert isinstance(value, basestring)
+ assert is_iterable_typed(value, basestring)
assert isinstance(path, int) # will also match bools
if path:
l = self.location_
@@ -625,10 +637,10 @@ class ProjectTarget (AbstractTarget):
# targets in config files, but that's for later.
l = self.get('source-location')
- value = os.path.join(l, value)
+ value = os.path.join(l, value[0])
# Now make the value absolute path. Constants should be in
# platform-native form.
- value = os.path.normpath(os.path.join(os.getcwd(), value))
+ value = [os.path.normpath(os.path.join(os.getcwd(), value))]
self.constants_[name] = value
bjam.call("set-variable", self.project_module(), name, value)
@@ -658,12 +670,13 @@ class MainTarget (AbstractTarget):
def __init__ (self, name, project):
AbstractTarget.__init__ (self, name, project)
self.alternatives_ = []
+ self.best_alternative = None
self.default_build_ = property_set.empty ()
def add_alternative (self, target):
""" Add a new alternative for this target.
"""
- assert isinstance(target, AbstractTarget)
+ assert isinstance(target, BasicTarget)
d = target.default_build ()
if self.alternatives_ and self.default_build_ != d:
@@ -769,6 +782,7 @@ class MainTarget (AbstractTarget):
"""
assert isinstance(prop_set, property_set.PropertySet)
best_alternative = self.__select_alternatives (prop_set, debug=0)
+ self.best_alternative = best_alternative
if not best_alternative:
# FIXME: revive.
@@ -881,9 +895,9 @@ class BasicTarget (AbstractTarget):
"""
def __init__ (self, name, project, sources, requirements = None, default_build = None, usage_requirements = None):
assert is_iterable_typed(sources, basestring)
- assert isinstance(requirements, property_set.PropertySet)
- assert isinstance(default_build, property_set.PropertySet)
- assert isinstance(usage_requirements, property_set.PropertySet)
+ assert isinstance(requirements, property_set.PropertySet) or requirements is None
+ assert isinstance(default_build, property_set.PropertySet) or default_build is None
+ assert isinstance(usage_requirements, property_set.PropertySet) or usage_requirements is None
AbstractTarget.__init__ (self, name, project)
for s in sources:
@@ -955,14 +969,14 @@ class BasicTarget (AbstractTarget):
free_unconditional = []
other = []
for p in requirements.all():
- if p.feature().free() and not p.condition() and p.feature().name() != 'conditional':
+ if p.feature.free and not p.condition and p.feature.name != 'conditional':
free_unconditional.append(p)
else:
other.append(p)
other = property_set.create(other)
key = (build_request, other)
- if not self.request_cache.has_key(key):
+ if key not in self.request_cache:
self.request_cache[key] = self.__common_properties2 (build_request, other)
return self.request_cache[key].add_raw(free_unconditional)
@@ -1143,10 +1157,10 @@ class BasicTarget (AbstractTarget):
usage_requirements = []
for p in properties:
- result = generate_from_reference(p.value(), self.project_, ps)
+ result = generate_from_reference(p.value, self.project_, ps)
for t in result.targets():
- result_properties.append(property.Property(p.feature(), t))
+ result_properties.append(property.Property(p.feature, t))
usage_requirements += result.usage_requirements().all()
@@ -1179,7 +1193,7 @@ class BasicTarget (AbstractTarget):
self.manager().targets().push_target(self)
- if not self.generated_.has_key(ps):
+ if ps not in self.generated_:
# Apply free features form the command line. If user
# said
@@ -1313,9 +1327,18 @@ class BasicTarget (AbstractTarget):
# they are propagated only to direct dependents. We might need
# a more general mechanism, but for now, only those two
# features are special.
- removed_pch = filter(lambda prop: prop.feature().name() not in ['<pch-header>', '<pch-file>'], subvariant.sources_usage_requirements().all())
- result = result.add(property_set.PropertySet(removed_pch))
-
+ properties = []
+ for p in subvariant.sources_usage_requirements().all():
+ if p.feature.name not in ('pch-header', 'pch-file'):
+ properties.append(p)
+ if 'shared' in rproperties.get('link'):
+ new_properties = []
+ for p in properties:
+ if p.feature.name != 'library':
+ new_properties.append(p)
+ properties = new_properties
+
+ result = result.add_raw(properties)
return result
def create_subvariant (self, root_targets, all_targets,
@@ -1398,11 +1421,9 @@ def apply_default_build(property_set_, default_build):
assert isinstance(property_set_, property_set.PropertySet)
assert isinstance(default_build, property_set.PropertySet)
- specified_features = set(p.feature() for p in property_set_.all())
-
defaults_to_apply = []
for d in default_build.all():
- if not d.feature() in specified_features:
+ if not property_set_.get(d.feature):
defaults_to_apply.append(d)
# 2. If there's any defaults to be applied, form the new
@@ -1426,10 +1447,16 @@ def apply_default_build(property_set_, default_build):
# be an indication that
# build_request.expand-no-defaults is the wrong rule
# to use here.
- compressed = feature.compress_subproperties(property_set_.all())
-
- result = build_request.expand_no_defaults(
- b2.build.property_set.create(feature.expand([p])) for p in (compressed + defaults_to_apply))
+ properties = build_request.expand_no_defaults(
+ [property_set.create([p]) for p in
+ feature.compress_subproperties(property_set_.all()) + defaults_to_apply]
+ )
+
+ if properties:
+ for p in properties:
+ result.append(property_set.create(feature.expand(p.all())))
+ else:
+ result = [property_set.empty()]
else:
result.append (property_set_)
diff --git a/tools/build/src/build/toolset.py b/tools/build/src/build/toolset.py
index 672d18f5ad..cf2b24b2e7 100644
--- a/tools/build/src/build/toolset.py
+++ b/tools/build/src/build/toolset.py
@@ -9,6 +9,7 @@
""" Support for toolset definition.
"""
+import sys
import feature, property, generators, property_set
import b2.util.set
@@ -16,13 +17,14 @@ import bjam
from b2.util import cached, qualify_jam_action, is_iterable_typed, is_iterable
from b2.util.utility import *
-from b2.util import bjam_signature
+from b2.util import bjam_signature, sequence
from b2.manager import get_manager
__re_split_last_segment = re.compile (r'^(.+)\.([^\.])*')
__re_two_ampersands = re.compile ('(&&)')
__re_first_segment = re.compile ('([^.]*).*')
__re_first_group = re.compile (r'[^.]*\.(.*)')
+_ignore_toolset_requirements = '--ignore-toolset-requirements' not in sys.argv
# Flag is a mechanism to set a value
# A single toolset flag. Specifies that when certain
@@ -76,8 +78,10 @@ reset ()
# FIXME: --ignore-toolset-requirements
def using(toolset_module, *args):
- loaded_toolset_module= get_manager().projects().load_module(toolset_module, [os.getcwd()]);
- loaded_toolset_module.init(*args)
+ if isinstance(toolset_module, (list, tuple)):
+ toolset_module = toolset_module[0]
+ loaded_toolset_module= get_manager().projects().load_module(toolset_module, [os.getcwd()]);
+ loaded_toolset_module.init(*args)
# FIXME push-checking-for-flags-module ....
# FIXME: investigate existing uses of 'hack-hack' parameter
@@ -182,16 +186,14 @@ def find_satisfied_condition(conditions, ps):
'properties', or an empty list if no such element exists."""
assert is_iterable_typed(conditions, property_set.PropertySet)
assert isinstance(ps, property_set.PropertySet)
- features = set(p.feature() for p in ps.all())
for condition in conditions:
found_all = True
for i in condition.all():
- found = False
- if i.value():
- found = i.value() in ps.get(i.feature())
+ if i.value:
+ found = i.value in ps.get(i.feature)
else:
# Handle value-less properties like '<architecture>' (compare with
# '<architecture>x86').
@@ -204,7 +206,7 @@ def find_satisfied_condition(conditions, ps):
# <a> <b>foo <a>foo <b>foo no match
# <a>foo <b>foo <b>foo no match
# <a>foo <b>foo <a>foo <b>foo match
- found = not i.feature() in features
+ found = not ps.get(i.feature)
found_all = found_all and found
@@ -337,12 +339,12 @@ def __handle_flag_value (manager, value, ps):
for value in values:
- if f.dependency():
+ if f.dependency:
# the value of a dependency feature is a target
# and must be actualized
result.append(value.actualize())
- elif f.path() or f.free():
+ elif f.path or f.free:
# Treat features with && in the value
# specially -- each &&-separated element is considered
@@ -354,11 +356,11 @@ def __handle_flag_value (manager, value, ps):
else:
result.extend(value.split ('&&'))
else:
- result.append (ungristed)
+ result.append (value)
else:
result.append (value)
- return result
+ return sequence.unique(result, stable=True)
def __add_flag (rule_or_module, variable_name, condition, values):
""" Adds a new flag setting with the specified values.
@@ -393,10 +395,9 @@ def add_requirements(requirements):
be conditional or indirect conditional."""
assert is_iterable_typed(requirements, basestring)
- #if ! $(.ignore-requirements)
- #{
- __requirements.extend(requirements)
- #}
+ if _ignore_toolset_requirements:
+ __requirements.extend(requirements)
+
# Make toolset 'toolset', defined in a module of the same name,
# inherit from 'base'
@@ -409,7 +410,7 @@ def add_requirements(requirements):
def inherit(toolset, base):
assert isinstance(toolset, basestring)
assert isinstance(base, basestring)
- get_manager().projects().load_module(base, []);
+ get_manager().projects().load_module(base, ['.']);
inherit_generators(toolset, [], base)
inherit_flags(toolset, base)
diff --git a/tools/build/src/build/type.py b/tools/build/src/build/type.py
index c8d6334c79..3d9b7c1b2c 100644
--- a/tools/build/src/build/type.py
+++ b/tools/build/src/build/type.py
@@ -71,14 +71,19 @@ def register (type, suffixes = [], base_type = None):
if __re_hyphen.search (type):
raise BaseException ('type name "%s" contains a hyphen' % type)
- if __types.has_key (type):
+ # it's possible for a type to be registered with a
+ # base type that hasn't been registered yet. in the
+ # check for base_type below and the following calls to setdefault()
+ # the key `type` will be added to __types. When the base type
+ # actually gets registered, it would fail after the simple check
+ # of "type in __types"; thus the check for "'base' in __types[type]"
+ if type in __types and 'base' in __types[type]:
raise BaseException ('Type "%s" is already registered.' % type)
- entry = {}
- entry ['base'] = base_type
- entry ['derived'] = []
- entry ['scanner'] = None
- __types [type] = entry
+ entry = __types.setdefault(type, {})
+ entry['base'] = base_type
+ entry.setdefault('derived', [])
+ entry.setdefault('scanner', None)
if base_type:
__types.setdefault(base_type, {}).setdefault('derived', []).append(type)
@@ -122,7 +127,7 @@ def register_suffixes (suffixes, type):
assert is_iterable_typed(suffixes, basestring)
assert isinstance(type, basestring)
for s in suffixes:
- if __suffixes_to_types.has_key (s):
+ if s in __suffixes_to_types:
old_type = __suffixes_to_types [s]
if old_type != type:
raise BaseException ('Attempting to specify type for suffix "%s"\nOld type: "%s", New type "%s"' % (s, old_type, type))
@@ -133,7 +138,7 @@ def registered (type):
""" Returns true iff type has been registered.
"""
assert isinstance(type, basestring)
- return __types.has_key (type)
+ return type in __types
def validate (type):
""" Issues an error if 'type' is unknown.
@@ -250,16 +255,23 @@ def generated_target_suffix(type, properties):
assert isinstance(properties, PropertySet)
return generated_target_ps(1, type, properties)
-# Sets a target prefix that should be used when generating targets of 'type'
-# with the specified properties. Can be called with empty properties if no
-# prefix for 'type' has been specified yet.
-#
-# The 'prefix' parameter can be empty string ("") to indicate that no prefix
-# should be used.
-#
-# Usage example: library names use the "lib" prefix on unix.
-@bjam_signature((["type"], ["properties", "*"], ["suffix"]))
+
+@bjam_signature((["type"], ["properties", "*"], ["prefix"]))
def set_generated_target_prefix(type, properties, prefix):
+ """
+ Sets a file prefix to be used when generating a target of 'type' with the
+ specified properties. Can be called with no properties if no prefix has
+ already been specified for the 'type'. The 'prefix' parameter can be an empty
+ string ("") to indicate that no prefix should be used.
+
+ Note that this does not cause files with 'prefix' to be automatically
+ recognized as being of 'type'. Two different types can use the same prefix for
+ their generated files but only one type can be auto-detected for a file with
+ that prefix. User should explicitly specify which one using the
+ register-prefixes rule.
+
+ Usage example: library names use the "lib" prefix on unix.
+ """
set_generated_target_ps(0, type, properties, prefix)
# Change the prefix previously registered for this type/properties combination.
@@ -349,7 +361,7 @@ def type(filename):
if not suffix: return None
suffix = suffix[1:]
- if __suffixes_to_types.has_key(suffix):
+ if suffix in __suffixes_to_types:
return __suffixes_to_types[suffix]
# NOTE: moved from tools/types/register
diff --git a/tools/build/src/build/version.py b/tools/build/src/build/version.py
index 1efe3b5c59..88299060e2 100644
--- a/tools/build/src/build/version.py
+++ b/tools/build/src/build/version.py
@@ -10,12 +10,12 @@ from b2.manager import get_manager
MANAGER = get_manager()
ERROR_HANDLER = MANAGER.errors()
-_major = "2014"
-_minor = "03"
+_major = "2015"
+_minor = "07"
def boost_build():
- return "{}.{}-svn".format(_major, _minor)
+ return "{}.{}-git".format(_major, _minor)
def verify_engine_version():
diff --git a/tools/build/src/build/virtual_target.py b/tools/build/src/build/virtual_target.py
index ea4b24d820..e5a1304763 100644
--- a/tools/build/src/build/virtual_target.py
+++ b/tools/build/src/build/virtual_target.py
@@ -117,7 +117,7 @@ class VirtualTargetRegistry:
signature = "-" + target.name()
result = None
- if not self.cache_.has_key (signature):
+ if signature not in self.cache_:
self.cache_ [signature] = []
for t in self.cache_ [signature]:
@@ -166,7 +166,7 @@ class VirtualTargetRegistry:
path = os.path.join(os.getcwd(), file_location, file)
path = os.path.normpath(path)
- if self.files_.has_key (path):
+ if path in self.files_:
return self.files_ [path]
file_type = b2.build.type.type (file)
@@ -200,7 +200,7 @@ class VirtualTargetRegistry:
def register_actual_name (self, actual_name, virtual_target):
assert isinstance(actual_name, basestring)
assert isinstance(virtual_target, VirtualTarget)
- if self.actual_.has_key (actual_name):
+ if actual_name in self.actual_:
cs1 = self.actual_ [actual_name].creating_subvariant ()
cs2 = virtual_target.creating_subvariant ()
cmt1 = cs1.main_target ()
@@ -218,10 +218,12 @@ class VirtualTargetRegistry:
p2 = p2.raw ()
properties_removed = set.difference (p1, p2)
- if not properties_removed: properties_removed = "none"
+ if not properties_removed:
+ properties_removed = ["none"]
properties_added = set.difference (p2, p1)
- if not properties_added: properties_added = "none"
+ if not properties_added:
+ properties_added = ["none"]
# FIXME: Revive printing of real location.
get_manager().errors()(
@@ -230,13 +232,14 @@ class VirtualTargetRegistry:
"created from '%s'\n"
"another virtual target '%s'\n"
"created from '%s'\n"
- "added properties: '%s'\n"
- "removed properties: '%s'\n"
+ "added properties:\n%s\n"
+ "removed properties:\n%s\n"
% (actual_name,
- self.actual_ [actual_name], "loc", #cmt1.location (),
+ self.actual_ [actual_name], cmt1.project().location(),
virtual_target,
- "loc", #cmt2.location (),
- properties_added, properties_removed))
+ cmt2.project().location(),
+ '\n'.join('\t' + p for p in properties_added),
+ '\n'.join('\t' + p for p in properties_removed)))
else:
self.actual_ [actual_name] = virtual_target
@@ -334,7 +337,7 @@ class VirtualTarget:
name = replace_grist (actual_name, '<' + g + '>')
- if not self.made_.has_key (name):
+ if name not in self.made_:
self.made_ [name] = True
self.project_.manager ().engine ().add_dependency (name, actual_name)
@@ -949,9 +952,9 @@ class NonScanningAction(Action):
#be removed? -- Steven Watanabe
Action.__init__(self, b2.manager.get_manager(), sources, action_name, property_set)
- def actualize_source_type(self, sources, property_set):
+ def actualize_source_type(self, sources, ps=None):
assert is_iterable_typed(sources, VirtualTarget)
- assert isinstance(property_set, property_set.PropertySet)
+ assert isinstance(ps, property_set.PropertySet) or ps is None
result = []
for s in sources:
result.append(s.actualize())
@@ -1099,8 +1102,8 @@ class Subvariant:
or as dependency properties. Targets referred with
dependency property are returned a properties, not targets."""
if __debug__:
- from .targets import GenerateResult
- assert isinstance(result, GenerateResult)
+ from .property import Property
+ assert is_iterable_typed(result, (VirtualTarget, Property))
# Find directly referenced targets.
deps = self.build_properties().dependency()
all_targets = self.sources_ + deps
@@ -1111,7 +1114,7 @@ class Subvariant:
if not e in result:
result.add(e)
if isinstance(e, property.Property):
- t = e.value()
+ t = e.value
else:
t = e
diff --git a/tools/build/src/build_system.py b/tools/build/src/build_system.py
index b5a3b27752..6e78ced50b 100644
--- a/tools/build/src/build_system.py
+++ b/tools/build/src/build_system.py
@@ -8,6 +8,15 @@
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
+import os
+import sys
+import re
+
+import bjam
+
+# set this early on since some of the following modules
+# require looking at the sys.argv
+sys.argv = bjam.variable("ARGV")
from b2.build.engine import Engine
@@ -16,13 +25,11 @@ from b2.util.path import glob
from b2.build import feature, property_set
import b2.build.virtual_target
from b2.build.targets import ProjectTarget
-from b2.util.sequence import unique
import b2.build.build_request
from b2.build.errors import ExceptionWithUserContext
import b2.tools.common
from b2.build.toolset import using
-import b2.build.project as project
import b2.build.virtual_target as virtual_target
import b2.build.build_request as build_request
@@ -32,13 +39,6 @@ from b2.manager import get_manager
from b2.util import cached
from b2.util import option
-
-import bjam
-
-import os
-import sys
-import re
-
################################################################################
#
# Module global data.
@@ -327,6 +327,8 @@ def load_configuration_files():
initialize_config_module('project-config', os.path.dirname(file[0]))
load_config('project-config', "project-config.jam", [os.path.dirname(file[0])], True)
+ get_manager().projects().end_load()
+
# Autoconfigure toolsets based on any instances of --toolset=xx,yy,...zz or
# toolset=xx,yy,...zz in the command line. May return additional properties to
@@ -421,8 +423,6 @@ def should_clean_project(project):
def main():
- sys.argv = bjam.variable("ARGV")
-
# FIXME: document this option.
if "--profiling" in sys.argv:
import cProfile
@@ -624,191 +624,6 @@ def main_real():
for t in virtual_targets:
actual_targets.append(t.actualize())
-
- # FIXME: restore
-## # If XML data output has been requested prepare additional rules and targets
-## # so we can hook into Jam to collect build data while its building and have
-## # it trigger the final XML report generation after all the planned targets
-## # have been built.
-## if $(.out-xml)
-## {
-## # Get a qualified virtual target name.
-## rule full-target-name ( target )
-## {
-## local name = [ $(target).name ] ;
-## local project = [ $(target).project ] ;
-## local project-path = [ $(project).get location ] ;
-## return $(project-path)//$(name) ;
-## }
-
-## # Generate an XML file containing build statistics for each constituent.
-## #
-## rule out-xml ( xml-file : constituents * )
-## {
-## # Prepare valid XML header and footer with some basic info.
-## local nl = "
-## " ;
-## local jam = [ version.jam ] ;
-## local os = [ modules.peek : OS OSPLAT JAMUNAME ] "" ;
-## local timestamp = [ modules.peek : JAMDATE ] ;
-## local cwd = [ PWD ] ;
-## local command = $(.sys.argv) ;
-## local bb-version = [ version.boost-build ] ;
-## .header on $(xml-file) =
-## "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
-## "$(nl)<build format=\"1.0\" version=\"$(bb-version)\">"
-## "$(nl) <jam version=\"$(jam:J=.)\" />"
-## "$(nl) <os name=\"$(os[1])\" platform=\"$(os[2])\"><![CDATA[$(os[3-]:J= )]]></os>"
-## "$(nl) <timestamp><![CDATA[$(timestamp)]]></timestamp>"
-## "$(nl) <directory><![CDATA[$(cwd)]]></directory>"
-## "$(nl) <command><![CDATA[\"$(command:J=\" \")\"]]></command>"
-## ;
-## .footer on $(xml-file) =
-## "$(nl)</build>" ;
-
-## # Generate the target dependency graph.
-## .contents on $(xml-file) +=
-## "$(nl) <targets>" ;
-## for local t in [ virtual-target.all-targets ]
-## {
-## local action = [ $(t).action ] ;
-## if $(action)
-## # If a target has no action, it has no dependencies.
-## {
-## local name = [ full-target-name $(t) ] ;
-## local sources = [ $(action).sources ] ;
-## local dependencies ;
-## for local s in $(sources)
-## {
-## dependencies += [ full-target-name $(s) ] ;
-## }
-
-## local path = [ $(t).path ] ;
-## local jam-target = [ $(t).actual-name ] ;
-
-## .contents on $(xml-file) +=
-## "$(nl) <target>"
-## "$(nl) <name><![CDATA[$(name)]]></name>"
-## "$(nl) <dependencies>"
-## "$(nl) <dependency><![CDATA[$(dependencies)]]></dependency>"
-## "$(nl) </dependencies>"
-## "$(nl) <path><![CDATA[$(path)]]></path>"
-## "$(nl) <jam-target><![CDATA[$(jam-target)]]></jam-target>"
-## "$(nl) </target>"
-## ;
-## }
-## }
-## .contents on $(xml-file) +=
-## "$(nl) </targets>" ;
-
-## # Build $(xml-file) after $(constituents). Do so even if a
-## # constituent action fails and regenerate the xml on every bjam run.
-## INCLUDES $(xml-file) : $(constituents) ;
-## ALWAYS $(xml-file) ;
-## __ACTION_RULE__ on $(xml-file) = build-system.out-xml.generate-action ;
-## out-xml.generate $(xml-file) ;
-## }
-
-## # The actual build actions are here; if we did this work in the actions
-## # clause we would have to form a valid command line containing the
-## # result of @(...) below (the name of the XML file).
-## #
-## rule out-xml.generate-action ( args * : xml-file
-## : command status start end user system : output ? )
-## {
-## local contents =
-## [ on $(xml-file) return $(.header) $(.contents) $(.footer) ] ;
-## local f = @($(xml-file):E=$(contents)) ;
-## }
-
-## # Nothing to do here; the *real* actions happen in
-## # out-xml.generate-action.
-## actions quietly out-xml.generate { }
-
-## # Define the out-xml file target, which depends on all the targets so
-## # that it runs the collection after the targets have run.
-## out-xml $(.out-xml) : $(actual-targets) ;
-
-## # Set up a global __ACTION_RULE__ that records all the available
-## # statistics about each actual target in a variable "on" the --out-xml
-## # target.
-## #
-## rule out-xml.collect ( xml-file : target : command status start end user
-## system : output ? )
-## {
-## local nl = "
-## " ;
-## # Open the action with some basic info.
-## .contents on $(xml-file) +=
-## "$(nl) <action status=\"$(status)\" start=\"$(start)\" end=\"$(end)\" user=\"$(user)\" system=\"$(system)\">" ;
-
-## # If we have an action object we can print out more detailed info.
-## local action = [ on $(target) return $(.action) ] ;
-## if $(action)
-## {
-## local action-name = [ $(action).action-name ] ;
-## local action-sources = [ $(action).sources ] ;
-## local action-props = [ $(action).properties ] ;
-
-## # The qualified name of the action which we created the target.
-## .contents on $(xml-file) +=
-## "$(nl) <name><![CDATA[$(action-name)]]></name>" ;
-
-## # The sources that made up the target.
-## .contents on $(xml-file) +=
-## "$(nl) <sources>" ;
-## for local source in $(action-sources)
-## {
-## local source-actual = [ $(source).actual-name ] ;
-## .contents on $(xml-file) +=
-## "$(nl) <source><![CDATA[$(source-actual)]]></source>" ;
-## }
-## .contents on $(xml-file) +=
-## "$(nl) </sources>" ;
-
-## # The properties that define the conditions under which the
-## # target was built.
-## .contents on $(xml-file) +=
-## "$(nl) <properties>" ;
-## for local prop in [ $(action-props).raw ]
-## {
-## local prop-name = [ MATCH ^<(.*)>$ : $(prop:G) ] ;
-## .contents on $(xml-file) +=
-## "$(nl) <property name=\"$(prop-name)\"><![CDATA[$(prop:G=)]]></property>" ;
-## }
-## .contents on $(xml-file) +=
-## "$(nl) </properties>" ;
-## }
-
-## local locate = [ on $(target) return $(LOCATE) ] ;
-## locate ?= "" ;
-## .contents on $(xml-file) +=
-## "$(nl) <jam-target><![CDATA[$(target)]]></jam-target>"
-## "$(nl) <path><![CDATA[$(target:G=:R=$(locate))]]></path>"
-## "$(nl) <command><![CDATA[$(command)]]></command>"
-## "$(nl) <output><![CDATA[$(output)]]></output>" ;
-## .contents on $(xml-file) +=
-## "$(nl) </action>" ;
-## }
-
-## # When no __ACTION_RULE__ is set "on" a target, the search falls back to
-## # the global module.
-## module
-## {
-## __ACTION_RULE__ = build-system.out-xml.collect
-## [ modules.peek build-system : .out-xml ] ;
-## }
-
-## IMPORT
-## build-system :
-## out-xml.collect
-## out-xml.generate-action
-## : :
-## build-system.out-xml.collect
-## build-system.out-xml.generate-action
-## ;
-## }
-
j = option.get("jobs")
if j:
bjam.call("set-variable", 'PARALLELISM', j)
diff --git a/tools/build/src/engine/build.bat b/tools/build/src/engine/build.bat
index e0e742da24..2086f37a7d 100644
--- a/tools/build/src/engine/build.bat
+++ b/tools/build/src/engine/build.bat
@@ -28,7 +28,7 @@ ECHO ### You can specify the toolset as the argument, i.e.:
ECHO ### .\build.bat msvc
ECHO ###
ECHO ### Toolsets supported by this script are: borland, como, gcc, gcc-nocygwin,
-ECHO ### intel-win32, metrowerks, mingw, msvc, vc7, vc8, vc9, vc10, vc11, vc12, vc14
+ECHO ### intel-win32, metrowerks, mingw, msvc, vc7, vc8, vc9, vc10, vc11, vc12, vc14, vc15
ECHO ###
call :Set_Error
endlocal
@@ -101,6 +101,16 @@ call :Test_Empty %ProgramFiles%
if not errorlevel 1 set ProgramFiles=C:\Program Files
call :Clear_Error
+if NOT "_%VS150COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET=vc15"
+ set "BOOST_JAM_TOOLSET_ROOT=%VS150COMNTOOLS%..\..\VC\"
+ goto :eof)
+call :Clear_Error
+if EXIST "%ProgramFiles%\Microsoft Visual Studio 15.0\VC\VCVARSALL.BAT" (
+ set "BOOST_JAM_TOOLSET=vc15"
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 15.0\VC\"
+ goto :eof)
+call :Clear_Error
if NOT "_%VS140COMNTOOLS%_" == "__" (
set "BOOST_JAM_TOOLSET=vc14"
set "BOOST_JAM_TOOLSET_ROOT=%VS140COMNTOOLS%..\..\VC\"
@@ -446,6 +456,21 @@ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
set "_known_=1"
:Skip_VC14
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc15_" goto Skip_VC15
+if NOT "_%VS150COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET_ROOT=%VS150COMNTOOLS%..\..\VC\"
+ )
+if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%VCVARSALL.BAT" %BOOST_JAM_ARGS%
+if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ if "_%VCINSTALLDIR%_" == "__" (
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
+ ) )
+set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib"
+set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
+set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
+set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
+set "_known_=1"
+:Skip_VC15
if NOT "_%BOOST_JAM_TOOLSET%_" == "_borland_" goto Skip_BORLAND
if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
call :Test_Path bcc32.exe )
diff --git a/tools/build/src/engine/build.jam b/tools/build/src/engine/build.jam
index ad2ea35800..e16b240859 100644
--- a/tools/build/src/engine/build.jam
+++ b/tools/build/src/engine/build.jam
@@ -394,12 +394,19 @@ toolset vc12 cl : /Fe /Fe /Fd /Fo : -D
[ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
-I$(--python-include) -I$(--extra-include)
: kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
+## Microsoft Visual C++ 2015
toolset vc14 cl : /Fe /Fe /Fd /Fo : -D
: /nologo
[ opt --release : /GL /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
[ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
-I$(--python-include) -I$(--extra-include)
: kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
+toolset vc15 cl : /Fe /Fe /Fd /Fo : -D
+ : /nologo
+ [ opt --release : /GL /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
+ [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
+ -I$(--python-include) -I$(--extra-include)
+ : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
## VMS/OpenVMS DEC C
toolset vmsdecc cc : /OBJECT= : "/DEFINES=(" "," ")"
: /STANDARD=VAXC /PREFIX_LIBRARY_ENTRIES=(ALL_ENTRIES)
diff --git a/tools/build/src/engine/debug.c b/tools/build/src/engine/debug.c
index b4601066f8..3dc3533923 100644
--- a/tools/build/src/engine/debug.c
+++ b/tools/build/src/engine/debug.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2005. Rene Rivera
+ * Copyright 2005, 2016. Rene Rivera
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -9,6 +9,7 @@
#include "debug.h"
#include "output.h"
#include "hash.h"
+#include <time.h>
static profile_frame * profile_stack = 0;
@@ -28,7 +29,7 @@ void profile_enter( OBJECT * rulename, profile_frame * frame )
{
if ( DEBUG_PROFILE )
{
- clock_t start = clock();
+ double start = profile_clock();
profile_info * p;
if ( !profile_hash && rulename )
@@ -53,15 +54,15 @@ void profile_enter( OBJECT * rulename, profile_frame * frame )
p = &profile_other;
}
- ++p->num_entries;
- ++p->stack_count;
+ p->num_entries += 1;
+ p->stack_count += 1;
frame->info = p;
frame->caller = profile_stack;
profile_stack = frame;
- frame->entry_time = clock();
+ frame->entry_time = profile_clock();
frame->overhead = 0;
frame->subrules = 0;
@@ -76,7 +77,7 @@ void profile_memory( long mem )
{
if ( DEBUG_PROFILE )
if ( profile_stack && profile_stack->info )
- profile_stack->info->memory += mem;
+ profile_stack->info->memory += ((double)mem) / 1024;
}
@@ -85,7 +86,7 @@ void profile_exit( profile_frame * frame )
if ( DEBUG_PROFILE )
{
/* Cumulative time for this call. */
- clock_t const t = clock() - frame->entry_time - frame->overhead;
+ double t = profile_clock() - frame->entry_time - frame->overhead;
/* If this rule is already present on the stack, do not add the time for
* this instance.
*/
@@ -111,22 +112,17 @@ void profile_exit( profile_frame * frame )
static void dump_profile_entry( void * p_, void * ignored )
{
profile_info * p = (profile_info *)p_;
- unsigned long mem_each = ( p->memory / ( p->num_entries ? p->num_entries : 1
+ double mem_each = ( p->memory / ( p->num_entries ? p->num_entries : 1
) );
- double cumulative = p->cumulative;
- double net = p->net;
double q = p->net;
- q /= ( p->num_entries ? p->num_entries : 1 );
- cumulative /= CLOCKS_PER_SEC;
- net /= CLOCKS_PER_SEC;
- q /= CLOCKS_PER_SEC;
+ if (p->num_entries) q /= p->num_entries;
if ( !ignored )
{
profile_total.cumulative += p->net;
profile_total.memory += p->memory;
}
- out_printf( "%10ld %12.6f %12.6f %12.8f %10ld %10ld %s\n", p->num_entries,
- cumulative, net, q, p->memory, mem_each, object_str( p->name ) );
+ out_printf( "%10ld %12.6f %12.6f %12.8f %10.2f %10.2f %s\n", p->num_entries,
+ p->cumulative, p->net, q, p->memory, mem_each, object_str( p->name ) );
}
@@ -143,3 +139,20 @@ void profile_dump()
dump_profile_entry( &profile_total, (void *)1 );
}
}
+
+double profile_clock()
+{
+ return ((double) clock()) / CLOCKS_PER_SEC;
+}
+
+OBJECT * profile_make_local( char const * scope )
+{
+ if ( DEBUG_PROFILE )
+ {
+ return object_new( scope );
+ }
+ else
+ {
+ return 0;
+ }
+}
diff --git a/tools/build/src/engine/debug.h b/tools/build/src/engine/debug.h
index 4151d27fab..b4e8472c9b 100644
--- a/tools/build/src/engine/debug.h
+++ b/tools/build/src/engine/debug.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2005. Rene Rivera
+ * Copyright 2005, 2016. Rene Rivera
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -10,23 +10,22 @@
#include "constants.h"
#include "object.h"
-#include <time.h>
typedef struct profile_info
{
/* name of rule being called */
OBJECT * name;
- /* cumulative time spent in rule */
- clock_t cumulative;
- /* time spent in rule proper */
- clock_t net;
+ /* cumulative time spent in rule, in seconds */
+ double cumulative;
+ /* time spent in rule proper, in seconds */
+ double net;
/* number of time rule was entered */
unsigned long num_entries;
/* number of the times this function is present in stack */
unsigned long stack_count;
- /* bytes of memory allocated by the call */
- unsigned long memory;
+ /* memory allocated by the call, in KiB */
+ double memory;
} profile_info;
typedef struct profile_frame
@@ -34,13 +33,13 @@ typedef struct profile_frame
/* permanent storage where data accumulates */
profile_info * info;
/* overhead for profiling in this call */
- clock_t overhead;
+ double overhead;
/* time of last entry to rule */
- clock_t entry_time;
+ double entry_time;
/* stack frame of caller */
struct profile_frame * caller;
/* time spent in subrules */
- clock_t subrules;
+ double subrules;
} profile_frame;
profile_frame * profile_init( OBJECT * rulename, profile_frame * );
@@ -48,8 +47,16 @@ void profile_enter( OBJECT * rulename, profile_frame * );
void profile_memory( long mem );
void profile_exit( profile_frame * );
void profile_dump();
+double profile_clock();
#define PROFILE_ENTER( scope ) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init( constant_ ## scope, &PROF_ ## scope )
#define PROFILE_EXIT( scope ) profile_exit( PROF_ ## scope ## _p )
+OBJECT * profile_make_local( char const * );
+#define PROFILE_ENTER_LOCAL( scope ) \
+ static OBJECT * constant_LOCAL_##scope = 0; \
+ if (DEBUG_PROFILE && !constant_LOCAL_##scope) constant_LOCAL_##scope = profile_make_local( #scope ); \
+ PROFILE_ENTER( LOCAL_##scope )
+#define PROFILE_EXIT_LOCAL( scope ) PROFILE_EXIT( LOCAL_##scope )
+
#endif
diff --git a/tools/build/src/engine/execunix.c b/tools/build/src/engine/execunix.c
index 8ee4d9dbf2..21a223d9ed 100644
--- a/tools/build/src/engine/execunix.c
+++ b/tools/build/src/engine/execunix.c
@@ -64,8 +64,6 @@ static int get_free_cmdtab_slot();
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
static clock_t tps;
-static int old_time_initialized;
-static struct tms old_time;
/* We hold stdout & stderr child process information in two element arrays
* indexed as follows.
@@ -178,13 +176,6 @@ void exec_cmd
exit( EXITBAD );
}
- /* Initialize old_time only once. */
- if ( !old_time_initialized )
- {
- times( &old_time );
- old_time_initialized = 1;
- }
-
/* Start the command */
timestamp_current( &cmdtab[ slot ].start_dt );
@@ -513,6 +504,7 @@ void exec_wait()
int status;
int rstat;
timing_info time_info;
+ struct rusage cmd_usage;
/* We found a terminated child process - our search is done. */
finished = 1;
@@ -523,7 +515,7 @@ void exec_wait()
close_streams( i, ERR );
/* Reap the child and release resources. */
- while ( ( pid = waitpid( cmdtab[ i ].pid, &status, 0 ) ) == -1 )
+ while ( ( pid = wait4( cmdtab[ i ].pid, &status, 0, &cmd_usage ) ) == -1 )
if ( errno != EINTR )
break;
if ( pid != cmdtab[ i ].pid )
@@ -539,15 +531,10 @@ void exec_wait()
: EXIT_OK;
{
- struct tms new_time;
- times( &new_time );
- time_info.system = (double)( new_time.tms_cstime -
- old_time.tms_cstime ) / CLOCKS_PER_SEC;
- time_info.user = (double)( new_time.tms_cutime -
- old_time.tms_cutime ) / CLOCKS_PER_SEC;
+ time_info.system = ((double)(cmd_usage.ru_stime.tv_sec)*1000000.0+(double)(cmd_usage.ru_stime.tv_usec))/1000000.0;
+ time_info.user = ((double)(cmd_usage.ru_utime.tv_sec)*1000000.0+(double)(cmd_usage.ru_utime.tv_usec))/1000000.0;
timestamp_copy( &time_info.start, &cmdtab[ i ].start_dt );
timestamp_current( &time_info.end );
- old_time = new_time;
}
/* Drive the completion. */
diff --git a/tools/build/src/engine/filent.c b/tools/build/src/engine/filent.c
index 4f19a56b5b..9802dcb0ad 100644
--- a/tools/build/src/engine/filent.c
+++ b/tools/build/src/engine/filent.c
@@ -227,10 +227,7 @@ int try_file_query_root( file_info_t * const info )
}
else if ( pathstr[ 1 ] == ':' )
{
- if ( !pathstr[ 2 ] )
- {
- }
- else if ( !pathstr[ 2 ] || ( pathstr[ 2 ] == '\\' && !pathstr[ 3 ] ) )
+ if ( !pathstr[ 2 ] || ( pathstr[ 2 ] == '\\' && !pathstr[ 3 ] ) )
{
buf[ 0 ] = pathstr[ 0 ];
buf[ 1 ] = ':';
diff --git a/tools/build/src/engine/function.c b/tools/build/src/engine/function.c
index 89f8dfe51f..6d7b0feba5 100644
--- a/tools/build/src/engine/function.c
+++ b/tools/build/src/engine/function.c
@@ -1,5 +1,6 @@
/*
* Copyright 2011 Steven Watanabe
+ * Copyright 2016 Rene Rivera
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -26,6 +27,17 @@
#include <stdlib.h>
#include <string.h>
+/* *
+#define FUNCTION_DEBUG_PROFILE
+/* */
+
+#ifndef FUNCTION_DEBUG_PROFILE
+#undef PROFILE_ENTER_LOCAL
+#define PROFILE_ENTER_LOCAL(x) static int unused_LOCAL_##x = 0
+#undef PROFILE_EXIT_LOCAL
+#define PROFILE_EXIT_LOCAL(x)
+#endif
+
int glob( char const * s, char const * c );
void backtrace( FRAME * );
void backtrace_line( FRAME * );
@@ -2889,7 +2901,7 @@ static void compile_parse( PARSE * parse, compiler * c, int result_location )
{
compile_parse( parse->left, c, RESULT_RETURN );
compile_emit_cleanups( c, 0 );
- compile_emit( c, INSTR_RETURN, 0 );
+ compile_emit( c, INSTR_RETURN, 0 ); /* 0 for return in the middle of a function. */
}
else if ( parse->type == PARSE_BREAK )
{
@@ -2961,7 +2973,7 @@ FUNCTION * function_compile( PARSE * parse )
JAM_FUNCTION * result;
compiler_init( c );
compile_parse( parse, c, RESULT_RETURN );
- compile_emit( c, INSTR_RETURN, 0 );
+ compile_emit( c, INSTR_RETURN, 1 );
result = compile_to_function( c );
compiler_free( c );
result->file = object_copy( parse->file );
@@ -2981,7 +2993,7 @@ FUNCTION * function_compile_actions( char const * actions, OBJECT * file,
compiler_init( c );
var_parse_actions_compile( parse, c );
var_parse_actions_free( parse );
- compile_emit( c, INSTR_RETURN, 0 );
+ compile_emit( c, INSTR_RETURN, 1 );
result = compile_to_function( c );
compiler_free( c );
result->file = object_copy( file );
@@ -3612,7 +3624,9 @@ FUNCTION * function_bind_variables( FUNCTION * f, module_t * module,
case INSTR_SET: op_code = INSTR_SET_FIXED; break;
case INSTR_APPEND: op_code = INSTR_APPEND_FIXED; break;
case INSTR_DEFAULT: op_code = INSTR_DEFAULT_FIXED; break;
- case INSTR_RETURN: return (FUNCTION *)new_func;
+ case INSTR_RETURN:
+ if( code->arg == 1 ) return (FUNCTION *)new_func;
+ else continue;
case INSTR_CALL_MEMBER_RULE:
case INSTR_CALL_RULE: ++i; continue;
case INSTR_PUSH_MODULE:
@@ -3764,19 +3778,27 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
LIST * result = L0;
void * saved_stack = s->data;
+ PROFILE_ENTER_LOCAL(function_run);
+
if ( function_->type == FUNCTION_BUILTIN )
{
+ PROFILE_ENTER_LOCAL(function_run_FUNCTION_BUILTIN);
BUILTIN_FUNCTION const * const f = (BUILTIN_FUNCTION *)function_;
if ( function_->formal_arguments )
argument_list_check( function_->formal_arguments,
function_->num_formal_arguments, function_, frame );
+ PROFILE_EXIT_LOCAL(function_run_FUNCTION_BUILTIN);
+ PROFILE_EXIT_LOCAL(function_run);
return f->func( frame, f->flags );
}
#ifdef HAVE_PYTHON
else if ( function_->type == FUNCTION_PYTHON )
{
+ PROFILE_ENTER_LOCAL(function_run_FUNCTION_PYTHON);
PYTHON_FUNCTION * f = (PYTHON_FUNCTION *)function_;
+ PROFILE_EXIT_LOCAL(function_run_FUNCTION_PYTHON);
+ PROFILE_EXIT_LOCAL(function_run);
return call_python_function( f, frame );
}
#endif
@@ -3799,31 +3821,50 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
*/
case INSTR_PUSH_EMPTY:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_EMPTY);
stack_push( s, L0 );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_EMPTY);
break;
+ }
case INSTR_PUSH_CONSTANT:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_CONSTANT);
OBJECT * value = function_get_constant( function, code->arg );
stack_push( s, list_new( object_copy( value ) ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_CONSTANT);
break;
}
case INSTR_PUSH_ARG:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_ARG);
stack_push( s, frame_get_local( frame, code->arg ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_ARG);
break;
+ }
case INSTR_PUSH_VAR:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_VAR);
stack_push( s, function_get_variable( function, frame, code->arg ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_VAR);
break;
+ }
case INSTR_PUSH_VAR_FIXED:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_VAR_FIXED);
stack_push( s, list_copy( frame->module->fixed_variables[ code->arg
] ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_VAR_FIXED);
break;
+ }
case INSTR_PUSH_GROUP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_GROUP);
LIST * value = L0;
LISTITER iter;
LISTITER end;
@@ -3834,121 +3875,183 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
function, frame, list_item( iter ) ) );
list_free( l );
stack_push( s, value );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_GROUP);
break;
}
case INSTR_PUSH_APPEND:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_APPEND);
r = stack_pop( s );
l = stack_pop( s );
stack_push( s, list_append( l, r ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_APPEND);
break;
+ }
case INSTR_SWAP:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_SWAP);
l = stack_top( s );
stack_set( s, 0, stack_at( s, code->arg ) );
stack_set( s, code->arg, l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_SWAP);
break;
+ }
case INSTR_POP:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_POP);
list_free( stack_pop( s ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_POP);
break;
+ }
/*
* Branch instructions
*/
case INSTR_JUMP:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP);
code += code->arg;
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP);
break;
+ }
case INSTR_JUMP_EMPTY:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_EMPTY);
l = stack_pop( s );
if ( !list_cmp( l, L0 ) ) code += code->arg;
list_free( l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_EMPTY);
break;
+ }
case INSTR_JUMP_NOT_EMPTY:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_NOT_EMPTY);
l = stack_pop( s );
if ( list_cmp( l, L0 ) ) code += code->arg;
list_free( l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_NOT_EMPTY);
break;
+ }
case INSTR_JUMP_LT:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_LT);
r = stack_pop( s );
l = stack_pop( s );
if ( list_cmp( l, r ) < 0 ) code += code->arg;
list_free( l );
list_free( r );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_LT);
break;
+ }
case INSTR_JUMP_LE:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_LE);
r = stack_pop( s );
l = stack_pop( s );
if ( list_cmp( l, r ) <= 0 ) code += code->arg;
list_free( l );
list_free( r );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_LE);
break;
+ }
case INSTR_JUMP_GT:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_GT);
r = stack_pop( s );
l = stack_pop( s );
if ( list_cmp( l, r ) > 0 ) code += code->arg;
list_free( l );
list_free( r );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_GT);
break;
+ }
case INSTR_JUMP_GE:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_GE);
r = stack_pop( s );
l = stack_pop( s );
if ( list_cmp( l, r ) >= 0 ) code += code->arg;
list_free( l );
list_free( r );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_GE);
break;
+ }
case INSTR_JUMP_EQ:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_EQ);
r = stack_pop( s );
l = stack_pop( s );
if ( list_cmp( l, r ) == 0 ) code += code->arg;
list_free( l );
list_free( r );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_EQ);
break;
+ }
case INSTR_JUMP_NE:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_NE);
r = stack_pop(s);
l = stack_pop(s);
if ( list_cmp(l, r) != 0 ) code += code->arg;
list_free(l);
list_free(r);
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_NE);
break;
+ }
case INSTR_JUMP_IN:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_IN);
r = stack_pop(s);
l = stack_pop(s);
if ( list_is_sublist( l, r ) ) code += code->arg;
list_free(l);
list_free(r);
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_IN);
break;
+ }
case INSTR_JUMP_NOT_IN:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_NOT_IN);
r = stack_pop( s );
l = stack_pop( s );
if ( !list_is_sublist( l, r ) ) code += code->arg;
list_free( l );
list_free( r );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_NOT_IN);
break;
+ }
/*
* For
*/
case INSTR_FOR_INIT:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_FOR_INIT);
l = stack_top( s );
*(LISTITER *)stack_allocate( s, sizeof( LISTITER ) ) =
list_begin( l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_FOR_INIT);
break;
+ }
case INSTR_FOR_LOOP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_FOR_LOOP);
LISTITER iter = *(LISTITER *)stack_get( s );
stack_deallocate( s, sizeof( LISTITER ) );
l = stack_top( s );
@@ -3964,13 +4067,16 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
*(LISTITER *)stack_allocate( s, sizeof( LISTITER ) ) = iter;
stack_push( s, r );
}
+ PROFILE_EXIT_LOCAL(function_run_INSTR_FOR_LOOP);
break;
}
case INSTR_FOR_POP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_FOR_POP);
stack_deallocate( s, sizeof( LISTITER ) );
list_free( stack_pop( s ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_FOR_POP);
break;
}
@@ -3980,6 +4086,7 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
case INSTR_JUMP_NOT_GLOB:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_NOT_GLOB);
char const * pattern;
char const * match;
l = stack_pop( s );
@@ -3991,6 +4098,7 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
else
list_free( stack_pop( s ) );
list_free( l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_NOT_GLOB);
break;
}
@@ -3999,20 +4107,29 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
*/
case INSTR_SET_RESULT:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_SET_RESULT);
list_free( result );
if ( !code->arg )
result = stack_pop( s );
else
result = list_copy( stack_top( s ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_SET_RESULT);
break;
+ }
case INSTR_PUSH_RESULT:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_RESULT);
stack_push( s, result );
result = L0;
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_RESULT);
break;
+ }
case INSTR_RETURN:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_RETURN);
if ( function_->formal_arguments )
argument_list_pop( function_->formal_arguments,
function_->num_formal_arguments, frame, s );
@@ -4028,6 +4145,8 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
}
#endif
assert( saved_stack == s->data );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_RETURN);
+ PROFILE_EXIT_LOCAL(function_run);
return result;
}
@@ -4037,38 +4156,49 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
case INSTR_PUSH_LOCAL:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_LOCAL);
LIST * value = stack_pop( s );
stack_push( s, function_swap_variable( function, frame, code->arg,
value ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_LOCAL);
break;
}
case INSTR_POP_LOCAL:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_POP_LOCAL);
function_set_variable( function, frame, code->arg, stack_pop( s ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_POP_LOCAL);
break;
+ }
case INSTR_PUSH_LOCAL_FIXED:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_LOCAL_FIXED);
LIST * value = stack_pop( s );
LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
assert( code->arg < frame->module->num_fixed_variables );
stack_push( s, *ptr );
*ptr = value;
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_LOCAL_FIXED);
break;
}
case INSTR_POP_LOCAL_FIXED:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_POP_LOCAL_FIXED);
LIST * value = stack_pop( s );
LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
assert( code->arg < frame->module->num_fixed_variables );
list_free( *ptr );
*ptr = value;
+ PROFILE_EXIT_LOCAL(function_run_INSTR_POP_LOCAL_FIXED);
break;
}
case INSTR_PUSH_LOCAL_GROUP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_LOCAL_GROUP);
LIST * const value = stack_pop( s );
LISTITER iter;
LISTITER end;
@@ -4079,11 +4209,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
list_item( iter ), list_copy( value ) ) );
list_free( value );
stack_push( s, l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_LOCAL_GROUP);
break;
}
case INSTR_POP_LOCAL_GROUP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_POP_LOCAL_GROUP);
LISTITER iter;
LISTITER end;
r = stack_pop( s );
@@ -4094,6 +4226,7 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
function_set_named_variable( function, frame, list_item( iter ),
stack_pop( s ) );
list_free( l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_POP_LOCAL_GROUP);
break;
}
@@ -4103,6 +4236,7 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
case INSTR_PUSH_ON:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_ON);
LIST * targets = stack_top( s );
if ( !list_empty( targets ) )
{
@@ -4119,11 +4253,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
stack_push( s, L0 );
code += code->arg;
}
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_ON);
break;
}
case INSTR_POP_ON:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_POP_ON);
LIST * result = stack_pop( s );
LIST * targets = stack_pop( s );
if ( !list_empty( targets ) )
@@ -4133,11 +4269,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
}
list_free( targets );
stack_push( s, result );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_POP_ON);
break;
}
case INSTR_SET_ON:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_SET_ON);
LIST * targets = stack_pop( s );
LIST * value = stack_pop( s );
LIST * vars = stack_pop( s );
@@ -4156,11 +4294,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
list_free( vars );
list_free( targets );
stack_push( s, value );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_SET_ON);
break;
}
case INSTR_APPEND_ON:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND_ON);
LIST * targets = stack_pop( s );
LIST * value = stack_pop( s );
LIST * vars = stack_pop( s );
@@ -4179,11 +4319,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
list_free( vars );
list_free( targets );
stack_push( s, value );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND_ON);
break;
}
case INSTR_DEFAULT_ON:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_DEFAULT_ON);
LIST * targets = stack_pop( s );
LIST * value = stack_pop( s );
LIST * vars = stack_pop( s );
@@ -4202,12 +4344,14 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
list_free( vars );
list_free( targets );
stack_push( s, value );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_DEFAULT_ON);
break;
}
/* [ on $(target) return $(variable) ] */
case INSTR_GET_ON:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_GET_ON);
LIST * targets = stack_pop( s );
LIST * result = L0;
if ( !list_empty( targets ) )
@@ -4232,6 +4376,7 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
}
list_free( targets );
stack_push( s, list_copy( result ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_GET_ON);
break;
}
@@ -4240,39 +4385,56 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
*/
case INSTR_SET:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_SET);
function_set_variable( function, frame, code->arg,
stack_pop( s ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_SET);
break;
+ }
case INSTR_APPEND:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND);
function_append_variable( function, frame, code->arg,
stack_pop( s ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND);
break;
+ }
case INSTR_DEFAULT:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_DEFAULT);
function_default_variable( function, frame, code->arg,
stack_pop( s ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_DEFAULT);
break;
+ }
case INSTR_SET_FIXED:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_SET_FIXED);
LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
assert( code->arg < frame->module->num_fixed_variables );
list_free( *ptr );
*ptr = stack_pop( s );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_SET_FIXED);
break;
}
case INSTR_APPEND_FIXED:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND_FIXED);
LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
assert( code->arg < frame->module->num_fixed_variables );
*ptr = list_append( *ptr, stack_pop( s ) );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND_FIXED);
break;
}
case INSTR_DEFAULT_FIXED:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_DEFAULT_FIXED);
LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
LIST * value = stack_pop( s );
assert( code->arg < frame->module->num_fixed_variables );
@@ -4280,11 +4442,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
*ptr = value;
else
list_free( value );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_DEFAULT_FIXED);
break;
}
case INSTR_SET_GROUP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_SET_GROUP);
LIST * value = stack_pop( s );
LIST * vars = stack_pop( s );
LISTITER iter = list_begin( vars );
@@ -4294,11 +4458,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
list_copy( value ) );
list_free( vars );
list_free( value );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_SET_GROUP);
break;
}
case INSTR_APPEND_GROUP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND_GROUP);
LIST * value = stack_pop( s );
LIST * vars = stack_pop( s );
LISTITER iter = list_begin( vars );
@@ -4308,11 +4474,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
), list_copy( value ) );
list_free( vars );
list_free( value );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND_GROUP);
break;
}
case INSTR_DEFAULT_GROUP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_DEFAULT_GROUP);
LIST * value = stack_pop( s );
LIST * vars = stack_pop( s );
LISTITER iter = list_begin( vars );
@@ -4322,6 +4490,7 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
iter ), list_copy( value ) );
list_free( vars );
list_free( value );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_DEFAULT_GROUP);
break;
}
@@ -4331,31 +4500,43 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
case INSTR_CALL_RULE:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_CALL_RULE);
char const * unexpanded = object_str( function_get_constant(
function, code[ 1 ].op_code ) );
LIST * result = function_call_rule( function, frame, s, code->arg,
unexpanded, function->file, code[ 1 ].arg );
stack_push( s, result );
++code;
+ PROFILE_EXIT_LOCAL(function_run_INSTR_CALL_RULE);
break;
}
case INSTR_CALL_MEMBER_RULE:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_CALL_MEMBER_RULE);
OBJECT * rule_name = function_get_constant( function, code[1].op_code );
LIST * result = function_call_member_rule( function, frame, s, code->arg, rule_name, function->file, code[1].arg );
stack_push( s, result );
++code;
+ PROFILE_EXIT_LOCAL(function_run_INSTR_CALL_MEMBER_RULE);
break;
}
case INSTR_RULE:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_RULE);
function_set_rule( function, frame, s, code->arg );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_RULE);
break;
+ }
case INSTR_ACTIONS:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_ACTIONS);
function_set_actions( function, frame, s, code->arg );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_ACTIONS);
break;
+ }
/*
* Variable expansion
@@ -4363,6 +4544,7 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
case INSTR_APPLY_MODIFIERS:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_MODIFIERS);
int n;
int i;
l = stack_pop( s );
@@ -4374,18 +4556,24 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
for ( i = 0; i < code->arg; ++i )
list_free( stack_pop( s ) ); /* pop modifiers */
stack_push( s, l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_MODIFIERS);
break;
}
case INSTR_APPLY_INDEX:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_INDEX);
l = apply_subscript( s );
list_free( stack_pop( s ) );
list_free( stack_pop( s ) );
stack_push( s, l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_INDEX);
break;
+ }
case INSTR_APPLY_INDEX_MODIFIERS:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_INDEX_MODIFIERS);
int i;
int n;
l = stack_pop( s );
@@ -4400,11 +4588,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
for ( i = 0; i < code->arg; ++i )
list_free( stack_pop( s ) ); /* pop modifiers */
stack_push( s, l );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_INDEX_MODIFIERS);
break;
}
case INSTR_APPLY_MODIFIERS_GROUP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_MODIFIERS_GROUP);
int i;
LIST * const vars = stack_pop( s );
int const n = expand_modifiers( s, code->arg );
@@ -4423,11 +4613,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
for ( i = 0; i < code->arg; ++i )
list_free( stack_pop( s ) ); /* pop modifiers */
stack_push( s, result );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_MODIFIERS_GROUP);
break;
}
case INSTR_APPLY_INDEX_GROUP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_INDEX_GROUP);
LIST * vars = stack_pop( s );
LIST * result = L0;
LISTITER iter = list_begin( vars );
@@ -4442,11 +4634,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
list_free( vars );
list_free( stack_pop( s ) );
stack_push( s, result );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_INDEX_GROUP);
break;
}
case INSTR_APPLY_INDEX_MODIFIERS_GROUP:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_INDEX_MODIFIERS_GROUP);
int i;
LIST * const vars = stack_pop( s );
LIST * const r = stack_pop( s );
@@ -4469,11 +4663,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
for ( i = 0; i < code->arg; ++i )
list_free( stack_pop( s ) ); /* pop modifiers */
stack_push( s, result );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_INDEX_MODIFIERS_GROUP);
break;
}
case INSTR_COMBINE_STRINGS:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_COMBINE_STRINGS);
size_t const buffer_size = code->arg * sizeof( expansion_item );
LIST * * const stack_pos = stack_get( s );
expansion_item * items = stack_allocate( s, buffer_size );
@@ -4486,11 +4682,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
for ( i = 0; i < code->arg; ++i )
list_free( stack_pop( s ) );
stack_push( s, result );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_COMBINE_STRINGS);
break;
}
case INSTR_GET_GRIST:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_GET_GRIST);
LIST * vals = stack_pop( s );
LIST * result = L0;
LISTITER iter, end;
@@ -4516,11 +4714,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
list_free( vals );
stack_push( s, result );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_GET_GRIST);
break;
}
case INSTR_INCLUDE:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_INCLUDE);
LIST * nt = stack_pop( s );
if ( !list_empty( nt ) )
{
@@ -4549,6 +4749,7 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
parse_file( t->boundname, frame );
}
+ PROFILE_EXIT_LOCAL(function_run_INSTR_INCLUDE);
break;
}
@@ -4558,6 +4759,7 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
case INSTR_PUSH_MODULE:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_MODULE);
LIST * const module_name = stack_pop( s );
module_t * const outer_module = frame->module;
frame->module = !list_empty( module_name )
@@ -4566,19 +4768,23 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
list_free( module_name );
*(module_t * *)stack_allocate( s, sizeof( module_t * ) ) =
outer_module;
+ PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_MODULE);
break;
}
case INSTR_POP_MODULE:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_POP_MODULE);
module_t * const outer_module = *(module_t * *)stack_get( s );
stack_deallocate( s, sizeof( module_t * ) );
frame->module = outer_module;
+ PROFILE_EXIT_LOCAL(function_run_INSTR_POP_MODULE);
break;
}
case INSTR_CLASS:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_CLASS);
LIST * bases = stack_pop( s );
LIST * name = stack_pop( s );
OBJECT * class_module = make_class_module( name, bases, frame );
@@ -4589,25 +4795,33 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
*(module_t * *)stack_allocate( s, sizeof( module_t * ) ) =
outer_module;
+ PROFILE_EXIT_LOCAL(function_run_INSTR_CLASS);
break;
}
case INSTR_BIND_MODULE_VARIABLES:
+ {
+ PROFILE_ENTER_LOCAL(function_run_INSTR_BIND_MODULE_VARIABLES);
module_bind_variables( frame->module );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_BIND_MODULE_VARIABLES);
break;
+ }
case INSTR_APPEND_STRINGS:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND_STRINGS);
string buf[ 1 ];
string_new( buf );
combine_strings( s, code->arg, buf );
stack_push( s, list_new( object_new( buf->value ) ) );
string_free( buf );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND_STRINGS);
break;
}
case INSTR_WRITE_FILE:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_WRITE_FILE);
string buf[ 1 ];
char const * out;
OBJECT * tmp_filename = 0;
@@ -4713,20 +4927,25 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
object_free( tmp_filename );
if ( out_debug ) out_putc( '\n' );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_WRITE_FILE);
break;
}
case INSTR_OUTPUT_STRINGS:
{
+ PROFILE_ENTER_LOCAL(function_run_INSTR_OUTPUT_STRINGS);
string * const buf = *(string * *)( (char *)stack_get( s ) + (
code->arg * sizeof( LIST * ) ) );
combine_strings( s, code->arg, buf );
+ PROFILE_EXIT_LOCAL(function_run_INSTR_OUTPUT_STRINGS);
break;
}
}
++code;
}
+
+ PROFILE_EXIT_LOCAL(function_run);
}
diff --git a/tools/build/src/engine/hash.c b/tools/build/src/engine/hash.c
index 772087a228..b2685a860b 100644
--- a/tools/build/src/engine/hash.c
+++ b/tools/build/src/engine/hash.c
@@ -24,7 +24,7 @@
#include <assert.h>
-/* */
+/* *
#define HASH_DEBUG_PROFILE 1
/* */
diff --git a/tools/build/src/engine/make1.c b/tools/build/src/engine/make1.c
index 7dbf7c8da2..8282279cfa 100644
--- a/tools/build/src/engine/make1.c
+++ b/tools/build/src/engine/make1.c
@@ -689,7 +689,7 @@ static void call_timing_rule( TARGET * target, timing_info const * const time )
if ( !list_empty( timing_rule ) )
{
- /* rule timing-rule ( args * : target : start end user system ) */
+ /* rule timing-rule ( args * : target : start end user system clock ) */
/* Prepare the argument list. */
FRAME frame[ 1 ];
@@ -703,12 +703,14 @@ static void call_timing_rule( TARGET * target, timing_info const * const time )
/* target :: the name of the target */
lol_add( frame->args, list_new( object_copy( target->name ) ) );
- /* start end user system :: info about the action command */
- lol_add( frame->args, list_push_back( list_push_back( list_push_back( list_new(
+ /* start end user system clock :: info about the action command */
+ lol_add( frame->args, list_push_back( list_push_back( list_push_back( list_push_back( list_new(
outf_time( &time->start ) ),
outf_time( &time->end ) ),
outf_double( time->user ) ),
- outf_double( time->system ) ) );
+ outf_double( time->system ) ),
+ outf_double( timestamp_delta_seconds(&time->start, &time->end) ) )
+ );
/* Call the rule. */
evaluate_rule( bindrule( rulename , root_module() ), rulename, frame );
@@ -854,7 +856,9 @@ static void make1c_closure
{
call_timing_rule( t, time );
if ( DEBUG_EXECCMD )
- out_printf( "%f sec system; %f sec user\n", time->system, time->user );
+ out_printf( "%f sec system; %f sec user; %f sec clock\n",
+ time->system, time->user,
+ timestamp_delta_seconds(&time->start, &time->end) );
/* Assume -p0 is in effect, i.e. cmd_stdout contains merged output. */
call_action_rule( t, status_orig, time, cmd->buf->value, cmd_stdout );
diff --git a/tools/build/src/engine/timestamp.c b/tools/build/src/engine/timestamp.c
index 17510bcd06..b6fd906efb 100644
--- a/tools/build/src/engine/timestamp.c
+++ b/tools/build/src/engine/timestamp.c
@@ -261,3 +261,11 @@ void timestamp_done()
hashdone( bindhash );
}
}
+
+/*
+ * timestamp_delta_seconds() - seconds from time a to b.
+ */
+double timestamp_delta_seconds( timestamp const * const a , timestamp const * const b )
+{
+ return ((b->secs*1000000.0+b->nsecs)-(a->secs*1000000.0+a->nsecs))/1000000.0;
+}
diff --git a/tools/build/src/engine/timestamp.h b/tools/build/src/engine/timestamp.h
index ecedb5f925..e9b41753c3 100644
--- a/tools/build/src/engine/timestamp.h
+++ b/tools/build/src/engine/timestamp.h
@@ -42,5 +42,6 @@ void timestamp_from_filetime( timestamp * const, FILETIME const * const );
#endif
void timestamp_done();
+double timestamp_delta_seconds( timestamp const * const, timestamp const * const );
#endif
diff --git a/tools/build/src/exceptions.py b/tools/build/src/exceptions.py
index 5750abfe3f..70d4d98317 100644
--- a/tools/build/src/exceptions.py
+++ b/tools/build/src/exceptions.py
@@ -2,43 +2,54 @@
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-# TODO: add more exception types?
-class BaseException (Exception):
- def __init__ (self, message = ''): Exception.__init__ (self, message)
+class BaseBoostBuildException(Exception):
+ """A base Exception class for all other Boost.Build exceptions to inherit from."""
-class UserError (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
-class FeatureConflict (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
+class UserError(BaseBoostBuildException):
+ pass
-class InvalidSource (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
-class InvalidFeature (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
+class FeatureConflict(BaseBoostBuildException):
+ pass
-class InvalidProperty (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
-class InvalidValue (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
+class InvalidSource(BaseBoostBuildException):
+ pass
-class InvalidAttribute (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
-class AlreadyDefined (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
+class InvalidFeature(BaseBoostBuildException):
+ pass
-class IllegalOperation (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
-class Recursion (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
+class InvalidProperty(BaseBoostBuildException):
+ pass
-class NoBestMatchingAlternative (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
-class NoAction (BaseException):
- def __init__ (self, message = ''): BaseException.__init__ (self, message)
+class InvalidValue(BaseBoostBuildException):
+ pass
+
+
+class InvalidAttribute(BaseBoostBuildException):
+ pass
+
+
+class AlreadyDefined(BaseBoostBuildException):
+ pass
+
+
+class IllegalOperation(BaseBoostBuildException):
+ pass
+
+
+class Recursion(BaseBoostBuildException):
+ pass
+
+
+class NoBestMatchingAlternative(BaseBoostBuildException):
+ pass
+
+
+class NoAction(BaseBoostBuildException):
+ pass
diff --git a/tools/build/src/kernel/bootstrap.jam b/tools/build/src/kernel/bootstrap.jam
index c4320dc299..74ee5d34f0 100644
--- a/tools/build/src/kernel/bootstrap.jam
+++ b/tools/build/src/kernel/bootstrap.jam
@@ -140,7 +140,6 @@ if ! $(dont-build)
}
else
{
- ECHO "Boost.Build V2 Python port (experimental)" ;
# Define additional interface exposed to Python code. Python code will
# also have access to select bjam builtins in the 'bjam' module, but
diff --git a/tools/build/src/tools/builtin.jam b/tools/build/src/tools/builtin.jam
index f39fb7018d..1236120fe7 100644
--- a/tools/build/src/tools/builtin.jam
+++ b/tools/build/src/tools/builtin.jam
@@ -40,7 +40,7 @@ import convert ;
import generate ;
-.os-names = aix android bsd cygwin darwin freebsd haiku hpux iphone linux netbsd
+.os-names = aix android appletv bsd cygwin darwin freebsd haiku hpux iphone linux netbsd
openbsd osf qnx qnxnto sgi solaris unix unixware windows vms
elf # Not actually an OS -- used for targeting bare metal where object
# format is ELF. This catches both -elf and -eabi gcc targets and well
diff --git a/tools/build/src/tools/builtin.py b/tools/build/src/tools/builtin.py
index a149a33320..ee6474b73a 100644
--- a/tools/build/src/tools/builtin.py
+++ b/tools/build/src/tools/builtin.py
@@ -82,7 +82,7 @@ def variant (name, parents_or_properties, explicit_properties = []):
feature.compose ("<variant>" + name, explicit_properties.all())
__os_names = """
- amiga aix bsd cygwin darwin dos emx freebsd hpux iphone linux netbsd
+ amiga aix appletv bsd cygwin darwin dos emx freebsd hpux iphone linux netbsd
openbsd osf qnx qnxnto sgi solaris sun sunos svr4 sysv ultrix unix unixware
vms windows
""".split()
@@ -147,7 +147,7 @@ def register_globals ():
feature.feature ('exception-handling', ['on', 'off'], ['propagated'])
# Whether there is support for asynchronous EH (e.g. catching SEGVs).
- feature.feature ('asynch-exceptions', ['on', 'off'], ['propagated'])
+ feature.feature ('asynch-exceptions', ['off', 'on'], ['propagated'])
# Whether all extern "C" functions are considered nothrow by default.
feature.feature ('extern-c-nothrow', ['off', 'on'], ['propagated'])
@@ -367,11 +367,21 @@ class CScanner (scanner.Scanner):
return r'#[ \t]*include[ ]*(<(.*)>|"(.*)")'
def process (self, target, matches, binding):
-
- angle = regex.transform (matches, "<(.*)>")
- quoted = regex.transform (matches, '"(.*)"')
-
- g = str(id(self))
+ # since it's possible for this function to be called
+ # thousands to millions of times (depending on how many
+ # header files there are), as such, there are some
+ # optimizations that have been used here. Anything that
+ # is slightly out of the ordinary for Python code
+ # has been commented.
+ angle = []
+ quoted = []
+ for match in matches:
+ if '<' in match:
+ angle.append(match.strip('<>'))
+ elif '"' in match:
+ quoted.append(match.strip('"'))
+
+ g = id(self)
b = os.path.normpath(os.path.dirname(binding[0]))
# Attach binding of including file to included targets.
@@ -382,27 +392,38 @@ class CScanner (scanner.Scanner):
# We don't need this extra information for angle includes,
# since they should not depend on including file (we can't
# get literal "." in include path).
- g2 = g + "#" + b
+ # Note: string interpolation is slightly faster
+ # than .format()
+ g2 = '<%s#%s>' % (g, b)
+ g = "<%s>" % g
- g = "<" + g + ">"
- g2 = "<" + g2 + ">"
angle = [g + x for x in angle]
quoted = [g2 + x for x in quoted]
all = angle + quoted
bjam.call("mark-included", target, all)
+ # each include in self.includes_ looks something like this:
+ # <include>path/to/somewhere
+ # calling get_value(include) is super slow,
+ # calling .replace('<include>', '') is much faster
+ # however, i[9:] is the fastest way of stripping off the "<include>"
+ # substring.
+ include_paths = [i[9:] for i in self.includes_]
+
engine = get_manager().engine()
- engine.set_target_variable(angle, "SEARCH", get_value(self.includes_))
- engine.set_target_variable(quoted, "SEARCH", [b] + get_value(self.includes_))
+ engine.set_target_variable(angle, "SEARCH", include_paths)
+ engine.set_target_variable(quoted, "SEARCH", [b] + include_paths)
# Just propagate current scanner to includes, in a hope
# that includes do not change scanners.
- get_manager().scanners().propagate(self, angle + quoted)
+ get_manager().scanners().propagate(self, all)
scanner.register (CScanner, 'include')
type.set_scanner ('CPP', CScanner)
type.set_scanner ('C', CScanner)
+type.set_scanner('H', CScanner)
+type.set_scanner('HPP', CScanner)
# Ported to trunk@47077
class LibGenerator (generators.Generator):
@@ -598,6 +619,8 @@ class LinkingGenerator (generators.Generator):
assert isinstance(prop_set, property_set.PropertySet)
assert is_iterable_typed(sources, virtual_target.VirtualTarget)
+ # create a copy since sources is being modified
+ sources = list(sources)
sources.extend(prop_set.get('<library>'))
# Add <library-path> properties for all searched libraries
@@ -729,11 +752,27 @@ class ArchiveGenerator (generators.Generator):
generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
def run (self, project, name, prop_set, sources):
- sources += prop_set.get ('<library>')
+ assert isinstance(project, targets.ProjectTarget)
+ assert isinstance(name, basestring) or name is None
+ assert isinstance(prop_set, property_set.PropertySet)
+ assert is_iterable_typed(sources, virtual_target.VirtualTarget)
+
+ # create a copy since this modifies the sources list
+ sources = list(sources)
+ sources.extend(prop_set.get('<library>'))
result = generators.Generator.run (self, project, name, prop_set, sources)
- return result
+ usage_requirements = []
+ link = prop_set.get('<link>')
+ if 'static' in link:
+ for t in sources:
+ if type.is_derived(t.type(), 'LIB'):
+ usage_requirements.append(property.Property('<library>', t))
+
+ usage_requirements = property_set.create(usage_requirements)
+
+ return usage_requirements, result
def register_archiver(id, source_types, target_types, requirements):
diff --git a/tools/build/src/tools/bzip2.jam b/tools/build/src/tools/bzip2.jam
index 0a525905c5..ae9a039090 100644
--- a/tools/build/src/tools/bzip2.jam
+++ b/tools/build/src/tools/bzip2.jam
@@ -137,13 +137,11 @@ rule init (
[ property.select <search> <include> <name> : $(options) ] "and"
[ property.select <source> <tag> <build-name> : $(options) ] ;
}
- else
- {
- no-build-from-source = true ;
- }
}
-
- source-path ?= [ modules.peek : BZIP2_SOURCE ] ;
+ else
+ {
+ source-path ?= [ modules.peek : BZIP2_SOURCE ] ;
+ }
if $(.configured.$(condition))
{
@@ -160,7 +158,7 @@ rule init (
}
return ;
}
- else if $(source-path) && ! $(no-build-from-source)
+ else if $(source-path)
{
build-name ?= bz2 ;
library-id = [ CALC $(library-id) + 1 ] ;
@@ -218,7 +216,9 @@ rule init (
$(mt).set-target $(target) ;
}
targets.main-target-alternative $(mt) ;
- } else {
+ }
+ else
+ {
if $(.debug)
{
ECHO "notice: [bzip2] Using pre-installed library" ;
@@ -229,7 +229,7 @@ rule init (
}
local mt = [ new ac-library bzip2 : $(.project) : $(condition) :
- $(include-path) : $(library-path) : $(library-name) : $(root) ] ;
+ $(include-path) : $(library-path) : $(library-name) ] ;
$(mt).set-header $(header) ;
$(mt).set-default-names $(names) ;
targets.main-target-alternative $(mt) ;
diff --git a/tools/build/src/tools/cast.py b/tools/build/src/tools/cast.py
index 0d21edb0b6..cf1a876273 100644
--- a/tools/build/src/tools/cast.py
+++ b/tools/build/src/tools/cast.py
@@ -25,7 +25,7 @@
# > cast, as defining a new target type + generator for that type is somewhat
# > simpler than defining a main target rule.
-from b2.build import targets, virtual_target, property_set
+from b2.build import targets, virtual_target, property_set, type as type_
from b2.manager import get_manager
from b2.util import bjam_signature, is_iterable_typed
@@ -52,6 +52,7 @@ class CastTargetClass(targets.TypedTarget):
return property_set.empty(), result
+
@bjam_signature((["name", "type"], ["sources", "*"], ["requirements", "*"],
["default_build", "*"], ["usage_requirements", "*"]))
def cast(name, type, sources, requirements, default_build, usage_requirements):
@@ -61,8 +62,11 @@ def cast(name, type, sources, requirements, default_build, usage_requirements):
project = get_manager().projects().current()
+ real_type = type_.type_from_rule_name(type)
+ if not real_type:
+ real_type = type
return t.main_target_alternative(
- CastTargetClass(name, project, type,
+ CastTargetClass(name, project, real_type,
t.main_target_sources(sources, name),
t.main_target_requirements(requirements, project),
t.main_target_default_build(default_build, project),
diff --git a/tools/build/src/tools/clang.jam b/tools/build/src/tools/clang.jam
index e0ac9a553c..2d89f3807a 100644
--- a/tools/build/src/tools/clang.jam
+++ b/tools/build/src/tools/clang.jam
@@ -3,7 +3,7 @@
# or copy at http://www.boost.org/LICENSE_1_0.txt)
# This is a generic 'clang' toolset. Depending on the current system, it
-# forwards either to 'clang-unix' or 'clang-darwin' modules.
+# forwards either to 'clang-linux' or 'clang-darwin' modules.
import feature ;
import os ;
diff --git a/tools/build/src/tools/common.py b/tools/build/src/tools/common.py
index 3f30baa568..87b942c6d3 100644
--- a/tools/build/src/tools/common.py
+++ b/tools/build/src/tools/common.py
@@ -182,7 +182,7 @@ def check_init_parameters(toolset, requirement, *args):
The return value from this rule is a condition to be used for flags settings.
"""
assert isinstance(toolset, basestring)
- assert is_iterable_typed(requirement, basestring)
+ assert is_iterable_typed(requirement, basestring) or requirement is None
from b2.build import toolset as b2_toolset
if requirement is None:
requirement = []
@@ -204,7 +204,7 @@ def check_init_parameters(toolset, requirement, *args):
### if $(value)-is-not-empty
if value is not None:
condition = condition + '-' + value
- if __had_unspecified_value.has_key(str_toolset_name):
+ if str_toolset_name in __had_unspecified_value:
raise BaseException("'%s' initialization: parameter '%s' inconsistent\n" \
"no value was specified in earlier initialization\n" \
"an explicit value is specified now" % (toolset, name))
@@ -220,8 +220,8 @@ def check_init_parameters(toolset, requirement, *args):
if m:
t = m.group(1)
- if not __had_value.has_key(str_toolset_name):
- if not __declared_subfeature.has_key(str((t, name))):
+ if str_toolset_name not in __had_value:
+ if str((t, name)) not in __declared_subfeature:
feature.subfeature('toolset', t, name, [], ['propagated'])
__declared_subfeature[str((t, name))] = True
@@ -231,7 +231,7 @@ def check_init_parameters(toolset, requirement, *args):
subcondition += ['<toolset-' + t + ':' + name + '>' + value ]
else:
- if __had_value.has_key(str_toolset_name):
+ if str_toolset_name in __had_value:
raise BaseException ("'%s' initialization: parameter '%s' inconsistent\n" \
"an explicit value was specified in an earlier initialization\n" \
"no value is specified now" % (toolset, name))
@@ -247,7 +247,7 @@ def check_init_parameters(toolset, requirement, *args):
if requirement:
sig += '-' + '-'.join(requirement)
- if __all_signatures.has_key(sig):
+ if sig in __all_signatures:
message = "duplicate initialization of '%s' with the following parameters: " % toolset
for arg in args:
@@ -314,9 +314,8 @@ def get_invocation_command_nodefault(
#FIXME
#ECHO "warning: initialized from" [ errors.nearest-user-location ]
command = []
- command = ' '.join(command)
-
- assert(isinstance(command, str))
+ if command:
+ command = ' '.join(command)
return command
@@ -542,9 +541,16 @@ def prepend_path_variable_command(variable, paths):
"""
assert isinstance(variable, basestring)
assert is_iterable_typed(paths, basestring)
+ return path_variable_setting_command(
+ variable, paths + [expand_variable(variable)])
+
+
+def expand_variable(variable):
+ """Produce a string that expands the shell variable."""
+ if os.name == 'nt':
+ return '%{}%'.format(variable)
+ return '${%s}' % variable
- return path_variable_setting_command(variable,
- paths + os.environ.get(variable, "").split(os.pathsep))
def file_creation_command():
"""
@@ -575,10 +581,7 @@ def mkdir(engine, target):
__mkdir_set.add(target)
# Schedule the mkdir build action.
- if os_name() == 'NT':
- engine.set_update_action("common.MkDir1-quick-fix-for-windows", target, [])
- else:
- engine.set_update_action("common.MkDir1-quick-fix-for-unix", target, [])
+ engine.set_update_action("common.MkDir", target, [])
# Prepare a Jam 'dirs' target that can be used to make the build only
# construct all the target directories.
@@ -816,62 +819,37 @@ def runtime_tag(name, target_type, prop_set ):
return tag
-## TODO:
-##rule __test__ ( )
-##{
-## import assert ;
-##
-## local nl = "
-##" ;
-##
-## local save-os = [ modules.peek os : .name ] ;
-##
-## modules.poke os : .name : LINUX ;
-##
-## assert.result "PATH=foo:bar:baz$(nl)export PATH$(nl)"
-## : path-variable-setting-command PATH : foo bar baz ;
-##
-## assert.result "PATH=foo:bar:$PATH$(nl)export PATH$(nl)"
-## : prepend-path-variable-command PATH : foo bar ;
-##
-## modules.poke os : .name : NT ;
-##
-## assert.result "set PATH=foo;bar;baz$(nl)"
-## : path-variable-setting-command PATH : foo bar baz ;
-##
-## assert.result "set PATH=foo;bar;%PATH%$(nl)"
-## : prepend-path-variable-command PATH : foo bar ;
-##
-## modules.poke os : .name : $(save-os) ;
-##}
-
def init(manager):
+ global __RM, __CP, __IGNORE, __LN
engine = manager.engine()
- engine.register_action("common.MkDir1-quick-fix-for-unix", 'mkdir -p "$(<)"')
- engine.register_action("common.MkDir1-quick-fix-for-windows", 'if not exist "$(<)\\" mkdir "$(<)"')
-
+ # register the make() and alias() rules globally
import b2.tools.make
import b2.build.alias
- global __RM, __CP, __IGNORE, __LN
+ windows_hack = ''
# ported from trunk@47281
if os_name() == 'NT':
__RM = 'del /f /q'
- __CP = 'copy'
+ __CP = 'copy /b'
+ windows_hack = '+ this-file-does-not-exist-A698EE7806899E69'
__IGNORE = '2>nul >nul & setlocal'
__LN = __CP
#if not __LN:
# __LN = CP
+ MKDIR = 'if not exist "$(<)\\" mkdir "$(<)"'
else:
__RM = 'rm -f'
__CP = 'cp'
__IGNORE = ''
__LN = 'ln'
+ MKDIR = 'mkdir -p "$(<)"'
+
+ engine.register_action("common.MkDir", MKDIR + __IGNORE)
- engine.register_action("common.Clean", __RM + ' "$(>)"',
- flags=['piecemeal', 'together', 'existing'])
- engine.register_action("common.copy", __CP + ' "$(>)" "$(<)"')
+ engine.register_action(
+ "common.Clean", __RM + ' "$(>)"', flags=['piecemeal', 'together', 'existing'])
+ engine.register_action("common.copy", '{} "$(>)" {} "$(<)"'.format(__CP, windows_hack))
engine.register_action("common.RmTemps", __RM + ' "$(>)" ' + __IGNORE,
flags=['quietly', 'updated', 'piecemeal', 'together'])
diff --git a/tools/build/src/tools/darwin.jam b/tools/build/src/tools/darwin.jam
index ceb2c6d3c3..a610603f03 100644
--- a/tools/build/src/tools/darwin.jam
+++ b/tools/build/src/tools/darwin.jam
@@ -223,6 +223,10 @@ local rule init-sdk ( condition * : root ? : version + : version-feature ? )
{
switch $(version[1])
{
+ case appletv* :
+ {
+ return $(version[1])-$(version[2-]:J=.) ;
+ }
case iphone* :
{
return $(version[1])-$(version[2-]:J=.) ;
@@ -265,6 +269,30 @@ local rule init-sdk ( condition * : root ? : version + : version-feature ? )
# Then device variation options.
switch $(version[1])
{
+ case appletvsim* :
+ {
+ local N = $(version[2]) ;
+ if ! $(version[3]) { N += 00 ; }
+ else if [ regex.match (..) : $(version[3]) ] { N += $(version[3]) ; }
+ else { N += 0$(version[3]) ; }
+ if ! $(version[4]) { N += 00 ; }
+ else if [ regex.match (..) : $(version[4]) ] { N += $(version[4]) ; }
+ else { N += 0$(version[4]) ; }
+ N = $(N:J=) ;
+ flags darwin.compile OPTIONS <macosx-version-min>$(version-feature)
+ : -D__IPHONE_OS_VERSION_MIN_REQUIRED=$(N) ;
+ flags darwin.link OPTIONS <macosx-version-min>$(version-feature)
+ : -D__IPHONE_OS_VERSION_MIN_REQUIRED=$(N) ;
+ }
+
+ case appletv* :
+ {
+ flags darwin.compile OPTIONS <macosx-version-min>$(version-feature)
+ : -mtvos-version-min=$(version[2-]:J=.) ;
+ flags darwin.link OPTIONS <macosx-version-min>$(version-feature)
+ : -mtvos-version-min=$(version[2-]:J=.) ;
+ }
+
case iphonesim* :
{
local N = $(version[2]) ;
@@ -280,7 +308,7 @@ local rule init-sdk ( condition * : root ? : version + : version-feature ? )
flags darwin.link OPTIONS <macosx-version-min>$(version-feature)
: -D__IPHONE_OS_VERSION_MIN_REQUIRED=$(N) ;
}
-
+
case iphone* :
{
flags darwin.compile OPTIONS <macosx-version-min>$(version-feature)
@@ -340,7 +368,7 @@ local rule init-available-sdk-versions ( condition * : root ? )
{
root ?= /Developer ;
local sdks-root = $(root)/SDKs ;
- local sdks = [ GLOB $(sdks-root) : MacOSX*.sdk iPhoneOS*.sdk iPhoneSimulator*.sdk ] ;
+ local sdks = [ GLOB $(sdks-root) : MacOSX*.sdk AppleTVOS*.sdk AppleTVSimulator*.sdk iPhoneOS*.sdk iPhoneSimulator*.sdk ] ;
local result ;
for local sdk in $(sdks)
{
@@ -355,6 +383,14 @@ local rule init-available-sdk-versions ( condition * : root ? )
{
sdk-version = mac $(sdk-version) ;
}
+ case appletvos :
+ {
+ sdk-version = appletv $(sdk-version) ;
+ }
+ case appletvsimulator :
+ {
+ sdk-version = appletvsim $(sdk-version) ;
+ }
case iphoneos :
{
sdk-version = iphone $(sdk-version) ;
diff --git a/tools/build/src/tools/doxproc.py b/tools/build/src/tools/doxproc.py
index c41d7fde15..d415133e1f 100644
--- a/tools/build/src/tools/doxproc.py
+++ b/tools/build/src/tools/doxproc.py
@@ -50,7 +50,7 @@ def get_args( argv = sys.argv[1:] ):
( option_pairs, other ) = getopt.getopt( argv, '', spec )
map( lambda x: options.__setitem__( x[0], x[1] ), option_pairs )
- if options.has_key( '--help' ):
+ if '--help' in options:
usage()
sys.exit(1)
@@ -59,7 +59,7 @@ def get_args( argv = sys.argv[1:] ):
'output' : options['--output'],
'id' : options['--id'],
'title' : options['--title'],
- 'index' : options.has_key('--enable-index')
+ 'index' : '--enable-index' in options
}
def if_attribute(node, attribute, true_value, false_value=None):
@@ -151,13 +151,13 @@ class Doxygen2BoostBook:
#~ BoostBook references.
def _rewriteIDs( self, node ):
if node.nodeName in ('link'):
- if (self.idmap.has_key(node.getAttribute('linkend'))):
+ if node.getAttribute('linkend') in self.idmap:
#~ A link, and we have someplace to repoint it at.
node.setAttribute('linkend',self.idmap[node.getAttribute('linkend')])
else:
#~ A link, but we don't have a generated target for it.
node.removeAttribute('linkend')
- elif hasattr(node,'hasAttribute') and node.hasAttribute('id') and self.idmap.has_key(node.getAttribute('id')):
+ elif hasattr(node,'hasAttribute') and node.hasAttribute('id') and node.getAttribute('id') in self.idmap:
#~ Simple ID, and we have a translation.
node.setAttribute('id',self.idmap[node.getAttribute('id')])
#~ Recurse, and iterate, depth-first traversal which turns out to be
@@ -333,7 +333,7 @@ class Doxygen2BoostBook:
'detailed' : self._getChildData('detaileddescription',root=node),
'parsed' : False
}
- if self.symbols.has_key(namespace['name']):
+ if namespace['name'] in self.symbols:
if not self.symbols[namespace['name']]['parsed']:
self.symbols[namespace['name']]['parsed'] = True
#~ for n in node.childNodes:
@@ -385,7 +385,7 @@ class Doxygen2BoostBook:
#~ Translate a <compounddef ...><includes ...>...</includes></compounddef>,
def _translate_compounddef_includes_( self, node, target=None, **kwargs ):
name = node.firstChild.data
- if not self.symbols.has_key(name):
+ if name not in self.symbols:
self._setID(node.getAttribute('refid'),name)
self.symbols[name] = {
'kind' : 'header',
@@ -800,7 +800,7 @@ class Doxygen2BoostBook:
namespace = '::'.join(result['namespace'])
while (
len(result['namespace']) > 0 and (
- not self.symbols.has_key(namespace) or
+ namespace not in self.symbols or
self.symbols[namespace]['kind'] != 'namespace')
):
result['name'] = result['namespace'].pop()+'::'+result['name']
diff --git a/tools/build/src/tools/emscripten.jam b/tools/build/src/tools/emscripten.jam
new file mode 100644
index 0000000000..2ad1b804a5
--- /dev/null
+++ b/tools/build/src/tools/emscripten.jam
@@ -0,0 +1,112 @@
+# Copyright Rene Rivera 2016
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import feature ;
+import os ;
+import toolset ;
+import common ;
+import gcc ;
+import type ;
+
+feature.feature embind : off on : propagated ;
+feature.feature closure : off on full : propagated ;
+feature.feature link-optimization : off on full : propagated ;
+
+rule init ( version ? : command * : options * )
+{
+ command = [ common.get-invocation-command emscripten
+ : emcc
+ : $(command) ] ;
+
+ # Determine the version
+ local command-string = $(command:J=" ") ;
+ if $(command)
+ {
+ version ?= [ MATCH "([0-9.]+)"
+ : [ SHELL "$(command-string) --version" ] ] ;
+ }
+
+ local condition = [ common.check-init-parameters emscripten
+ : version $(version) ] ;
+
+ common.handle-options emscripten : $(condition) : $(command) : $(options) ;
+}
+
+feature.extend toolset : emscripten ;
+
+toolset.inherit-generators emscripten <toolset>emscripten
+ : gcc
+ : gcc.mingw.link gcc.mingw.link.dll gcc.compile.c.pch gcc.compile.c++.pch
+ ;
+toolset.inherit-rules emscripten : gcc ;
+toolset.inherit-flags emscripten : gcc
+ :
+ <optimization>off <optimization>speed <optimization>space
+ <profiling>off <profiling>on
+ <inlining>off <inlining>on <inlining>full
+ <warnings>off <warnings>all <warnings>on
+ <warnings-as-errors>off <warnings-as-errors>on
+ <debug-symbols>off <debug-symbols>on
+ <rtti>off <rtti>on
+ ;
+
+type.set-generated-target-suffix EXE : <toolset>emscripten : "js" ;
+type.set-generated-target-suffix OBJ : <toolset>emscripten : "bc" ;
+type.set-generated-target-suffix STATIC_LIB : <toolset>emscripten : "bc" ;
+
+toolset.flags emscripten.compile OPTIONS <flags> ;
+toolset.flags emscripten.compile OPTIONS <cflags> ;
+toolset.flags emscripten.compile.c++ OPTIONS <cxxflags> ;
+
+toolset.flags emscripten.compile OPTIONS <optimization>off : -O0 ;
+toolset.flags emscripten.compile OPTIONS <optimization>speed : -O3 ;
+toolset.flags emscripten.compile OPTIONS <optimization>space : -Oz ;
+toolset.flags emscripten.link OPTIONS <optimization>off : -O0 ;
+toolset.flags emscripten.link OPTIONS <optimization>speed : -O3 ;
+toolset.flags emscripten.link OPTIONS <optimization>space : -O3 ;
+
+toolset.flags emscripten.compile OPTIONS <profiling>on : --profiling-funcs ;
+
+toolset.flags emscripten.compile OPTIONS <inlining>off : -fno-inline ;
+toolset.flags emscripten.compile OPTIONS <inlining>on : -Wno-inline ;
+toolset.flags emscripten.compile OPTIONS <inlining>full : -Wno-inline ;
+
+toolset.flags emscripten.compile OPTIONS <warnings>off : -w ;
+toolset.flags emscripten.compile OPTIONS <warnings>on : -Wall ;
+toolset.flags emscripten.compile OPTIONS <warnings>all : -Wall -pedantic ;
+toolset.flags emscripten.compile OPTIONS <warnings-as-errors>on : -Werror ;
+
+toolset.flags emscripten OPTIONS <debug-symbols>off : -g0 ;
+toolset.flags emscripten OPTIONS <debug-symbols>on : -g4 -s DEMANGLE_SUPPORT=1 ;
+toolset.flags emscripten OPTIONS <rtti>off : -fno-rtti ;
+
+toolset.flags emscripten.link OPTIONS <embind>on : --bind ;
+toolset.flags emscripten.link OPTIONS <closure>on : --closure 1 ;
+toolset.flags emscripten.link OPTIONS <closure>full : --closure 2 ;
+toolset.flags emscripten.link OPTIONS <link-optimization>off : --llvm-lto 0 ;
+toolset.flags emscripten.link OPTIONS <link-optimization>on : --llvm-lto 1 ;
+toolset.flags emscripten.link OPTIONS <link-optimization>full : --llvm-lto 3 ;
+
+actions compile.c
+{
+ "$(CONFIG_COMMAND)" -x c $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" -x c++ $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions archive
+{
+ "$(CONFIG_COMMAND)" $(AROPTIONS) -o "$(<)" "$(>)"
+}
+
+toolset.flags emscripten.link USER_OPTIONS <linkflags> ;
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(USER_OPTIONS) -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" $(START-GROUP) $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS)
+}
diff --git a/tools/build/src/tools/gcc.py b/tools/build/src/tools/gcc.py
index bc810e489f..270ca97b66 100644
--- a/tools/build/src/tools/gcc.py
+++ b/tools/build/src/tools/gcc.py
@@ -103,11 +103,13 @@ def init(version = None, command = None, options = None):
# The command.
command = to_seq(common.get_invocation_command('gcc', 'g++', command))
# The root directory of the tool install.
- root = feature.get_values('<root>', options) ;
+ root = feature.get_values('<root>', options)
+ root = root[0] if root else ''
# The bin directory where to find the command to execute.
bin = None
# The flavor of compiler.
flavor = feature.get_values('<flavor>', options)
+ flavor = flavor[0] if flavor else ''
# Autodetect the root and bin dir if not given.
if command:
if not bin:
@@ -198,7 +200,7 @@ def init(version = None, command = None, options = None):
# objects, so configure that.
rc_command = common.get_invocation_command('gcc', 'as', [], [bin], path_last=True)
rc_type = 'null'
- rc.configure(rc_command, condition, '<rc-type>' + rc_type)
+ rc.configure([rc_command], condition, ['<rc-type>' + rc_type])
###if [ os.name ] = NT
###{
@@ -209,6 +211,8 @@ def init(version = None, command = None, options = None):
#FIXME: when register_c_compiler is moved to
# generators, these should be updated
+builtin.register_c_compiler('gcc.compile.c++.preprocess', ['CPP'], ['PREPROCESSED_CPP'], ['<toolset>gcc'])
+builtin.register_c_compiler('gcc.compile.c.preprocess', ['C'], ['PREPROCESSED_C'], ['<toolset>gcc'])
builtin.register_c_compiler('gcc.compile.c++', ['CPP'], ['OBJ'], ['<toolset>gcc'])
builtin.register_c_compiler('gcc.compile.c', ['C'], ['OBJ'], ['<toolset>gcc'])
builtin.register_c_compiler('gcc.compile.asm', ['ASM'], ['OBJ'], ['<toolset>gcc'])
@@ -376,6 +380,24 @@ engine.register_action(
function=gcc_compile_c,
bound_list=['PCH_FILE'])
+engine.register_action(
+ 'gcc.compile.c++.preprocess',
+ function=gcc_compile_cpp,
+ bound_list=['PCH_FILE'],
+ command="""
+ $(CONFIG_COMMAND) $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" "$(>:W)" -E >"$(<:W)"
+ """
+)
+
+engine.register_action(
+ 'gcc.compile.c.preprocess',
+ function=gcc_compile_c,
+ bound_list=['PCH_FILE'],
+ command="""
+ $(CONFIG_COMMAND) $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" "$(>)" -E >$(<)
+ """
+)
+
def gcc_compile_asm(targets, sources, properties):
get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp')
diff --git a/tools/build/src/tools/intel-win.jam b/tools/build/src/tools/intel-win.jam
index d501167960..21392e7bf4 100644
--- a/tools/build/src/tools/intel-win.jam
+++ b/tools/build/src/tools/intel-win.jam
@@ -475,6 +475,7 @@ if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
.iclvars-14.0-supported-vcs = "12.0 11.0 10.0 9.0" ;
.iclvars-15.0-supported-vcs = "12.0 11.0 10.0 9.0" ;
.iclvars-16.0-supported-vcs = "14.0 12.0 11.0 10.0 9.0" ;
+.iclvars-17.0-supported-vcs = "14.0 12.0 11.0 10.0" ;
.iclvars-version-alias-vc14 = vs2015 ;
.iclvars-version-alias-vc12 = vs2013 ;
.iclvars-version-alias-vc11 = vs2012 ;
diff --git a/tools/build/src/tools/mc.py b/tools/build/src/tools/mc.py
index 9992c36c19..d8b9701945 100644
--- a/tools/build/src/tools/mc.py
+++ b/tools/build/src/tools/mc.py
@@ -34,7 +34,7 @@ feature('mc-set-customer-bit', ['no', 'yes'], ['free'])
flags('mc.compile', 'MCFLAGS', ['<mc-input-encoding>ansi'], ['-a'])
flags('mc.compile', 'MCFLAGS', ['<mc-input-encoding>unicode'], ['-u'])
-flags('mc.compile', 'MCFLAGS', ['<mc-output-encoding>ansi'], '-A')
+flags('mc.compile', 'MCFLAGS', ['<mc-output-encoding>ansi'], ['-A'])
flags('mc.compile', 'MCFLAGS', ['<mc-output-encoding>unicode'], ['-U'])
flags('mc.compile', 'MCFLAGS', ['<mc-set-customer-bit>no'], [])
flags('mc.compile', 'MCFLAGS', ['<mc-set-customer-bit>yes'], ['-c'])
diff --git a/tools/build/src/tools/message.py b/tools/build/src/tools/message.py
index 5ec3efc768..3f276f93e4 100644
--- a/tools/build/src/tools/message.py
+++ b/tools/build/src/tools/message.py
@@ -15,9 +15,10 @@ from b2.manager import get_manager
class MessageTargetClass(targets.BasicTarget):
- def __init__(self, name, project, *args):
-
- targets.BasicTarget.__init__(self, name, project, [])
+ def __init__(self, name, project, sources, requirements, default_build,
+ usage_requirements, *args):
+ targets.BasicTarget.__init__(
+ self, name, project, sources, requirements, default_build, usage_requirements)
self.args = args
self.built = False
@@ -38,9 +39,16 @@ def message(name, *args):
name = name[0]
t = get_manager().targets()
-
project = get_manager().projects().current()
- return t.main_target_alternative(MessageTargetClass(*((name, project) + args)))
+ return t.main_target_alternative(
+ MessageTargetClass(
+ name, project,
+ t.main_target_sources([], name),
+ t.main_target_requirements([], project),
+ t.main_target_default_build([], project),
+ t.main_target_usage_requirements([], project),
+ *args
+ ))
get_manager().projects().add_rule("message", message)
diff --git a/tools/build/src/tools/mpi.jam b/tools/build/src/tools/mpi.jam
index a161101bc4..1ccc541330 100644
--- a/tools/build/src/tools/mpi.jam
+++ b/tools/build/src/tools/mpi.jam
@@ -3,33 +3,33 @@
# (C) Copyright 2005, 2006 Trustees of Indiana University
# (C) Copyright 2005 Douglas Gregor
#
-# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
#
# Authors: Douglas Gregor
# Andrew Lumsdaine
#
# ==== MPI Configuration ====
-#
-# For many users, MPI support can be enabled simply by adding the following
+#
+# For many users, MPI support can be enabled simply by adding the following
# line to your user-config.jam file:
#
# using mpi ;
#
-# This should auto-detect MPI settings based on the MPI wrapper compiler in
+# This should auto-detect MPI settings based on the MPI wrapper compiler in
# your path, e.g., "mpic++". If the wrapper compiler is not in your path, or
# has a different name, you can pass the name of the wrapper compiler as the
# first argument to the mpi module:
#
# using mpi : /opt/mpich2-1.0.4/bin/mpiCC ;
#
-# If your MPI implementation does not have a wrapper compiler, or the MPI
+# If your MPI implementation does not have a wrapper compiler, or the MPI
# auto-detection code does not work with your MPI's wrapper compiler,
-# you can pass MPI-related options explicitly via the second parameter to the
+# you can pass MPI-related options explicitly via the second parameter to the
# mpi module:
#
# using mpi : : <find-shared-library>lammpio <find-shared-library>lammpi++
-# <find-shared-library>mpi <find-shared-library>lam
+# <find-shared-library>mpi <find-shared-library>lam
# <find-shared-library>dl ;
#
# To see the results of MPI auto-detection, pass "--debug-configuration" on
@@ -41,17 +41,17 @@
# to this to run tests and tell the program to expect the number of
# processors to follow (default: "-np"). With the default parameters,
# for instance, the test harness will execute, e.g.,
-#
+#
# mpirun -np 4 all_gather_test
#
# ==== Linking Against the MPI Libraries ===
#
-# To link against the MPI libraries, import the "mpi" module and add the
+# To link against the MPI libraries, import the "mpi" module and add the
# following requirement to your target:
-#
-# <library>/mpi//mpi
#
-# Since MPI support is not always available, you should check
+# <library>/mpi//mpi
+#
+# Since MPI support is not always available, you should check
# "mpi.configured" before trying to link against the MPI libraries.
import "class" : new ;
@@ -82,7 +82,7 @@ if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
# <name>value rest-of-cmdline
#
# This is a subroutine of cmdline_to_features
-rule add_feature ( prefix name cmdline )
+rule add_feature ( prefix name cmdline )
{
local match = [ MATCH "^$(prefix)([^\" ]+|\"[^\"]+\") *(.*)$" : $(cmdline) ] ;
@@ -142,7 +142,7 @@ rule cmdline_to_features ( cmdline : unknown-features ? )
executable = $(match[1]) ;
cmdline = $(match[2]) ;
- # List the prefix/feature pairs that we will be able to transform.
+ # List the prefix/feature pairs that we will be able to transform.
# Every kind of parameter not mentioned here will be placed in both
# cxxflags and linkflags, because we don't know where they should go.
local feature_kinds-D = "define" ;
@@ -171,13 +171,13 @@ rule cmdline_to_features ( cmdline : unknown-features ? )
# uses -lpthread as opposed to -pthread. We do want to
# set <threading>multi, instead of -lpthread.
result += "<threading>multi" ;
- MPI_EXTRA_REQUIREMENTS += "<threading>multi" ;
+ MPI_EXTRA_REQUIREMENTS += "<threading>multi" ;
}
else
- {
- result += $(add[1]) ;
+ {
+ result += $(add[1]) ;
}
-
+
cmdline = $(add[2]) ;
matched = yes ;
}
@@ -204,7 +204,7 @@ rule cmdline_to_features ( cmdline : unknown-features ? )
# conflicts when BBv2 determines which "common" properties to
# apply to a target. In our case, the <threading>single property
# gets propagated from the common properties to Boost.MPI
- # targets, even though <threading>multi is in the usage
+ # targets, even though <threading>multi is in the usage
# requirements of <library>/mpi//mpi.
MPI_EXTRA_REQUIREMENTS += "<threading>multi" ;
}
@@ -235,63 +235,97 @@ local rule safe-shell-command ( cmdline )
return [ MATCH ".*(SSCOK).*" : $(result) ] ;
}
-# Initialize the MPI module.
+# Initialize the MPI module.
rule init ( mpicxx ? : options * : mpirun-with-options * )
{
if ! $(options) && $(.debug-configuration)
{
ECHO "===============MPI Auto-configuration===============" ;
}
-
+
if ! $(mpicxx) && [ os.on-windows ]
- {
- # Try to auto-configure to the Microsoft Compute Cluster Pack
+ {
+ # Paths for Microsoft MPI
+ local ms_mpi_path_native = "C:\\Program Files\\Microsoft MPI" ;
+ local ms_mpi_sdk_path_native = "C:\\Program Files (x86)\\Microsoft SDKs\\MPI" ;
+
+ # Path for Microsoft Compute Cluster Pack
local cluster_pack_path_native = "C:\\Program Files\\Microsoft Compute Cluster Pack" ;
- local cluster_pack_path = [ path.make $(cluster_pack_path_native) ] ;
- if [ GLOB $(cluster_pack_path_native)\\Include : mpi.h ]
+
+ # Try to auto-configure Microsoft MPI
+ if [ GLOB $(ms_mpi_path_native)\\Bin : mpiexec.exe ] &&
+ [ GLOB $(ms_mpi_sdk_path_native)\\Include : mpi.h ]
+ {
+ if $(.debug-configuration)
+ {
+ ECHO "Found Microsoft MPI: $(ms_mpi_path_native)" ;
+ ECHO "Found Microsoft MPI SDK: $(ms_mpi_sdk_path_native)" ;
+ }
+
+ local ms_mpi_sdk_path = [ path.make $(ms_mpi_sdk_path_native) ] ;
+
+ # Pick up either the 32-bit or 64-bit library, depending on which address
+ # model the user has selected. Default to 32-bit.
+ options = <include>$(ms_mpi_sdk_path)/Include
+ <address-model>64:<library-path>$(ms_mpi_sdk_path)/Lib/x64
+ <library-path>$(ms_mpi_sdk_path)/Lib/x86
+ <find-static-library>msmpi
+ <toolset>msvc:<define>_SECURE_SCL=0
+ ;
+
+ # Setup the "mpirun" equivalent (mpiexec)
+ .mpirun = "\"$(ms_mpi_path_native)\\Bin\\mpiexec.exe"\" ;
+ .mpirun_flags = -n ;
+ }
+ # Try to auto-configure to the Microsoft Compute Cluster Pack
+ else if [ GLOB $(cluster_pack_path_native)\\Include : mpi.h ]
{
if $(.debug-configuration)
{
ECHO "Found Microsoft Compute Cluster Pack: $(cluster_pack_path_native)" ;
}
-
+
+ local cluster_pack_path = [ path.make $(cluster_pack_path_native) ] ;
+
# Pick up either the 32-bit or 64-bit library, depending on which address
# model the user has selected. Default to 32-bit.
- options = <include>$(cluster_pack_path)/Include
+ options = <include>$(cluster_pack_path)/Include
<address-model>64:<library-path>$(cluster_pack_path)/Lib/amd64
<library-path>$(cluster_pack_path)/Lib/i386
<find-static-library>msmpi
<toolset>msvc:<define>_SECURE_SCL=0
;
-
+
# Setup the "mpirun" equivalent (mpiexec)
.mpirun = "\"$(cluster_pack_path_native)\\Bin\\mpiexec.exe"\" ;
.mpirun_flags = -n ;
}
else if $(.debug-configuration)
{
+ ECHO "Did not find Microsoft MPI in $(ms_mpi_path_native)" ;
+ ECHO " and/or Microsoft MPI SDK in $(ms_mpi_sdk_path_native)." ;
ECHO "Did not find Microsoft Compute Cluster Pack in $(cluster_pack_path_native)." ;
}
- }
-
+ }
+
if ! $(options)
- {
+ {
# Try to auto-detect options based on the wrapper compiler
local command = [ common.get-invocation-command mpi : mpic++ : $(mpicxx) ] ;
- if ! $(mpicxx) && ! $(command)
+ if ! $(mpicxx) && ! $(command)
{
- # Try "mpiCC", which is used by MPICH
+ # Try "mpiCC", which is used by MPICH
command = [ common.get-invocation-command mpi : mpiCC ] ;
}
- if ! $(mpicxx) && ! $(command)
+ if ! $(mpicxx) && ! $(command)
{
# Try "mpicxx", which is used by OpenMPI and MPICH2
command = [ common.get-invocation-command mpi : mpicxx ] ;
}
- if ! $(mpicxx) && ! $(command)
+ if ! $(mpicxx) && ! $(command)
{
# Try "CC", which is used by Cray
command = [ common.get-invocation-command mpi : CC ] ;
@@ -302,10 +336,10 @@ rule init ( mpicxx ? : options * : mpirun-with-options * )
local link_flags ;
if ! $(command)
- {
+ {
# Do nothing: we'll complain later
}
- # OpenMPI and newer versions of LAM-MPI have -showme:compile and
+ # OpenMPI and newer versions of LAM-MPI have -showme:compile and
# -showme:link.
else if [ safe-shell-command "$(command) -showme:compile" ] &&
[ safe-shell-command "$(command) -showme:link" ]
@@ -317,8 +351,8 @@ rule init ( mpicxx ? : options * : mpirun-with-options * )
compile_flags = [ SHELL "$(command) -showme:compile" ] ;
link_flags = [ SHELL "$(command) -showme:link" ] ;
-
- # Prepend COMPILER as the executable name, to match the format of
+
+ # Prepend COMPILER as the executable name, to match the format of
# other compilation commands.
compile_flags = "COMPILER $(compile_flags) -DOMPI_SKIP_MPICXX " ;
link_flags = "COMPILER $(link_flags)" ;
@@ -379,7 +413,7 @@ rule init ( mpicxx ? : options * : mpirun-with-options * )
ECHO "Found IBM MPI wrapper compiler: $(command)" ;
}
- #
+ #
compile_flags = [ SHELL "$(command) -c -v 2>/dev/null" ] ;
compile_flags = [ MATCH "(.*)exec: export.*" : $(compile_flags) ] ;
local front = [ MATCH "(.*)-v" : $(compile_flags) ] ;
@@ -402,7 +436,7 @@ rule init ( mpicxx ? : options * : mpirun-with-options * )
compile_flags = "$(compile_flags) $(f_flags)" ;
}
}
- # Cray
+ # Cray
else if [ safe-shell-command "$(command) -v" ]
{
compile_flags = [ safe-shell-command "$(command) -###" ] ;
@@ -411,8 +445,8 @@ rule init ( mpicxx ? : options * : mpirun-with-options * )
# ECHO "Noel: link_flags: $(link_flags)" ;
result = " " ;
}
-
- # Prepend COMPILER as the executable name, to match the format of
+
+ # Prepend COMPILER as the executable name, to match the format of
if $(result) || $(compile_flags) && $(link_flags)
{
@@ -421,17 +455,17 @@ rule init ( mpicxx ? : options * : mpirun-with-options * )
result = [ strip-eol $(result) ] ;
options = [ cmdline_to_features $(result) ] ;
}
- else
- {
+ else
+ {
compile_flags = [ strip-eol $(compile_flags) ] ;
link_flags = [ strip-eol $(link_flags) ] ;
# Separately process compilation and link features, then combine
# them at the end.
- local compile_features = [ cmdline_to_features $(compile_flags)
- : "<cxxflags>" ] ;
- local link_features = [ cmdline_to_features $(link_flags)
- : "<linkflags>" ] ;
+ local compile_features = [ cmdline_to_features $(compile_flags)
+ : "<cxxflags>" ] ;
+ local link_features = [ cmdline_to_features $(link_flags)
+ : "<linkflags>" ] ;
options = $(compile_features) $(link_features) ;
}
@@ -444,44 +478,44 @@ rule init ( mpicxx ? : options * : mpirun-with-options * )
}
else
{
- local match = [ MATCH "^([^\" ]+|\"[^\"]+\") *(.*)$"
+ local match = [ MATCH "^([^\" ]+|\"[^\"]+\") *(.*)$"
: $(compile_flags) ] ;
ECHO "MPI compilation flags: $(match[2])" ;
- local match = [ MATCH "^([^\" ]+|\"[^\"]+\") *(.*)$"
+ local match = [ MATCH "^([^\" ]+|\"[^\"]+\") *(.*)$"
: $(link_flags) ] ;
ECHO "MPI link flags: $(match[2])" ;
}
}
- }
- else
+ }
+ else
{
if $(command)
{
ECHO "MPI auto-detection failed: unknown wrapper compiler $(command)" ;
ECHO "Please report this error to the Boost mailing list: http://www.boost.org" ;
- }
+ }
else if $(mpicxx)
{
ECHO "MPI auto-detection failed: unable to find wrapper compiler $(mpicxx)" ;
- }
+ }
else
{
ECHO "MPI auto-detection failed: unable to find wrapper compiler `mpic++' or `mpiCC'" ;
}
ECHO "You will need to manually configure MPI support." ;
}
-
+
}
# Find mpirun (or its equivalent) and its flags
if ! $(.mpirun)
{
- .mpirun =
+ .mpirun =
[ common.get-invocation-command mpi : mpirun : $(mpirun-with-options[1]) ] ;
.mpirun_flags = $(mpirun-with-options[2-]) ;
.mpirun_flags ?= -np ;
}
-
+
if $(.debug-configuration)
{
if $(options)
@@ -494,15 +528,15 @@ rule init ( mpicxx ? : options * : mpirun-with-options * )
{
echo "MPI launcher: $(.mpirun) $(.mpirun_flags)" ;
}
-
+
ECHO "====================================================" ;
}
- if $(options)
+ if $(options)
{
.configured = true ;
- # Set up the "mpi" alias
+ # Set up the "mpi" alias
alias mpi : : : : $(options) ;
}
}
@@ -537,21 +571,21 @@ class mpi-test-generator : generator
}
rule run ( project name ? : property-set : sources * : multiple ? )
- {
+ {
# Generate an executable from the sources. This is the executable we will run.
- local executable =
+ local executable =
[ generators.construct $(project) $(name) : EXE : $(property-set) : $(sources) ] ;
- result =
+ result =
[ construct-result $(executable[2-]) : $(project) $(name)-run : $(property-set) ] ;
}
}
# Use mpi-test-generator to generate MPI tests from sources
-generators.register
+generators.register
[ new mpi-test-generator mpi.capture-output : : RUN_MPI_OUTPUT ] ;
-generators.register-standard testing.expect-success
+generators.register-standard testing.expect-success
: RUN_MPI_OUTPUT : RUN_MPI ;
# The number of processes to spawn when executing an MPI test.
@@ -574,25 +608,25 @@ rule capture-output ( target : sources * : properties * )
JAM_SEMAPHORE on $(target) = <s>mpi-run-semaphore ;
# We launch MPI processes using the "mpirun" equivalent specified by the user.
- LAUNCHER on $(target) =
+ LAUNCHER on $(target) =
[ on $(target) return $(.mpirun) $(.mpirun_flags) $(num_processes) ] ;
}
-# Creates a set of test cases to be run through the MPI launcher. The name, sources,
-# and requirements are the same as for any other test generator. However, schedule is
-# a list of numbers, which indicates how many processes each test run will use. For
+# Creates a set of test cases to be run through the MPI launcher. The name, sources,
+# and requirements are the same as for any other test generator. However, schedule is
+# a list of numbers, which indicates how many processes each test run will use. For
# example, passing 1 2 7 will run the test with 1 process, then 2 processes, then 7
-# 7 processes. The name provided is just the base name: the actual tests will be
-# the name followed by a hypen, then the number of processes.
+# 7 processes. The name provided is just the base name: the actual tests will be
+# the name followed by a hypen, then the number of processes.
rule mpi-test ( name : sources * : requirements * : schedule * )
-{
+{
sources ?= $(name).cpp ;
schedule ?= 1 2 3 4 7 8 13 17 ;
local result ;
for processes in $(schedule)
- {
- result += [ testing.make-test
+ {
+ result += [ testing.make-test
run-mpi : $(sources) /boost/mpi//boost_mpi
: $(requirements) <toolset>msvc:<link>static <mpi:processes>$(processes) : $(name)-$(processes) ] ;
}
diff --git a/tools/build/src/tools/msvc.jam b/tools/build/src/tools/msvc.jam
index 78e64e6849..3f8f49e68b 100644
--- a/tools/build/src/tools/msvc.jam
+++ b/tools/build/src/tools/msvc.jam
@@ -907,7 +907,11 @@ local rule configure-really ( version ? : options * )
# version from the path.
# FIXME: We currently detect both Microsoft Visual Studio 9.0 and
# 9.0express as 9.0 here.
- if [ MATCH "(Microsoft Visual Studio 14)" : $(command) ]
+ if [ MATCH "(Microsoft Visual Studio 15)" : $(command) ]
+ {
+ version = 15.0 ;
+ }
+ else if [ MATCH "(Microsoft Visual Studio 14)" : $(command) ]
{
version = 14.0 ;
}
@@ -1591,7 +1595,7 @@ if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
armv7 armv7s ;
# Known toolset versions, in order of preference.
-.known-versions = 14.0 12.0 11.0 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1
+.known-versions = 15.0 14.0 12.0 11.0 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1
7.1toolkit 7.0 6.0 ;
# Version aliases.
@@ -1604,6 +1608,7 @@ if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
.version-alias-11 = 11.0 ;
.version-alias-12 = 12.0 ;
.version-alias-14 = 14.0 ;
+.version-alias-15 = 15.0 ;
# Names of registry keys containing the Visual C++ installation path (relative
# to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
@@ -1619,6 +1624,7 @@ if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
.version-11.0-reg = "VisualStudio\\11.0\\Setup\\VC" ;
.version-12.0-reg = "VisualStudio\\12.0\\Setup\\VC" ;
.version-14.0-reg = "VisualStudio\\14.0\\Setup\\VC" ;
+.version-15.0-reg = "VisualStudio\\15.0\\Setup\\VC" ;
# Visual C++ Toolkit 2003 does not store its installation path in the registry.
# The environment variable 'VCToolkitInstallDir' and the default installation
diff --git a/tools/build/src/tools/msvc.py b/tools/build/src/tools/msvc.py
index 8cdc273e0e..baa57e8311 100644
--- a/tools/build/src/tools/msvc.py
+++ b/tools/build/src/tools/msvc.py
@@ -344,7 +344,7 @@ class SetupAction:
def register_setup_action(action_name,setup_function,function=None):
global engine
- if engine.actions.has_key(action_name):
+ if action_name in engine.actions:
raise "Bjam action %s is already defined" % action_name
engine.actions[action_name] = SetupAction(setup_function, function)
@@ -380,12 +380,12 @@ def setup_preprocess_c_cpp_action(targets, sources, properties):
return 'preprocess-c-c++'
register_setup_action(
- 'msvc.preprocess.c',
+ 'msvc.compile.c.preprocess',
setup_preprocess_c_cpp_action,
function=compile_c_preprocess)
register_setup_action(
- 'msvc.preprocess.c++',
+ 'msvc.compile.c++.preprocess',
setup_preprocess_c_cpp_action,
function=compile_cpp_preprocess)
@@ -623,6 +623,102 @@ def auto_detect_toolset_versions():
register_configuration(i,default_path(i))
+def maybe_rewrite_setup(toolset, setup_script, setup_options, version, rewrite_setup='off'):
+ """
+ Helper rule to generate a faster alternative to MSVC setup scripts.
+
+ We used to call MSVC setup scripts directly in every action, however in
+ newer MSVC versions (10.0+) they make long-lasting registry queries
+ which have a significant impact on build time.
+ """
+ result = '"{}" {}'.format(setup_script, setup_options)
+
+ # At the moment we only know how to rewrite scripts with cmd shell.
+ if os.name == 'nt' and rewrite_setup != 'off':
+ basename = os.path.basename(setup_script)
+ filename, _ = os.path.splitext(basename)
+ setup_script_id = 'b2_{}_{}_{}'.format(toolset, version, filename)
+ if setup_options:
+ setup_script_id = '{}_{}'.format(setup_script_id, setup_options)
+
+ tempdir = os.environ.get('TEMP')
+ replacement = os.path.join(tempdir, setup_script_id + '.cmd')
+ if rewrite_setup == 'always' or not os.path.exists(replacement):
+ import subprocess
+ # call the setup script and print the environment after doing so
+ p = subprocess.Popen([
+ setup_script, setup_options, '>', 'nul', '&&', 'set',
+ ], stdout=subprocess.PIPE, shell=True
+ )
+ stdout, _ = p.communicate()
+
+ diff_vars = []
+ for var in stdout.splitlines():
+ # returns a tuple of ('var-name', '=', 'value').
+ # partition is being used here (over something like .split())
+ # for two reasons:
+ # 1) an environment variable may have a value that contains an '=';
+ # .partition() will still return the correct key and value pair.
+ # 2) if the line doesn't contain an '=' at all, then the returned
+ # tuple will contain only empty strings rather than raising
+ # an exception.
+ key, _, value = var.partition('=')
+ # os.environ handles casing differences here. Usually the
+ # call to "set" above will produce pascal-cased environment
+ # variable names, so a normal python dict can't be used here.
+ # check for the existence of key in case the partitioning() above
+ # returned an empty key value pair.
+ if key and os.environ.get(key) != value:
+ diff_vars.append('SET {}={}'.format(key, value))
+
+ if diff_vars:
+ with open(replacement, 'wb') as f:
+ f.write(os.linesep.join(diff_vars))
+
+ result = '"{}"'.format(replacement)
+ else:
+ result = '"{}"'.format(replacement)
+
+ return result
+
+
+def generate_setup_cmd(version, command, parent, options, cpu, global_setup,
+ default_global_setup_options, default_setup):
+ setup_prefix = "call "
+ setup_suffix = """ >nul\n"""
+ if on_cygwin():
+ setup_prefix = "cmd.exe /S /C call "
+ setup_suffix = " \">nul\" \"&&\" "
+
+ setup_options = ''
+ setup_cpu = feature.get_values('<setup-{}>'.format(cpu), options)
+
+ if not setup_cpu:
+ if global_setup:
+ setup_cpu = global_setup
+ # If needed we can easily add using configuration flags
+ # here for overriding which options get passed to the
+ # global setup command for which target platform:
+ # setup_options = feature.get_values('<setup-options-{}>'.format(cpu),options)
+ if not setup_options:
+ setup_options = default_global_setup_options[cpu]
+ else:
+ setup_cpu = locate_default_setup(command, parent, default_setup[cpu])
+ else:
+ setup_cpu = setup_cpu[0]
+
+ # Cygwin to Windows path translation.
+ # setup-$(c) = "\""$(setup-$(c):W)"\"" ;
+
+ # Append setup options to the setup name and add the final setup
+ # prefix & suffix.
+ rewrite = feature.get_values('<rewrite-setup-scripts>', options)
+ rewrite = rewrite[0] if rewrite else ''
+ setup = maybe_rewrite_setup(
+ 'msvc', setup_cpu, setup_options, version, rewrite)
+ return '{}{}{}'.format(setup_prefix, setup, setup_suffix)
+
+
# Worker rule for toolset version configuration. Takes an explicit version id or
# nothing in case it should configure the default toolset version (the first
# registered one or a new 'default' one in case no toolset versions have been
@@ -676,7 +772,9 @@ def configure_really(version=None, options=[]):
# version from the path.
# FIXME: We currently detect both Microsoft Visual Studio 9.0 and
# 9.0express as 9.0 here.
- if re.search("Microsoft Visual Studio 14", command):
+ if re.search("Microsoft Visual Studio 15", command):
+ version = '15.0'
+ elif re.search("Microsoft Visual Studio 14", command):
version = '14.0'
elif re.search("Microsoft Visual Studio 12", command):
version = '12.0'
@@ -785,39 +883,15 @@ def configure_really(version=None, options=[]):
elif somehow_detect_the_itanium_platform:
default_global_setup_options[ 'ia64' ] = 'ia64'
- setup_prefix = "call "
- setup_suffix = """ >nul\n"""
- if on_cygwin():
- setup_prefix = "cmd.exe /S /C call "
- setup_suffix = " \">nul\" \"&&\" "
-
for c in cpu:
- setup_options = None
- setup_cpu = feature.get_values('<setup-{}>'.format(c),options)
-
- if not setup_cpu:
- if global_setup:
- setup_cpu = global_setup
- # If needed we can easily add using configuration flags
- # here for overriding which options get passed to the
- # global setup command for which target platform:
- # setup_options = feature.get_values('<setup-options-{}>'.format(c),options)
- if not setup_options:
- setup_options = default_global_setup_options[ c ]
- else:
- setup_cpu = locate_default_setup(command, parent, default_setup[ c ])
-
- # Cygwin to Windows path translation.
- # setup-$(c) = "\""$(setup-$(c):W)"\"" ;
-
- # Append setup options to the setup name and add the final setup
- # prefix & suffix.
- setup_scripts[ c ] = '{}"{}" {}{}'.format(setup_prefix, setup_cpu, setup_options, setup_suffix)
+ setup_scripts[c] = generate_setup_cmd(
+ version, command, parent, options, c, global_setup,
+ default_global_setup_options, default_setup
+ )
# Get tool names (if any) and finish setup.
compiler = feature.get_values("<compiler>", options)
- if not compiler:
- compiler = "cl"
+ compiler = compiler[0] if compiler else 'cl'
linker = feature.get_values("<linker>", options)
if not linker:
@@ -965,7 +1039,7 @@ def register_toolset_really():
feature.extend('toolset', ['msvc'])
# Intel and msvc supposedly have link-compatible objects.
- feature.subfeature( 'toolset', 'msvc', 'vendor', 'intel', ['propagated', 'optional'])
+ feature.subfeature( 'toolset', 'msvc', 'vendor', ['intel'], ['propagated', 'optional'])
# Inherit MIDL flags.
toolset.inherit_flags('msvc', 'midl')
@@ -1191,7 +1265,7 @@ __cpu_type_itanium2 = ['itanium2', 'mckinley']
# Known toolset versions, in order of preference.
-_known_versions = ['14.0', '12.0', '11.0', '10.0', '10.0express', '9.0', '9.0express', '8.0', '8.0express', '7.1', '7.1toolkit', '7.0', '6.0']
+_known_versions = ['15.0', '14.0', '12.0', '11.0', '10.0', '10.0express', '9.0', '9.0express', '8.0', '8.0express', '7.1', '7.1toolkit', '7.0', '6.0']
# Version aliases.
__version_alias_6 = '6.0'
@@ -1203,6 +1277,7 @@ __version_alias_10 = '10.0'
__version_alias_11 = '11.0'
__version_alias_12 = '12.0'
__version_alias_14 = '14.0'
+__version_alias_15 = '15.0'
# Names of registry keys containing the Visual C++ installation path (relative
# to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
@@ -1218,6 +1293,7 @@ __version_10_0express_reg = "VCExpress\\10.0\\Setup\\VC"
__version_11_0_reg = "VisualStudio\\11.0\\Setup\\VC"
__version_12_0_reg = "VisualStudio\\12.0\\Setup\\VC"
__version_14_0_reg = "VisualStudio\\14.0\\Setup\\VC"
+__version_15_0_reg = "VisualStudio\\15.0\\Setup\\VC"
# Visual C++ Toolkit 2003 does not store its installation path in the registry.
# The environment variable 'VCToolkitInstallDir' and the default installation
diff --git a/tools/build/src/tools/python.jam b/tools/build/src/tools/python.jam
index 506e533f8e..cc13385cac 100644
--- a/tools/build/src/tools/python.jam
+++ b/tools/build/src/tools/python.jam
@@ -797,13 +797,11 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
}
}
- # Anything left to compute?
+ # Check whether configuration succeeded.
if ! ( $(includes) && $(libraries) )
{
- version ?= $(fallback-version) ;
- version ?= 2.5 ;
- exec-prefix ?= $(prefix) ;
- compute-default-paths $(target-os) : $(version) : $(prefix:E=) ;
+ debug-message Python headers and libraries not found. ;
+ return ;
}
.configured = true ;
@@ -832,6 +830,27 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
}
#
+ # Discover the presence of NumPy
+ #
+ debug-message "Checking for NumPy..." ;
+ local full-cmd = "import sys; sys.stderr = sys.stdout; import numpy; print(numpy.get_include())" ;
+ local full-cmd = $(interpreter-cmd)" -c \"$(full-cmd)\"" ;
+ debug-message "running command '$(full-cmd)'" ;
+ local result = [ SHELL $(full-cmd) : strip-eol : exit-status ] ;
+ if $(result[2]) = 0
+ {
+ .numpy = true ;
+ .numpy-include = $(result[1]) ;
+ debug-message "NumPy enabled" ;
+ }
+ else
+ {
+ debug-message "NumPy disabled. Reason:" ;
+ debug-message " $(full-cmd) aborted with " ;
+ debug-message " $(result[1])" ;
+ }
+
+ #
# End autoconfiguration sequence.
#
local target-requirements = $(condition) ;
@@ -915,6 +934,19 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
toolset.add-requirements <target-os>$(target-os):<python>$(version:E=default) ;
}
+ # We also set a default requirement that assigns the first python configured
+ # for a particular target OS as the default. This makes it so that we can
+ # select a python interpreter with only knowledge of the target OS. And hence
+ # can configure different Pythons based on the target OS only.
+ local toolset-requirements = [ toolset.requirements ] ;
+ local toolset-target-os-requirements
+ = [ property.evaluate-conditionals-in-context
+ [ $(toolset-requirements).raw ] : <target-os>$(target-os) ] ;
+ if ! <python> in $(toolset-target-os-requirements:G)
+ {
+ toolset.add-requirements <target-os>$(target-os):<python>$(version:E=default) ;
+ }
+
# Register the right suffix for extensions.
register-extension-suffix $(extension-suffix) : $(target-requirements) ;
@@ -1014,6 +1046,16 @@ rule configured ( )
return $(.configured) ;
}
+rule numpy ( )
+{
+ return $(.numpy) ;
+}
+
+rule numpy-include ( )
+{
+ return $(.numpy-include) ;
+}
+
type.register PYTHON_EXTENSION : : SHARED_LIB ;
@@ -1069,19 +1111,6 @@ rule python-extension ( name : sources * : requirements * : default-build * :
IMPORT python : python-extension : : python-extension ;
-rule py2to3
-{
- common.copy $(<) : $(>) ;
- 2to3 $(<) ;
-}
-
-actions 2to3
-{
- 2to3 -wn --no-diffs "$(<)"
- 2to3 -dwn --no-diffs "$(<)"
-}
-
-
# Support for testing.
type.register PY : py ;
type.register RUN_PYD_OUTPUT ;
@@ -1104,22 +1133,6 @@ class python-test-generator : generator
local python ;
local other-pythons ;
- # Make new target that converting Python source by 2to3 when running with Python 3.
- local rule make-2to3-source ( source )
- {
- if $(pyversion) >= 3.0
- {
- local a = [ new action $(source) : python.py2to3 : $(property-set) ] ;
- local t = [ utility.basename [ $(s).name ] ] ;
- local p = [ new file-target $(t) : PY : $(project) : $(a) ] ;
- return $(p) ;
- }
- else
- {
- return $(source) ;
- }
- }
-
for local s in $(sources)
{
if [ $(s).type ] = PY
@@ -1127,13 +1140,13 @@ class python-test-generator : generator
if ! $(python)
{
# First Python source ends up on command line.
- python = [ make-2to3-source $(s) ] ;
+ python = $(s) ;
}
else
{
# Other Python sources become dependencies.
- other-pythons += [ make-2to3-source $(s) ] ;
+ other-pythons += $(s) ;
}
}
}
@@ -1223,7 +1236,7 @@ local rule pyd-pythonpath ( source )
# The flag settings on testing.capture-output do not apply to python.capture
# output at the moment. Redo this explicitly.
toolset.flags python.capture-output ARGS <testing.arg> ;
-
+toolset.flags python.capture-output INPUT_FILES <testing.input-file> ;
rule capture-output ( target : sources * : properties * )
{
@@ -1270,5 +1283,20 @@ rule bpl-test ( name : sources * : requirements * )
: $(requirements) : $(name) ] ;
}
+# The same as bpl-test but additionally require (and link to) boost_numpy.
+# Masked whenever NumPy is not enabled.
+rule numpy-test ( name : sources * : requirements * )
+{
+ numpy-include = [ python.numpy-include ] ;
+ # yuk !
+ if ! $(.numpy) { requirements += <build>no ; }
+ sources ?= $(name).py $(name).cpp ;
+ name = [ regex.replace $(name) "[/]" "~" ] ;
+ return [ testing.make-test run-pyd
+ : $(sources) /boost/python//boost_numpy /boost/python//boost_python
+ : $(requirements) <include>$(numpy-include)
+ : $(name) ] ;
+}
IMPORT $(__name__) : bpl-test : : bpl-test ;
+IMPORT $(__name__) : numpy-test : : numpy-test ;
diff --git a/tools/build/src/tools/rc.py b/tools/build/src/tools/rc.py
index 5bdebb9be2..c7a02dbb6b 100644
--- a/tools/build/src/tools/rc.py
+++ b/tools/build/src/tools/rc.py
@@ -68,7 +68,7 @@ def configure (command = None, condition = None, options = None):
if command and condition and rc_type:
flags('rc.compile.resource', '.RC', condition, command)
- flags('rc.compile.resource', '.RC_TYPE', condition, rc_type.lower())
+ flags('rc.compile.resource', '.RC_TYPE', condition, [rc_type.lower()])
flags('rc.compile.resource', 'DEFINES', [], ['<define>'])
flags('rc.compile.resource', 'INCLUDES', [], ['<include>'])
if debug():
@@ -91,12 +91,13 @@ class RCAction:
# FIXME: What is the proper way to dispatch actions?
def rc_register_action(action_name, function = None):
global engine
- if engine.actions.has_key(action_name):
+ if action_name in engine.actions:
raise AlreadyDefined("Bjam action %s is already defined" % action_name)
engine.actions[action_name] = RCAction(action_name, function)
def rc_compile_resource(targets, sources, properties):
rc_type = bjam.call('get-target-variable', targets, '.RC_TYPE')
+ rc_type = rc_type[0] if rc_type else ''
global engine
engine.set_update_action('rc.compile.resource.' + rc_type, targets, sources, properties)
diff --git a/tools/build/src/tools/stage.py b/tools/build/src/tools/stage.py
index 76b10f65a6..2a15dd18a7 100644
--- a/tools/build/src/tools/stage.py
+++ b/tools/build/src/tools/stage.py
@@ -60,7 +60,7 @@ class InstallTargetClass(targets.BasicTarget):
# properties.
if build_ps.get('hardcode-dll-paths') != ['true']:
- properties = [p for p in properties if p.feature().name() != 'dll-path']
+ properties = [p for p in properties if p.feature.name != 'dll-path']
# If any <dll-path> properties were specified for installing, add
# them.
@@ -75,7 +75,7 @@ class InstallTargetClass(targets.BasicTarget):
# sources, then we shall get virtual targets with the <location>
# property set.
properties = [p for p in properties
- if not p.feature().name() in ['tag', 'location']]
+ if not p.feature.name in ['tag', 'location']]
properties.extend(build_ps.get_properties('dependency'))
@@ -90,7 +90,7 @@ class InstallTargetClass(targets.BasicTarget):
# making the path absolute will help.
if d:
p = d[0]
- properties.append(property.Property(p.feature(), os.path.abspath(p.value())))
+ properties.append(property.Property(p.feature, os.path.abspath(p.value)))
return property_set.create(properties)
@@ -180,8 +180,8 @@ class InstallTargetClass(targets.BasicTarget):
for r in result:
if isinstance(r, property.Property):
- if r.feature().name() != 'use':
- result2.append(r.value())
+ if r.feature.name != 'use':
+ result2.append(r.value)
else:
result2.append(r)
result2 = unique(result2)
diff --git a/tools/build/src/tools/testing-aux.jam b/tools/build/src/tools/testing-aux.jam
index a264e4c35f..30309fbb8f 100644
--- a/tools/build/src/tools/testing-aux.jam
+++ b/tools/build/src/tools/testing-aux.jam
@@ -1,3 +1,5 @@
+import feature ;
+
# This module is imported by testing.py. The definitions here are
# too tricky to do in Python
diff --git a/tools/build/src/tools/testing.jam b/tools/build/src/tools/testing.jam
index 7fbb692a19..0f6359d200 100644
--- a/tools/build/src/tools/testing.jam
+++ b/tools/build/src/tools/testing.jam
@@ -750,20 +750,37 @@ generators.register-composing testing.time : : TIME ;
# there are multiple actions operating on the same target in sequence. One such
# example are msvc exe targets first created by a linker action and then updated
# with an embedded manifest file by a separate action.
-rule record-time ( target : source : start end user system )
+rule record-time ( target : source : start end user system clock )
{
local src-string = [$(source:G=:J=",")"] " ;
USER_TIME on $(target) += $(src-string)$(user) ;
SYSTEM_TIME on $(target) += $(src-string)$(system) ;
+ CLOCK_TIME on $(target) += $(src-string)$(clock) ;
# We need the following variables because attempting to perform such
# variable expansion in actions would not work due to quotes getting treated
# as regular characters.
USER_TIME_SECONDS on $(target) += $(src-string)$(user)" seconds" ;
SYSTEM_TIME_SECONDS on $(target) += $(src-string)$(system)" seconds" ;
+ CLOCK_TIME_SECONDS on $(target) += $(src-string)$(clock)" seconds" ;
}
+# Support for generating timing information for any main target. To use
+# declare a custom make target that uses the testing.time generator rule
+# specified here. For example:
+#
+# make main.cpp : main_cpp.pro : @do-something ;
+# time main.time : main.cpp ;
+# actions do-something
+# {
+# sleep 2 && echo "$(<)" > "$(<)"
+# }
+#
+# The above will generate a "main.time", and echo to output, timing
+# information for the action of source "main.cpp".
+
+
IMPORT testing : record-time : : testing.record-time ;
@@ -774,7 +791,14 @@ IMPORT testing : record-time : : testing.record-time ;
rule time ( target : sources + : properties * )
{
# Set up rule for recording timing information.
- __TIMING_RULE__ on $(sources) = testing.record-time $(target) ;
+ local action = [ on $(target) return $(.action) ] ;
+ for local action.source in [ $(action).sources ]
+ {
+ # Yes, this uses the private "actual-name" of the target action.
+ # But it's the only way to get at the real name of the sources
+ # given the context of header scanners.
+ __TIMING_RULE__ on [ $(action.source).actual-name ] = testing.record-time $(target) ;
+ }
# Make sure the sources get rebuilt any time we need to retrieve that
# information.
@@ -786,9 +810,11 @@ actions time
{
echo user: $(USER_TIME)
echo system: $(SYSTEM_TIME)
+ echo clock: $(CLOCK_TIME)
echo user: $(USER_TIME_SECONDS) > "$(<)"
echo system: $(SYSTEM_TIME_SECONDS) >> "$(<)"
+ echo clock: $(CLOCK_TIME_SECONDS) >> "$(<)"
}
if [ os.name ] = VMS
@@ -797,8 +823,10 @@ if [ os.name ] = VMS
{
WRITE SYS$OUTPUT "user: ", "$(USER_TIME)"
WRITE SYS$OUTPUT "system: ", "(SYSTEM_TIME)"
+ WRITE SYS$OUTPUT "clock: ", "(CLOCK_TIME)"
PIPE WRITE SYS$OUTPUT "user: ", "$(USER_TIME_SECONDS)" | TYPE SYS$INPUT /OUT=$(<:W)
PIPE WRITE SYS$OUTPUT "system: ", "$(SYSTEM_TIME_SECONDS)" | APPEND /NEW SYS$INPUT $(<:W)
+ PIPE WRITE SYS$OUTPUT "clock: ", "$(CLOCK_TIME_SECONDS)" | APPEND /NEW SYS$INPUT $(<:W)
}
}
diff --git a/tools/build/src/tools/testing.py b/tools/build/src/tools/testing.py
index 868905a05b..b634bea28c 100644
--- a/tools/build/src/tools/testing.py
+++ b/tools/build/src/tools/testing.py
@@ -113,7 +113,7 @@ def make_test(target_type, sources, requirements, target_name=None):
# The alias to the real target, per period replacement above.
if real_name != target_name:
- get_manager().projects().project_rules().all_names_["alias"](
+ get_manager().projects().project_rules().rules["alias"](
target_name, [t])
# Remember the test (for --dump-tests). A good way would be to collect all
diff --git a/tools/build/src/tools/types/asm.py b/tools/build/src/tools/types/asm.py
index a4b4aee61e..d9a30152eb 100644
--- a/tools/build/src/tools/types/asm.py
+++ b/tools/build/src/tools/types/asm.py
@@ -27,7 +27,7 @@ def set_asm_type(type_, sources, name=''):
name = name if name else _project_types[project.name() + type_]
type_ += '.asm'
- cast(name, type_.upper(), sources, [], [], [])
+ return cast(name, type_.upper(), sources, [], [], [])
PROJECT_REGISTRY.add_rule("set-asm-type", set_asm_type)
diff --git a/tools/build/src/tools/types/cpp.py b/tools/build/src/tools/types/cpp.py
index 22f4dece45..50797bae48 100644
--- a/tools/build/src/tools/types/cpp.py
+++ b/tools/build/src/tools/types/cpp.py
@@ -1,84 +1,10 @@
# Copyright David Abrahams 2004. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-import os
-import re
+from b2.build import type as type_
-import bjam
-
-from b2.build import type as type_, scanner
-from b2.manager import get_manager
-from b2.util.utility import replace_grist
-
-
-MANAGER = get_manager()
-ENGINE = MANAGER.engine()
-SCANNERS = MANAGER.scanners()
-
-
-class CScanner(scanner.Scanner):
- def __init__(self, includes):
- scanner.Scanner.__init__(self)
- self.includes = []
- for include in includes:
- self.includes.extend(replace_grist(include, '').split('&&'))
-
- def pattern(self):
- return '#\s*include\s*(<(.*)>|"(.*)")'
-
- def process(self, target, matches, binding):
- # create a single string so that findall
- # can be used since it returns a list of
- # all grouped matches
- match_str = ' '.join(matches)
- # the question mark makes the regexes non-greedy
- angles = re.findall(r'<(.*?)>', match_str)
- quoted = re.findall(r'"(.*?)"', match_str)
-
- # CONSIDER: the new scoping rules seem to defeat "on target" variables.
- g = ENGINE.get_target_variable(target, 'HDRGRIST')
- b = os.path.normpath(os.path.dirname(binding))
-
- # Attach binding of including file to included targets. When a target is
- # directly created from a virtual target this extra information is
- # unnecessary. But in other cases, it allows us to distinguish between
- # two headers of the same name included from different places. We do not
- # need this extra information for angle includes, since they should not
- # depend on the including file (we can not get literal "." in the
- # include path).
- # local g2 = $(g)"#"$(b) ;
- g2 = g + '#' + b
-
- angles = [replace_grist(angle, g) for angle in angles]
- quoted = [replace_grist(quote, g2) for quote in quoted]
-
- includes = angles + quoted
-
- bjam.call('INCLUDES', target, includes)
- bjam.call('NOCARE', includes)
- ENGINE.set_target_variable(angles, 'SEARCH', self.includes)
- ENGINE.set_target_variable(quoted, 'SEARCH', [b] + self.includes)
-
- # Just propagate the current scanner to includes, in hope that includes
- # do not change scanners.
- SCANNERS.propagate(self, includes)
-
- bjam.call('ISFILE', includes)
-
-
-scanner.register(CScanner, 'include')
type_.register_type('CPP', ['cpp', 'cxx', 'cc'])
type_.register_type('H', ['h'])
type_.register_type('HPP', ['hpp'], 'H')
type_.register_type('C', ['c'])
-# It most cases where a CPP file or a H file is a source of some action, we
-# should rebuild the result if any of files included by CPP/H are changed. One
-# case when this is not needed is installation, which is handled specifically.
-type_.set_scanner('CPP', CScanner)
-type_.set_scanner('C', CScanner)
-# One case where scanning of H/HPP files is necessary is PCH generation -- if
-# any header included by HPP being precompiled changes, we need to recompile the
-# header.
-type_.set_scanner('H', CScanner)
-type_.set_scanner('HPP', CScanner)
diff --git a/tools/build/src/tools/unix.py b/tools/build/src/tools/unix.py
index 681a872027..298fc1dc5e 100644
--- a/tools/build/src/tools/unix.py
+++ b/tools/build/src/tools/unix.py
@@ -46,8 +46,13 @@ class UnixArchiveGenerator (builtin.ArchiveGenerator):
builtin.ArchiveGenerator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
def run (self, project, name, prop_set, sources):
+ from b2.build.property_set import PropertySet
result = builtin.ArchiveGenerator.run(self, project, name, prop_set, sources)
- set_library_order(project.manager(), sources, prop_set, result)
+ if result and isinstance(result[0], PropertySet):
+ _, targets = result
+ else:
+ targets = result
+ set_library_order(project.manager(), sources, prop_set, targets)
return result
class UnixSearchedLibGenerator (builtin.SearchedLibGenerator):
@@ -130,7 +135,7 @@ def set_library_order (manager, sources, prop_set, result):
used_libraries = []
deps = prop_set.dependency ()
- sources.extend(d.value() for d in deps)
+ sources.extend(d.value for d in deps)
sources = sequence.unique(sources)
for l in sources:
diff --git a/tools/build/src/tools/zlib.jam b/tools/build/src/tools/zlib.jam
index 8095eeeeef..5a7d5fbdf5 100644
--- a/tools/build/src/tools/zlib.jam
+++ b/tools/build/src/tools/zlib.jam
@@ -135,13 +135,11 @@ rule init (
[ property.select <search> <include> <name> : $(options) ] "and"
[ property.select <source> <tag> <build-name> : $(options) ] ;
}
- else
- {
- no-build-from-source = true ;
- }
}
-
- source-path ?= [ modules.peek : ZLIB_SOURCE ] ;
+ else
+ {
+ source-path ?= [ modules.peek : ZLIB_SOURCE ] ;
+ }
if $(.configured.$(condition))
{
@@ -158,7 +156,7 @@ rule init (
}
return ;
}
- else if $(source-path) && ! $(no-build-from-source)
+ else if $(source-path)
{
build-name ?= z ;
library-id = [ CALC $(library-id) + 1 ] ;
@@ -185,7 +183,8 @@ rule init (
}
}
local target ;
- if $(sources) {
+ if $(sources)
+ {
target = [ targets.create-typed-target LIB : $(.project)
: $(build-name).$(library-id)
: $(sources)
@@ -207,7 +206,9 @@ rule init (
$(mt).set-target $(target) ;
}
targets.main-target-alternative $(mt) ;
- } else {
+ }
+ else
+ {
if $(.debug)
{
ECHO "notice: [zlib] Using pre-installed library" ;
@@ -218,7 +219,7 @@ rule init (
}
local mt = [ new ac-library zlib : $(.project) : $(condition) :
- $(include-path) : $(library-path) : $(library-name) : $(root) ] ;
+ $(include-path) : $(library-path) : $(library-name) ] ;
$(mt).set-header $(header) ;
$(mt).set-default-names $(names) ;
targets.main-target-alternative $(mt) ;
diff --git a/tools/build/src/util/option.py b/tools/build/src/util/option.py
index 120c2a32c2..b23a7257cd 100644
--- a/tools/build/src/util/option.py
+++ b/tools/build/src/util/option.py
@@ -29,7 +29,7 @@ def get(name, default_value=None, implied_value=None):
m = b2.util.regex.transform(sys.argv, "--(" + re.escape(name) + ")")
if m and implied_value:
return implied_value
- elif options.has_key(name) and options[name] != None:
+ elif options.get(name) is not None:
return options[name]
else:
return default_value
diff --git a/tools/build/src/util/os_j.py b/tools/build/src/util/os_j.py
index f44cca6201..f5dff1f904 100644
--- a/tools/build/src/util/os_j.py
+++ b/tools/build/src/util/os_j.py
@@ -8,6 +8,7 @@
# Copyright 2003, 2005 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+import os
import bjam
@@ -17,3 +18,7 @@ __OS = bjam.call("peek", [], "OS")[0]
# when faced with Python naming
def name():
return __OS
+
+
+def environ(keys):
+ return [os.environ[key] for key in keys if key in os.environ]
diff --git a/tools/build/src/util/path.py b/tools/build/src/util/path.py
index 7b90320730..e451c2cbee 100644
--- a/tools/build/src/util/path.py
+++ b/tools/build/src/util/path.py
@@ -881,7 +881,7 @@ def glob_tree(roots, patterns, exclude_patterns=None):
exclude_patterns = []
result = glob(roots, patterns, exclude_patterns)
- subdirs = [s for s in glob(roots, ["*"]) if s != "." and s != ".." and os.path.isdir(s)]
+ subdirs = [s for s in glob(roots, ["*"], exclude_patterns) if s != "." and s != ".." and os.path.isdir(s)]
if subdirs:
result.extend(glob_tree(subdirs, patterns, exclude_patterns))
diff --git a/tools/build/src/util/regex.py b/tools/build/src/util/regex.py
index 6348c6fb19..37eeb6d888 100644
--- a/tools/build/src/util/regex.py
+++ b/tools/build/src/util/regex.py
@@ -38,7 +38,16 @@ def replace(s, pattern, replacement):
pattern (str): the search expression
replacement (str): the string to replace each match with
"""
- return re.sub(pattern, replacement, s)
+ # the replacement string may contain invalid backreferences (like \1 or \g)
+ # which will cause python's regex to blow up. Since this should emulate
+ # the jam version exactly and the jam version didn't support
+ # backreferences, this version shouldn't either. re.sub
+ # allows replacement to be a callable; this is being used
+ # to simply return the replacement string and avoid the hassle
+ # of worrying about backreferences within the string.
+ def _replacement(matchobj):
+ return replacement
+ return re.sub(pattern, _replacement, s)
@bjam_signature((['items', '*'], ['match'], ['replacement']))
diff --git a/tools/build/src/util/set.py b/tools/build/src/util/set.py
index f2239a021d..98b1d17f5e 100644
--- a/tools/build/src/util/set.py
+++ b/tools/build/src/util/set.py
@@ -10,13 +10,11 @@ from .utility import to_seq
def difference (b, a):
""" Returns the elements of B that are not in A.
"""
- assert is_iterable(b)
- assert is_iterable(a)
+ a = set(a)
result = []
- for element in b:
- if not element in a:
- result.append (element)
-
+ for item in b:
+ if item not in a:
+ result.append(item)
return result
def intersection (set1, set2):
diff --git a/tools/build/src/util/utility.py b/tools/build/src/util/utility.py
index 162a57be4f..ded3e5bcdc 100644
--- a/tools/build/src/util/utility.py
+++ b/tools/build/src/util/utility.py
@@ -59,17 +59,28 @@ def replace_grist (features, new_grist):
"""
assert is_iterable_typed(features, basestring) or isinstance(features, basestring)
assert isinstance(new_grist, basestring)
- def replace_grist_one (name, new_grist):
- split = __re_grist_and_value.match (name)
- if not split:
- return new_grist + name
- else:
- return new_grist + split.group (2)
-
- if isinstance (features, str):
- return replace_grist_one (features, new_grist)
- else:
- return [ replace_grist_one (feature, new_grist) for feature in features ]
+ # this function is used a lot in the build phase and the original implementation
+ # was extremely slow; thus some of the weird-looking optimizations for this function.
+ single_item = False
+ if isinstance(features, str):
+ features = [features]
+ single_item = True
+
+ result = []
+ for feature in features:
+ # '<feature>value' -> ('<feature', '>', 'value')
+ # 'something' -> ('something', '', '')
+ # '<toolset>msvc/<feature>value' -> ('<toolset', '>', 'msvc/<feature>value')
+ grist, split, value = feature.partition('>')
+ # if a partition didn't occur, then grist is just 'something'
+ # set the value to be the grist
+ if not value and not split:
+ value = grist
+ result.append(new_grist + value)
+
+ if single_item:
+ return result[0]
+ return result
def get_value (property):
""" Gets the value of a property, that is, the part following the grist, if any.
@@ -124,7 +135,7 @@ def forward_slashes (s):
""" Converts all backslashes to forward slashes.
"""
assert isinstance(s, basestring)
- return __re_backslash.sub ('/', s)
+ return s.replace('\\', '/')
def split_action_id (id):
diff --git a/tools/build/test/BoostBuild.py b/tools/build/test/BoostBuild.py
index 8c51cf05fb..55f3bc221a 100644
--- a/tools/build/test/BoostBuild.py
+++ b/tools/build/test/BoostBuild.py
@@ -452,7 +452,12 @@ class Tester(TestCmd.TestCmd):
if ignore_toolset_requirements:
kw["program"].append("--ignore-toolset-requirements")
if "--python" in sys.argv:
- kw["program"].append("--python")
+ # -z disables Python optimization mode.
+ # this enables type checking (all assert
+ # and if __debug__ statements).
+ kw["program"].extend(["--python", "-z"])
+ if "--stacktrace" in sys.argv:
+ kw["program"].append("--stacktrace")
kw["chdir"] = subdir
self.last_program_invocation = kw["program"]
build_time_start = time.time()
diff --git a/tools/build/test/conditionals_multiple.py b/tools/build/test/conditionals_multiple.py
index 91b8f30d76..dd11690811 100755
--- a/tools/build/test/conditionals_multiple.py
+++ b/tools/build/test/conditionals_multiple.py
@@ -147,7 +147,7 @@ rule init ( version ? ) { }
from b2.build import feature
feature.extend('toolset', ["%(toolset)s"])
feature.subfeature('toolset', "%(toolset)s", "version", ['0','1'])
-def init ( version ): pass
+def init (version=''): pass
""" % {"toolset": toolset})
t.write("jamroot.jam", """\
diff --git a/tools/build/test/dependency_property.py b/tools/build/test/dependency_property.py
index cdd8055b0e..bcced6ad94 100644
--- a/tools/build/test/dependency_property.py
+++ b/tools/build/test/dependency_property.py
@@ -10,7 +10,6 @@
# targets ended up being in the same location.
import BoostBuild
-import string
t = BoostBuild.Tester()
@@ -31,6 +30,10 @@ void foo() {}
""")
t.run_build_system(["--no-error-backtrace"], status=1)
-t.fail_test(string.find(t.stdout(), "Tried to build the target twice") == -1)
+output = t.stdout()
+t.fail_test(
+ "Tried to build the target twice" not in output and
+ "Duplicate name of actual target" not in output
+)
t.cleanup()
diff --git a/tools/build/test/inherit_toolset.py b/tools/build/test/inherit_toolset.py
index af18780039..95884647e3 100644
--- a/tools/build/test/inherit_toolset.py
+++ b/tools/build/test/inherit_toolset.py
@@ -25,6 +25,36 @@ actions compile { yfc1-compile }
actions link { yfc1-link }
""")
+t.write(
+ 'yfc1.py',
+"""
+from b2.build import feature, generators
+from b2.manager import get_manager
+
+MANAGER = get_manager()
+ENGINE = MANAGER.engine()
+
+feature.extend('toolset', ['yfc1'])
+
+generators.register_standard('yfc1.compile', ['CPP'], ['OBJ'], ['<toolset>yfc1'])
+generators.register_standard('yfc1.link', ['OBJ'], ['EXE'], ['<toolset>yfc1'])
+
+ENGINE.register_action(
+ 'yfc1.compile',
+ 'yfc1-compile'
+)
+
+ENGINE.register_action(
+ 'yfc1.link',
+ 'yfc1-link'
+)
+
+def init(*args):
+ pass
+
+"""
+)
+
t.write("yfc2.jam", """\
import feature ;
import toolset ;
@@ -36,6 +66,25 @@ rule init ( ) { }
actions link { yfc2-link }
""")
+t.write(
+ 'yfc2.py',
+"""
+from b2.build import feature, toolset
+from b2.manager import get_manager
+
+MANAGER = get_manager()
+ENGINE = MANAGER.engine()
+
+feature.extend('toolset', ['yfc2'])
+toolset.inherit('yfc2', 'yfc1')
+
+ENGINE.register_action('yfc2.link', 'yfc2-link')
+
+def init(*args):
+ pass
+"""
+)
+
t.write("jamfile.jam", "exe a : a.cpp ;")
t.write("jamroot.jam", "using yfc1 ;")
diff --git a/tools/build/test/scanner_causing_rebuilds.py b/tools/build/test/scanner_causing_rebuilds.py
index 2b5fc501c5..d1ff66bfd4 100755
--- a/tools/build/test/scanner_causing_rebuilds.py
+++ b/tools/build/test/scanner_causing_rebuilds.py
@@ -68,6 +68,54 @@ actions foo
$(.touch) "$(<[2])"
}
""")
+
+t.write(
+ 'foo.py',
+"""
+import os
+
+from b2.build import type as type_, generators
+from b2.tools import common
+from b2.manager import get_manager
+
+MANAGER = get_manager()
+ENGINE = MANAGER.engine()
+
+type_.register('FOO', ['foo'])
+type_.register('BAR', ['bar'])
+generators.register_standard('foo.foo', ['FOO'], ['CPP', 'BAR'])
+
+def sleep_cmd(delay):
+ if os.name == 'nt':
+ return 'ping 127.0.0.1 -n {} -w 1000 >NUL'.format(delay)
+ return 'sleep {}'.format(delay)
+
+def foo(targets, sources, properties):
+ cpp, bar = targets
+ foo = sources[0]
+ # We add the INCLUDE relationship between our generated CPP & BAR targets
+ # explicitly instead of relying on Boost Jam's internal implementation
+ # detail - automatically adding such relationships between all files
+ # generated by the same action. This way our test will continue to function
+ # correctly even if the related Boost Jam implementation detail changes.
+ # Note that adding this relationship by adding an #include directive in our
+ # generated CPP file is not good enough as such a relationship would get
+ # added only after the scanner target's relationships have already been
+ # established and they (as affected by our initial INCLUDE relationship) are
+ # the original reason for this test failing.
+ bjam.call('INCLUDES', cpp, bar)
+
+ENGINE.register_action(
+ 'foo.foo',
+ '''
+ {touch} "$(<[1])"
+ {sleep}
+ {touch} "$(<[2])"
+ '''.format(touch=common.file_creation_command(), sleep=sleep_cmd(2))
+)
+"""
+)
+
t.write("x.foo", "")
t.write("jamroot.jam", """\
import foo ;
diff --git a/tools/build/test/source_order.py b/tools/build/test/source_order.py
index f42f4ccae2..af8fd54bce 100755
--- a/tools/build/test/source_order.py
+++ b/tools/build/test/source_order.py
@@ -27,6 +27,37 @@ actions check-order
generators.register-composing check-order.check-order : C : ORDER_TEST ;
""")
+t.write(
+ 'check-order.py',
+"""
+import bjam
+
+from b2.build import type as type_, generators
+from b2.tools import common
+from b2.manager import get_manager
+
+MANAGER = get_manager()
+ENGINE = MANAGER.engine()
+
+type_.register('ORDER_TEST', ['order-test'])
+
+generators.register_composing('check-order.check-order', ['C'], ['ORDER_TEST'])
+
+def check_order(targets, sources, properties):
+ ENGINE.set_target_variable(targets, 'SPACE', ' ')
+ ENGINE.set_target_variable(targets, 'nl', '\\n')
+
+ENGINE.register_action(
+ 'check-order.check-order',
+ function=check_order,
+ command='''
+ echo$(SPACE)$(>[1])>$(<[1])
+ echo$(SPACE)$(>[2-])>>$(<[1])$(nl)
+ '''
+)
+"""
+)
+
# The aliases are necessary for this test, since
# the targets were sorted by virtual target
# id, not by file name.
diff --git a/tools/build/test/test_rc.py b/tools/build/test/test_rc.py
index 510b47275b..1ffac15b06 100755
--- a/tools/build/test/test_rc.py
+++ b/tools/build/test/test_rc.py
@@ -73,6 +73,44 @@ set-generated-obj-suffix windows ;
set-generated-obj-suffix cygwin ;
""" % toolsetName)
+ t.write(
+ toolsetName + '.py',
+"""
+from b2.build import feature, type as type_
+from b2.manager import get_manager
+from b2.tools import rc, common
+
+MANAGER = get_manager()
+ENGINE = MANAGER.engine()
+
+toolset_name = "{0}"
+
+feature.extend('toolset', [toolset_name])
+
+def init(*args):
+ pass
+
+rc.configure(['dummy-rc-command'], ['<toolset>' + toolset_name], ['<rc-type>dummy'])
+
+ENGINE.register_action(
+ 'rc.compile.resource.dummy',
+ '''
+ %s "$(<)"
+ ''' % common.file_creation_command()
+)
+
+def set_generated_obj_suffix(target_os=''):
+ requirements = ['<toolset>' + toolset_name]
+ if target_os:
+ requirements.append('<target-os>' + target_os)
+ type_.set_generated_target_suffix('OBJ', requirements, 'obj')
+
+set_generated_obj_suffix()
+set_generated_obj_suffix('windows')
+set_generated_obj_suffix('cygwin')
+""".format(toolsetName)
+ )
+
# Prepare project source files.
t.write("jamroot.jam", """\
ECHO {{{ [ modules.peek : XXX ] [ modules.peek : NOEXEC ] }}} ;
diff --git a/tools/build/test/timedata.py b/tools/build/test/timedata.py
index 20a95c2a22..2bfc3ef318 100644
--- a/tools/build/test/timedata.py
+++ b/tools/build/test/timedata.py
@@ -49,14 +49,15 @@ rule time
actions time
{
- echo $(>) user: $(__USER_TIME__) system: $(__SYSTEM_TIME__)
+ echo $(>) user: $(__USER_TIME__) system: $(__SYSTEM_TIME__) clock: $(__CLOCK_TIME__)
echo timed from $(>) >> $(<)
}
-rule record_time ( target : source : start end user system )
+rule record_time ( target : source : start end user system clock )
{
__USER_TIME__ on $(target) = $(user) ;
__SYSTEM_TIME__ on $(target) = $(system) ;
+ __CLOCK_TIME__ on $(target) = $(clock) ;
}
rule make
@@ -80,7 +81,7 @@ make bar : baz ;
\.\.\.updating 2 targets\.\.\.
make bar
time foo
-bar +user: [0-9\.]+ +system: +[0-9\.]+ *
+bar +user: [0-9\.]+ +system: +[0-9\.]+ +clock: +[0-9\.]+ *
\.\.\.updated 2 targets\.\.\.$
"""
@@ -125,6 +126,8 @@ time my-time : my-exe ;
"user: *[0-9] seconds")
t.expect_content_lines("bin/$toolset/debug/my-time.time",
"system: *[0-9] seconds")
+ t.expect_content_lines("bin/$toolset/debug/my-time.time",
+ "clock: *[0-9] seconds")
t.cleanup()
diff --git a/tools/build/tutorial.html b/tools/build/tutorial.html
index c500d20855..f50586e4f3 100644
--- a/tools/build/tutorial.html
+++ b/tools/build/tutorial.html
@@ -1433,7 +1433,7 @@ exe hello : hello.cpp : &lt;library&gt;/boost//thread ;
<tr>
<td>&lt;target-os&gt;</td>
- <td>aix, bsd, cygwin, darwin, freebsd, hpux, iphone, linux,
+ <td>aix, appletv, bsd, cygwin, darwin, freebsd, hpux, iphone, linux,
netbsd, openbsd, osf, qnx, qnxnto, sgi, solaris, unix, unixware,
windows</td>