Boost logo

Boost-Commit :

From: daniel_james_at_[hidden]
Date: 2007-11-10 10:46:50


Author: danieljames
Date: 2007-11-10 10:46:49 EST (Sat, 10 Nov 2007)
New Revision: 40989
URL: http://svn.boost.org/trac/boost/changeset/40989

Log:
Add the separate compilation page from the old site. Fixes #1370.

Added:
   website/public_html/beta/development/separate_compilation.html (contents, props changed)
Text files modified:
   website/public_html/beta/common/menu-development.html | 3 +++
   1 files changed, 3 insertions(+), 0 deletions(-)

Modified: website/public_html/beta/common/menu-development.html
==============================================================================
--- website/public_html/beta/common/menu-development.html (original)
+++ website/public_html/beta/common/menu-development.html 2007-11-10 10:46:49 EST (Sat, 10 Nov 2007)
@@ -31,6 +31,9 @@
         <li><a href="/development/header.html">Header policy <span class=
         "link">&gt;</span></a></li>
 
+ <li><a href="/development/separate_compilation.html">Separate Source
+ <span class="link">&gt;</span></a></li>
+
         <li><a href="/development/reuse.html">Library Reuse <span class=
         "link">&gt;</span></a></li>
 

Added: website/public_html/beta/development/separate_compilation.html
==============================================================================
--- (empty file)
+++ website/public_html/beta/development/separate_compilation.html 2007-11-10 10:46:49 EST (Sat, 10 Nov 2007)
@@ -0,0 +1,535 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+ <title>Guidelines for Authors of Boost Libraries Containing Separate
+ Source</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
+ <link rel="icon" href="/favicon.ico" type="image/ico" />
+ <link rel="stylesheet" type="text/css" href=
+ "/style/section-development.css" />
+ <!--[if IE]> <style type="text/css"> body { behavior: url(/style/csshover.htc); } </style> <![endif]-->
+</head>
+
+<body>
+ <div id="heading">
+ <!--#include virtual="/common/heading.html" -->
+ </div>
+
+ <div id="body">
+ <div id="body-inner">
+ <div id="content">
+ <div class="section" id="intro">
+ <div class="section-0">
+ <div class="section-title">
+ <h1>Guidelines for Authors of Boost Libraries Containing
+ Separate Source</h1>
+ </div>
+
+ <div class="section-body">
+ <p>These guidelines are designed for the authors of Boost
+ libraries which have separate source that need compiling in
+ order to use the library. Throughout, this guide refers to a
+ fictitious "whatever" library, so replace all occurrences of
+ "whatever" or "WHATEVER" with your own library's name when
+ copying the examples.</p>
+
+ <h2>Contents</h2>
+
+ <dl class="index">
+ <dt><a href="#source_changes">Changes Affecting Source
+ Code</a></dt>
+
+ <dd>
+ <dl class="index">
+ <dt><a href="#abi">Preventing Compiler ABI
+ Clashes</a></dt>
+
+ <dt><a href="#static_or_dynamic">Static or Dymanic
+ Libraries</a></dt>
+
+ <dt>Supporting Windows Dll's</dt>
+
+ <dt><a href="#auto-link">Automatic Library Selection and
+ Linking with auto_link.hpp</a></dt>
+ </dl>
+ </dd>
+
+ <dt><a href="#build_changes">Changes Affecting the Build
+ System</a></dt>
+
+ <dd>
+ <dl class="index">
+ <dt><a href="#jamfile">Creating the Library
+ Jamfile</a></dt>
+
+ <dt>Testing Auto-linking</dt>
+ </dl>
+ </dd>
+
+ <dt>Copyright</dt>
+ </dl>
+
+ <h2><a name="source_changes" id="source_changes"></a>Changes
+ Affecting Source Code</h2>
+
+ <h3><a name="abi" id="abi"></a>Preventing Compiler ABI
+ Clashes</h3>
+
+ <p>There are some compilers (mostly Microsoft Windows compilers
+ again!), which feature a range of compiler switches that alter
+ the ABI of C++ classes and functions. By way of example,
+ consider Borland's compiler which has the following
+ options:</p>
+ <pre>
+-b (on or off - effects enum sizes).
+-Vx (on or off - empty members).
+-Ve (on or off - empty base classes).
+-aX (alignment - 5 options).
+-pX (Calling convention - 4 options).
+-VmX (member pointer size and layout - 5 options).
+-VC (on or off, changes name mangling).
+-Vl (on or off, changes struct layout).
+</pre>
+
+ <p>These options are provided in addition to those affecting
+ which runtime library is used (more on which later); the total
+ number of combinations of options can be obtained by
+ multiplying together the individual options above, so that
+ gives 2*2*2*5*4*5*2*2 = 3200 combinations!</p>
+
+ <p>The problem is that users often expect to be able to build
+ the Boost libraries and then just link to them and have
+ everything just plain work, no matter what their project
+ settings are. Irrespective of whether this is a reasonable
+ expectation or not, without some means of managing this issue,
+ the user may well find that their program will experience
+ strange and hard to track down crashes at runtime unless the
+ library they link to was built with the same options as their
+ project (changes to the default alignment setting are a prime
+ culprit). One way to manage this is with "prefix and suffix"
+ headers: these headers invoke compiler specific #pragma
+ directives to instruct the compiler that whatever code follows
+ was built (or is to be built) with a specific set of compiler
+ ABI settings.</p>
+
+ <p>Boost.config provides the macro BOOST_HAS_ABI_HEADERS which
+ is set whenever there are prefix and suffix headers available
+ for the compiler in use, typical usage in a header like
+ this:</p>
+ <pre>
+#ifndef BOOST_WHATEVER_HPP
+#define BOOST_WHATEVER_HPP
+
+#include &lt;boost/config.hpp&gt;
+
+// this must occur after all of the includes and before any code appears:
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+//
+// this header declares one class, and one function by way of examples:
+//
+class whatever
+{
+ // details.
+};
+
+whatever get_whatever();
+
+// the suffix header occurs after all of our code:
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif
+</pre>
+
+ <p>You can include this code in your library source files as
+ well if you want, although you probably shouldn't need to:</p>
+
+ <ul>
+ <li>If you <em>don't</em> use these in the library source
+ files (but do in your library's headers) and the user
+ attempts to compile the library source with a non-default ABI
+ setting, then they will get compiler errors if there are any
+ conflicts.</li>
+
+ <li>If you <em>do</em> include them in both the library's
+ headers and the library source files, then the code should
+ always compile no matter what the compiler settings used,
+ although the result might not match what the user was
+ expecting: since we've forced the ABI back into default
+ mode.</li>
+ </ul>
+
+ <h4>Rationale:</h4>
+
+ <p>Without some means of managing this issue, users often
+ report bugs along the line of "Your silly library always
+ crashes when I try and call it" and so on. These issues can be
+ extremely difficult and time consuming to track down, only to
+ discover in the end that it's a compiler setting that's changed
+ the ABI of the class and/or function types of the program
+ compared to those in the pre-compiled library. The use of
+ prefix/suffix headers can minimize this problem, although
+ probably not remove it completely.</p>
+
+ <h5>Counter Argument #1:</h5>
+
+ <p>Trust the user, if they want 13-byte alignment (!) let them
+ have it.</p>
+
+ <h5>Counter Argument #2:</h5>
+
+ <p>Prefix/suffix headers have a tendency to "spread" to other
+ boost libraries - for example if boost::shared_ptr&lt;&gt;
+ forms part of your class's ABI, then including prefix/suffix
+ headers in your code will be of no use unless shared_ptr.hpp
+ also uses them. Authors of header-only boost libraries may not
+ be so keen on this solution - with some justification - since
+ they don't face the same problem.</p>
+
+ <h3><a name="static_or_dynamic" id=
+ "static_or_dynamic"></a>Static or Dynamic Libraries</h3>
+
+ <p>When the users runtime is dynamically linked the Boost
+ libraries can be built either as dynamic libraries (.so's on
+ Unix platforms, .dll's on Windows) or as static libraries (.a's
+ on Unix, .lib's on Windows). So we have a choice as to which is
+ supported by default:</p>
+
+ <ul>
+ <li>On Unix platforms it typically makes no difference to the
+ code: the user just selects in their makesfile which library
+ they prefer to link to.</li>
+
+ <li>On Windows platforms, the code has to be specially
+ annotated to support DLL's, so we need to pick one option as
+ the default and one as an alternative.</li>
+
+ <li>On Windows platforms, we can inject special code to
+ automatically select which library variant to link against:
+ so again we need to decide which is to be the default (see
+ the section on auto-linking below).</li>
+ </ul>
+
+ <p>The recomendation is to pick static linking by default.</p>
+
+ <h4>Rationale:</h4>
+
+ <p>There is no one policy that fits all here.</p>
+
+ <p>The rationale for the current behaviour was inherited from
+ Boost.Regex (and it's ancestor regex++): this library
+ originally used dynamic linking by default whenever the runtime
+ was dynamic. It's actually safer that way should you be using
+ regex from a dll for example. However, this behavior brought a
+ persistent stream of user complaints: mainly about deployment,
+ all asking if static linking could be the default. After regex
+ changed behavior the complaints stopped, and the author hasn't
+ had one complaint about static linking by default being the
+ wrong choice.</p>
+
+ <p>Note that other libraries might need to make other choices:
+ for example libraries that are intended to be used to implement
+ dll pluggin's would like need to use dynamic linking in almost
+ all cases.</p>
+
+ <h3>Supporting Windows Dll's</h3>
+
+ <p>On most Unix-like platforms no special annotations of source
+ code are required in order for that source to be compiled as a
+ shared library because all external symbols are exposed.
+ However the majority of Windows compilers require that symbols
+ that are to be imported or exported from a dll, be prefixed
+ with __declspec(dllimport) or __declspec(dllexport). Without
+ this mangling of source code, it is not possible to correctly
+ build shared libraries on Windows (historical note - originally
+ these declaration modifiers were required on 16-bit Windows
+ where the memory layout for exported classes was different from
+ that of "local" classes - although this is no longer an issue,
+ there is still no way to instruct the linker to "export
+ everything", it also remains to be seen whether 64-bit Windows
+ will resurrect the segmented architecture that led to this
+ problem in the first place. Note also that the mangled names of
+ exported symbols are different from non-exported ones, so
+ __declspec(dllimport) is required in order to link to code
+ within a dll).</p>
+
+ <p>In order to support the building of shared libraries on MS
+ Windows your code will have to prefix all the symbols that your
+ library exports with a macro (lets call it BOOST_WHATEVER_DECL)
+ that your library will define to expand to either
+ __declspec(dllexport) or __declspec(dllimport) or nothing,
+ depending upon how your library is being built or used. Typical
+ usage would look like this:</p>
+ <pre>
+#ifndef BOOST_WHATEVER_HPP
+#define BOOST_WHATEVER_HPP
+
+#include &lt;boost/config.hpp&gt;
+
+#ifdef BOOST_HAS_DECLSPEC // defined in config system
+// we need to import/export our code only if the user has specifically
+// asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
+// libraries to be dynamically linked, or BOOST_WHATEVER_DYN_LINK
+// if they want just this one to be dynamically liked:
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_WHATEVER_DYN_LINK)
+// export if this is our own source, otherwise import:
+#ifdef BOOST_WHATEVER_SOURCE
+# define BOOST_WHATEVER_DECL __declspec(dllexport)
+#else
+# define BOOST_WHATEVER_DECL __declspec(dllimport)
+#endif // BOOST_WHATEVER_SOURCE
+#endif // DYN_LINK
+#endif // BOOST_HAS_DECLSPEC
+//
+// if BOOST_WHATEVER_DECL isn't defined yet define it now:
+#ifndef BOOST_WHATEVER_DECL
+#define BOOST_WHATEVER_DECL
+#endif
+
+//
+// this header declares one class, and one function by way of examples:
+//
+class BOOST_WHATEVER_DECL whatever
+{
+ // details.
+};
+
+BOOST_WHATEVER_DECL whatever get_whatever();
+
+#endif
+</pre>And then in the source code for this library one would use:
+ <pre>
+
+//
+// define BOOST_WHATEVER SOURCE so that our library's
+// setup code knows that we are building the library (possibly exporting code),
+// rather than using it (possibly importing code):
+//
+#define BOOST_WHATEVER_SOURCE
+#include &lt;boost/whatever.hpp&gt;
+
+// class members don't need any further annotation:
+whatever::whatever() { }
+// but functions do:
+BOOST_WHATEVER_DECL whatever get_whatever()
+{
+ return whatever();
+}
+</pre>
+
+ <h4>Importing/exporting dependencies</h4>
+
+ <p>As well as exporting your main classes and functions (those
+ that are actually documented), Microsoft Visual C++ will warn
+ loudly and often if you try to import/export a class whose
+ dependencies are not also exported. Dependencies include: any
+ base classes, any user defined types used as data members, plus
+ all of the dependencies of your dependencies and so on. This
+ causes particular problems when a dependency is a template
+ class, because although it is technically possible to export
+ these, it is not at all easy, especially if the template itself
+ has dependencies which are implementation-specific details. In
+ most cases it's probably better to simply suppress the warnings
+ using:</p>
+ <pre>
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable : 4251 4231 4660)
+#endif
+
+// code here
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+</pre>
+
+ <p>This is safe provided that there are no dependencies that
+ are (template) classes with non-constant static data members,
+ these really do need exporting, otherwise there will be
+ multiple copies of the static data members in the program, and
+ that's really really bad.</p>
+
+ <p>Historical note: on 16-bit Windows you really did have to
+ export all dependencies or the code wouldn't work, however
+ since the latest Visual Studio .NET supports the import/export
+ of individual member functions, it's a reasonably safe bet that
+ Windows compilers won't do anything nasty - like changing the
+ class's ABI - when importing/exporting a class.</p>
+
+ <h4>Rationale:</h4>
+
+ <p><em>Why bother - doesn't the import/export mechanism take up
+ more code that the classes themselves?</em></p>
+
+ <p>A good point, and probably true, however there are some
+ circumstances where library code must be placed in a shared
+ library - for example when the application consists of multiple
+ dll's as well as the executable, and more than one those dll's
+ link to the same Boost library - in this case if the library
+ isn't dynamically linked and it contains any global data (even
+ if that data is private to the internals of the library) then
+ really bad things can happen - even without global data, we
+ will still get a code bloating effect. Incidentally, for larger
+ applications, splitting the application into multiple dll's can
+ be highly advantageous - by using Microsoft's "delay load"
+ feature the application will load only those parts it really
+ needs at any one time, giving the impression of a much more
+ responsive and faster-loading application.</p>
+
+ <p><em>Why static linking by default?</em></p>
+
+ <p>In the worked example above, the code assumes that the
+ library will be statically linked unless the user asks
+ otherwise. Most users seem to prefer this (there are no
+ separate dll's to distribute, and the overall distribution size
+ is often significantly smaller this way as well: i.e. you pay
+ for what you use and no more), but this is a subjective call,
+ and some libraries may even only be available in dynamic
+ versions (Boost.threads for example).</p>
+
+ <h3><a name="auto-link" id="auto-link"></a>Automatic Library
+ Selection and Linking with <a href=
+ "../boost/config/auto_link.hpp">auto_link.hpp</a></h3>
+
+ <p>Many Windows compilers ship with multiple runtime libraries
+ - for example Microsoft Visual Studio .NET comes with 6
+ versions of the C and C++ runtime. It is essential that the
+ Boost library that the user links to is built against the same
+ C runtime as the program is built against. If that is not the
+ case, then the user will experience linker errors at best, and
+ runtime crashes at worst. The Boost build system manages this
+ by providing different build variants, each of which is build
+ against a different runtime, and gets a slightly different
+ mangled name depending upon which runtime it is built against.
+ For example the regex libraries get named as follows when built
+ with Visual Studio .NET 2003:</p>
+ <pre>
+boost_regex-vc71-mt-1_31.lib
+boost_regex-vc71-mt-gd-1_31.lib
+libboost_regex-vc71-mt-1_31.lib
+libboost_regex-vc71-mt-gd-1_31.lib
+libboost_regex-vc71-mt-s-1_31.lib
+libboost_regex-vc71-mt-sgd-1_31.lib
+libboost_regex-vc71-s-1_31.lib
+libboost_regex-vc71-sgd-1_31.lib
+</pre>
+
+ <p>The difficulty now is selecting which of these the user
+ should link his or her code to.</p>
+
+ <p>In contrast, most Unix compilers typically only have one
+ runtime (or sometimes two if there is a separate thread safe
+ option). For these systems the only choice in selecting the
+ right library variant is whether they want debugging info, and
+ possibly thread safety.</p>
+
+ <p>Historically Microsoft Windows compilers have managed this
+ issue by providing a #pragma option that allows the header for
+ a library to automatically select the library to link to. This
+ makes everything automatic and extremely easy for the end user:
+ as soon as they include a header file that has separate source
+ code, the name of the right library build variant gets embedded
+ in the object file, and as long as that library is in the
+ linker search path, it will get pulled in by the linker without
+ any user intervention.</p>
+
+ <p>Automatic library selection and linking can be enabled for a
+ Boost library by including the header
+ &lt;boost/config/auto_link.hpp&gt;, after first defining
+ BOOST_LIB_NAME and, if applicable, BOOST_DYN_LINK.</p>
+ <pre>
+//
+// Automatically link to the correct build variant where possible.
+//
+#if !defined(BOOST_ALL_NO_LIB) &amp;&amp; !defined(BOOST_WHATEVER_NO_LIB) &amp;&amp; !defined(BOOST_WHATEVER_SOURCE)
+//
+// Set the name of our library, this will get undef'ed by auto_link.hpp
+// once it's done with it:
+//
+#define BOOST_LIB_NAME boost_whatever
+//
+// If we're importing code from a dll, then tell auto_link.hpp about it:
+//
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_WHATEVER_DYN_LINK)
+# define BOOST_DYN_LINK
+#endif
+//
+// And include the header that does the work:
+//
+#include &lt;boost/config/auto_link.hpp&gt;
+#endif // auto-linking disabled
+</pre>
+
+ <p>The library's user documentation should note that the
+ feature can be disabled by defining either BOOST_ALL_NO_LIB or
+ BOOST_WHATEVER_NO_LIB:</p>
+
+ <p>If for any reason you need to debug this feature, the header
+ &lt;boost/config/auto_link.hpp&gt; will output some helpful
+ diagnostic messages if you first define
+ BOOST_LIB_DIAGNOSTIC.</p>
+
+ <h2><a name="build_changes" id="build_changes"></a>Changes
+ Affecting the Build System</h2>
+
+ <h3><a name="build" id="build"></a><a name="jamfile" id=
+ "jamfile"></a>Creating the library Jamfile</h3>
+
+ <p>The Jamfile for building library "whatever" typically lives
+ in boost-root/libs/whatever/build, the only extra step required
+ is to add a &lt;define&gt; requirement to the library target so
+ that your code knows whether it's building a dll or static
+ library, a typical Jamfile would like like this:</p>
+ <pre>
+lib boost_regex : ../src/whatever.cpp :
+ &lt;link&gt;shared:&lt;define&gt;BOOST_WHATEVER_DYN_LINK=1 ;
+
+</pre>
+
+ <h3><a name="testing" id="testing"></a>Testing
+ Auto-linking</h3>
+
+ <p>Testing the auto-link feature is somewhat convoluted, and
+ requires access to a compiler that supports the feature: refer
+ to <a href=
+ "../libs/config/test/link/test/Jamfile.v2">libs/config/test/link/test/Jamfile.v2</a>
+ for an example.</p>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="sidebar">
+ <!--#include virtual="/common/sidebar-common.html" -->
+ <!--#include virtual="/common/sidebar-development.html" -->
+ </div>
+
+ <div class="clear"></div>
+ </div>
+ </div>
+
+ <div id="footer">
+ <div id="footer-left">
+ <div id="revised">
+ <p>Revised $Date: 2007-10-22 22:55:52 +0100 (Mon, 22 Oct 2007) $</p>
+ </div>
+
+ <div id="copyright">
+ <p>Copyright John Maddock 1998.</p>
+ </div><!--#include virtual="/common/footer-license.html" -->
+ </div>
+
+ <div id="footer-right">
+ <!--#include virtual="/common/footer-banners.html" -->
+ </div>
+
+ <div class="clear"></div>
+ </div>
+</body>
+</html>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk