diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-09-13 11:05:34 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-09-13 11:06:28 +0900 |
commit | 34bd32e225e2a8a94104489b31c42e5801cc1f4a (patch) | |
tree | d021b579a0c190354819974e1eaf0baa54b551f3 /tools | |
parent | f763a99a501650eff2c60288aa6f10ef916d769e (diff) | |
download | boost-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')
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"><</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">></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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id1"><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id2"><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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">></phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id1"><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id2"><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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">>=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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: <<link linkend="header.boost.array_hpp">boost/array.hpp</link>> @@ -163,13 +163,13 @@ <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id1"><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id2"><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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">></phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id1"><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id2"><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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">>=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><</phrase><phrase role="keyword">typename</phrase> U<phrase role="special">></phrase> array& <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"><</phrase><phrase role="identifier">U</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><</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">></phrase> - <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_id1"/><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><</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">></phrase> - <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_id2"/><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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">></phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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 < x</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_=_id1"/><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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"><=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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 < x)</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> - <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_=_id2"/><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"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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">>=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">></phrase><phrase role="special">&</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></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"><</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash">hash</link><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_bool_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">bool</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_char_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">char</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_signed_ch_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_wchar_t_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_short_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">short</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id2">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_int_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id3">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id4">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_long_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id5">hash</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="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_float_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">float</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_double_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">double</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_doub_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_strin_id1">hash</link><phrase role="special"><</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> - <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_wstri_id1">hash</link><phrase role="special"><</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_bo_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">bool</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_ch_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">char</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_si_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_wc_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_sh_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">short</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id2">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_in_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id3">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id4">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id2">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id5">hash</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="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_fl_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">float</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_do_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">double</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id3">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_st_id1">hash</link><phrase role="special"><</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> + <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_st_id2">hash</link><phrase role="special"><</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">></phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">></phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_T_id1">hash</link><phrase role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase><phrase role="special">></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<bool></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<bool></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + </para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_bo_id1"><refmeta><refentrytitle>Struct hash<bool></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<bool></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_bool_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">bool</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_bo_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">bool</phrase><phrase role="special">></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<char></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<char></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<char></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<char></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_char_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">char</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_ch_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">char</phrase><phrase role="special">></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<signed char></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<signed char></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<signed char></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<signed char></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_signed_ch_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_si_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">></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<unsigned char></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned char></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<unsigned char></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned char></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">></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<wchar_t></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<wchar_t></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<wchar_t></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<wchar_t></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_wchar_t_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_wc_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">></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<short></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<short></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<short></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<short></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_short_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">short</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_sh_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">short</phrase><phrase role="special">></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<unsigned short></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned short></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<unsigned short></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned short></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id2">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id2">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">></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<int></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<int></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<int></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<int></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_int_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_in_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">></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<unsigned int></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned int></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<unsigned int></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned int></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id3">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id3">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">></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<long></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<long></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<long></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<long></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase><phrase role="special">></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<unsigned long></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned long></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<unsigned long></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned long></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id4">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id4">hash</link><phrase role="special"><</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">></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<long long></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<long long></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<long long></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<long long></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_long_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id2">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">></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<unsigned long long></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned long long></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<unsigned long long></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<unsigned long long></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned__id5">hash</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="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_un_id5">hash</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="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<float></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<float></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<float></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<float></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_float_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">float</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_fl_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">float</phrase><phrase role="special">></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<double></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<double></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<double></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<double></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_double_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">double</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_do_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">double</phrase><phrase role="special">></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<long double></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<long double></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<long double></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<long double></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_doub_id1">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_lo_id3">hash</link><phrase role="special"><</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">></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<std::string></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<std::string></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<std::string></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<std::string></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_strin_id1">hash</link><phrase role="special"><</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_st_id1">hash</link><phrase role="special"><</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">></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">&</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">&</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<std::wstring></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<std::wstring></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> + ?><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<std::wstring></refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash<std::wstring></refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: <<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>> </phrase> -<phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_wstri_id1">hash</link><phrase role="special"><</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">></phrase> <phrase role="special">{</phrase> +<phrase role="keyword">struct</phrase> <link linkend="boost.hash_st_id2">hash</link><phrase role="special"><</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">></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">&</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">&</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"><</phrase><phrase role="identifier">Value</phrase><phrase role="special">></phrase> <phrase role="special">></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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_set</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_set</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase><phrase role="special">&</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"><</phrase><phrase role="identifier">Value</phrase><phrase role="special">></phrase> <phrase role="special">></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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_multiset</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_multiset</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_set</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_set</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">unordered_set</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">unordered_set</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_multiset</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_multiset</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">unordered_multiset</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">unordered_multiset</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_map</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_map</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_multimap</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_multimap</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> @@ -887,11 +887,11 @@ <phrase role="comment">// <link linkend="id210-bb">Equality Comparisons</link></phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_map</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_map</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">unordered_map</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">unordered_map</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_multimap</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase> <phrase role="keyword">template</phrase><phrase role="special"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase><phrase role="special">,</phrase> <phrase role="identifier">unordered_multimap</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">unordered_multimap</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">unordered_multimap</phrase><phrase role="special"><</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">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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 <module> boostdep [options] --subset <module> boostdep [options] [--header] <header> + boostdep --test <module> [options]: [--track-sources] [--title <title>] [--footer <footer>] [--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 -> 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 -> 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: "<literal>C:\Borland\BCC55</literal>"</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: "<literal>C:\MinGW</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>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: "<literal>%ProgramFiles%\Microsoft - Visual Studio</literal>", "<literal>%ProgramFiles%\Microsoft - Visual C++</literal>"</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: "<literal>%ProgramFiles%\Microsoft Visual - Studio .NET</literal>", "<literal>%ProgramFiles%\Microsoft - Visual Studio .NET 2003</literal>"</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: "<literal>%ProgramFiles%\Microsoft - Visual Studio 9</literal>"</listitem> - <listitem><literal>%VS80COMNTOOLS%</literal> - is present in environment</listitem> - <listitem>Common install location: "<literal>%ProgramFiles%\Microsoft - Visual Studio 8</literal>"</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 "HP-UX"</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: - "<literal>/opt/intel/cc/9.0</literal>", "<literal>/opt/intel_cc_80</literal>", - "<literal>/opt/intel/compiler70</literal>", "<literal>/opt/intel/compiler60</literal>", - "<literal>/opt/intel/compiler50</literal>"</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 "<literal>IRIX</literal>" or - "<literal>IRIX64</literal>"</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: "<literal>/opt/SUNWspro</literal>"</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 "<literal>QNX</literal>" 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 "<literal>OSF1</literal>"</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 "<literal>Darwin</literal>"</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: "<literal>/mingw</literal>"</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: "<literal>bin.linuxx86</literal>". 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 "<literal>--option</literal>", 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 "<literal>--option</literal>" 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 "<literal>bin./platform/.debug</literal>". - </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 "boehm_gc" 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 "duma" - 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 (") 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 (") 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 "on" - the target being bound, then in the global module). If non-empty, =$(BINDRULE[1])= - names a rule which is called with the name of the target and the path it - is being bound to. The signature of the rule named by =$(BINDRULE[1])= - should match the following: - </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 "[ - <emphasis>rule</emphasis> <emphasis>args</emphasis> ... ]". 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>$(<)</literal> - and <literal>$(>)</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>$(>)</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>$(>)</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>$(>)</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>$(>)</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 "I'm sorry, - Dave" 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 "<literal>:</literal>" - 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 "varargs" 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 - "classic" 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> - "<literal>foo.o</literal>" depends on "<literal>foo.c</literal>" - and "<literal>foo.h</literal>" 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 "leaf" 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 "<literal>all</literal>" 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">"exception"</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> - "<literal>Echo</literal>", "<literal>echo</literal>", - "<literal>Exit</literal>", and "<literal>exit</literal>" - 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 "<literal>include</literal>". - </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 "=[ ]=". For example: "<literal>FILES = [ GLOB dir1 - dir2 : *.c *.h ]</literal>" 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 : "Install Dir" ] ; -</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 "default" 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 = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths" ; -local subkeys = [ W32_GETREGNAMES "$(key)" : subkeys ] ; -for local subkey in $(subkeys) -{ - local values = [ W32_GETREGNAMES "$(key)\\$(subkey)" : values ] ; - for local value in $(values) - { - local data = [ W32_GETREG "$(key)\\$(subkey)" : "$(value)" ] ; - ECHO "Registry path: " $(key)\\$(subkey) ":" $(value) "=" $(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 ("") - 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 "w" or "r". 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> < <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> <= <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> > <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> >= <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> && <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 "<literal>bind</literal>" - 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) -> a b c -t$(X) -> ta tb tc -$(X)z -> az bz cz -$(X)-$(X) -> a-a a-b a-c b-a b-b b-c c-a c-b c-c -</programlisting> - <para> - The variable name and modifiers can themselves contain a variable reference, - and this partakes of the product as well: - </para> -<programlisting>$(X) -> a b c -$(Y) -> 1 2 -$(Z) -> X Y -$($(Z)) -> 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) -> a "" -$(Y) -> "" 1 -$(Z) -> --$(X)$(Y)- -> -a- -a1- -- -1- --$(X)$(Z)- -> -</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 ("\") to forward slashes ("/"). - For example -<programlisting><phrase role="identifier">x</phrase> <phrase role="special">=</phrase> <phrase role="string">"C:\\Program Files\\Borland"</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>"C:/Program Files/Borland"</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">"/cygdrive/c/Program Files/Borland"</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>"C:\Program Files\Borland"</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">"subdir/filename.c"</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>"[.subdir]filename.c"</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 "1", "2", or "3" -} -ECHO $(y) ; # prints "4 5 6" -</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 "internal" - 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 - "<literal>-j</literal>" 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 "3.1.19" - </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 "<literal>03</literal>" - "<literal>00</literal>". 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 "$2";; -2|5) on blinken sh -c "$2";; -3|6) on nod sh -c "$2";; -*) eval "$2";; -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, "<literal>module</literal>" - 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 "999" - } -} -module B -{ - y = 2 ; - rule f ( ) - { - ECHO $(y) ; # always prints "2" - 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 $($(>)) ; - } -} -</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 "<literal>$(>)</literal>" 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 "{Y} - {X}": - </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 "<literal>actions</literal>" - or "<literal>rule</literal>" 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>$(<)</literal> or <literal>$(>)</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 "<literal>rules</literal>" 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 - "right thing to do" 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 "bound value" 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 "binding" 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 "binding" can lead to some confusion. In particular, - the Modifying Binding section in the Jam documentation should probably - be titled "Modifying Update Determination". - </simpara> - </listitem> - <listitem> - <simpara> - "Grist" is just a string prefix of the form <<emphasis>characters</emphasis>>. - It is used in Jam to create unique target names based on simpler names. - For example, the file name "<literal>test.exe</literal>" may - be used by targets in separate subprojects, or for the debug and release - variants of the "same" abstract target. Each distinct target - bound to a file called "test.exe" 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 <s and trailing >s are added if necessary to - form an expression of the form <expr2>; <expr2> 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. - ":" for UNIX and ";" for Windows). All other variables - are split on space (" ") 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>"-sMESSAGE=message - text"</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 - "=". -- <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 - & 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 "sun" 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 "real" 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—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—14.0</para></listitem> + <listitem><para>Visual Studio 2013—12.0</para></listitem> + <listitem><para>Visual Studio 2012—11.0</para></listitem> <listitem><para>Visual Studio 2010—10.0</para></listitem> <listitem><para>Visual Studio 2008—9.0</para></listitem> <listitem><para>Visual Studio 2005—8.0</para></listitem> @@ -2661,7 +2664,7 @@ exe hello : hello.cpp : <os>NT,<toolset>gcc:<link>static ; target. The syntax is:</para> <programlisting> -target-id -> (project-id | target-name | file-name ) +target-id -> (target-name | file-name | project-id | directory-name) | (project-id | directory-name) "//" target-name project-id -> path target-name -> path @@ -2675,34 +2678,41 @@ directory-name -> 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><include>.</literal> will be + dependents. In this case, <literal><include>.</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><library></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 — 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 : <library>/boost//thread ; <tr> <td><target-os></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> |