mirror of
https://github.com/boostorg/website.git
synced 2026-01-19 04:42:17 +00:00
539 lines
23 KiB
HTML
539 lines
23 KiB
HTML
<!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=utf-8" />
|
|
<link rel="icon" href="/favicon.ico" type="image/ico" />
|
|
<link rel="stylesheet" type="text/css" href=
|
|
"/style-v2/section-development.css" />
|
|
<!--[if IE 7]> <style type="text/css"> body { behavior: url(/style-v2/csshover3.htc); } </style> <![endif]-->
|
|
<script defer data-domain="original.boost.org" src="https://plausible.io/js/script.js"></script></head><!--
|
|
Note: Editing website content is documented at:
|
|
https://www.boost.org/development/website_updating.html
|
|
-->
|
|
|
|
<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><a href="#dlls">Supporting Windows Dll's</a></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><a href="#testing">Testing Auto-linking</a></dt>
|
|
</dl>
|
|
</dd>
|
|
|
|
<dt><a href="#copyright">Copyright</a></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 <boost/config.hpp>
|
|
|
|
// 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<>
|
|
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 <boost/config.hpp>
|
|
|
|
#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 <boost/whatever.hpp>
|
|
|
|
// 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=
|
|
"/doc/libs/release/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
|
|
<boost/config/auto_link.hpp>, 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) && !defined(BOOST_WHATEVER_NO_LIB) && !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 <boost/config/auto_link.hpp>
|
|
#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
|
|
<boost/config/auto_link.hpp> 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 <define> 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 :
|
|
<link>shared:<define>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=
|
|
"/doc/libs/release/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>
|