Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/more/separate_compilation.html @ 12

Last change on this file since 12 was 12, checked in by landauf, 18 years ago

added boost

File size: 21.9 KB
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2<html>
3   <head>
4      <title>Guidelines for Authors of Boost Libraries Containing Separate Source</title>
5      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
6      <LINK href="../boost.css" type="text/css" rel="stylesheet"></head>
7   <body>
8      <P>
9         <TABLE id="Table1" cellSpacing="1" cellPadding="1" width="100%" border="0">
10            <TR>
11               <td vAlign="top" width="300">
12                  <h3><A href="../index.htm"><IMG height="86" alt="C++ Boost" src="../boost.png" width="277" border="0"></A></h3>
13               </td>
14               <TD width="353">
15                  <H1 align="center">Guidelines for Authors of Boost Libraries Containing Separate
16                     Source</H1>
17               </TD>
18            </TR>
19         </TABLE>
20      </P>
21      <HR>
22      <P>These guidelines are designed for the authors of Boost libraries which have
23         separate source that need compiling in order to use the library. Throughout,
24         this guide refers to a fictitious "whatever" library, so replace all
25         occurrences of "whatever" or "WHATEVER" with your own library's name when
26         copying the examples.</P>
27      <H2>Contents</H2>
28      <P>
29         <dl class="index">
30            <dt><A href="#source_changes">Changes Affecting Source Code</A>
31               <dd>
32                  <dl class="index">
33                     <dt><A href="#abi">Preventing Compiler ABI Clashes</A> <dt><A href="#dlls">Supporting
34                              Windows Dll's</A> <dt><a href="#auto-link">Automatic Library Selection and Linking
35                                 with auto_link.hpp</a> </dt>
36                  </dl>
37                  <dt><A href="#build_changes">Changes Affecting the Build System</A>
38                     <dd>
39                        <dl class="index">
40                           <dt><A href="#jamfile">Creating the Library Jamfile</A> <dt><A href="#testing">Testing
41                                    Auto-linking</A> </dt>
42                        </dl>
43                        <dt><A href="#copyright">Copyright</A></dt>
44         </dl>
45      <P></P>
46      <h2><A name="source_changes"></A>Changes Affecting Source Code</h2>
47      <H3><A name="abi"></A>Preventing Compiler ABI Clashes</H3>
48      <P>There are some compilers (mostly Microsoft Windows compilers again!), which
49         feature a range of compiler switches that alter the ABI of C++ classes and
50         functions. By way of example, consider Borland's compiler which has the
51         following options:</P>
52      <PRE>-b    (on or off - effects enum sizes).
53-Vx   (on or off - empty members).
54-Ve   (on or off - empty base classes).
55-aX   (alignment - 5 options).
56-pX   (Calling convention - 4 options).
57-VmX  (member pointer size and layout - 5 options).
58-VC   (on or off, changes name mangling).
59-Vl   (on or off, changes struct layout).
60</PRE>
61      <P>These options are provided in addition to those affecting which runtime library
62         is used (more on which later); the total number of combinations of options can
63         be obtained by multiplying together the individual options above, so that gives
64         2*2*2*5*4*5*2*2 = 3200 combinations!
65      </P>
66      <P>The problem is that users often expect to be able to build the Boost libraries
67         and then just link to them and have everything just plain work, no matter what
68         their project settings are. Irrespective of whether this is a reasonable
69         expectation or not, without some means of managing this issue, the user may
70         well find that their program will experience strange and hard to track down
71         crashes at runtime unless the library they link to was built with the same
72         options as their project (changes to the default alignment setting are a prime
73         culprit). One way to manage this is with "prefix and suffix" headers: these
74         headers invoke compiler specific #pragma directives to instruct the compiler
75         that whatever code follows was built (or is to be built) with a specific set of
76         compiler ABI settings.</P>
77      <P>Boost.config provides the macro BOOST_HAS_ABI_HEADERS which is set whenever
78         there are prefix and suffix headers available for the compiler in use, typical
79         usage in a header like this:</P>
80      <PRE>#ifndef BOOST_WHATEVER_HPP
81#define BOOST_WHATEVER_HPP
82
83#include &lt;boost/config.hpp&gt;
84
85// this must occur after all of the includes and before any code appears:
86#ifdef BOOST_HAS_ABI_HEADERS
87#  include BOOST_ABI_PREFIX
88#endif
89//
90// this header declares one class, and one function by way of examples:
91//
92class whatever
93{
94   // details.
95};
96
97whatever get_whatever();
98
99// the suffix header occurs after all of our code:
100#ifdef BOOST_HAS_ABI_HEADERS
101#  include BOOST_ABI_SUFFIX
102#endif
103
104#endif
105</PRE>
106      <P>You can include this code in your source files as well if you want - although
107         you probably shouldn't need to - these headers fix the ABI to the default used
108         by the compiler, and if the user attempts to compile the source with any other
109         setting then they will get compiler errors if there are any conflicts.</P>
110      <H4>Rationale:</H4>
111      <P>Without some means of managing this issue, users often report bugs along the
112         line of "Your silly library always crashes when I try and call it" and so on.
113         These issues can be extremely difficult and time consuming to track down, only
114         to discover in the end that it's a compiler setting that's changed the ABI of
115         the class and/or function types of the program compared to those in the
116         pre-compiled library. The use of prefix/suffix headers can minimize this
117         problem, although probably not remove it completely.</P>
118      <H5>Counter Argument #1:</H5>
119      <P>Trust the user, if they want 13-byte alignment (!) let them have it.</P>
120      <H5>Counter Argument #2:</H5>
121      <P>Prefix/suffix headers have a tendency to "spread" to other boost libraries -
122         for example if boost::shared_ptr&lt;&gt; forms part of your class's ABI, then
123         including prefix/suffix headers in your code will be of no use unless
124         shared_ptr.hpp also uses them. Authors of header-only boost libraries may not
125         be so keen on this solution - with some justification - since they don't face
126         the same problem.</P>
127      <h3><A name="dlls"></A>Supporting Windows Dll's</h3>
128      <p>On most Unix-like platforms no special annotations of source code are required
129         in order for that source to be compiled as a shared library because all
130         external symbols are exposed. However the majority of Windows compilers require
131         that symbols that are to be imported or exported from a dll, be prefixed with
132         __declspec(dllimport) or __declspec(dllexport). Without this mangling of source
133         code, it is not possible to correctly build shared libraries on Windows
134         (historical note - originally these declaration modifiers were required on
135         16-bit Windows where the memory layout for exported classes was different from
136         that of "local" classes - although this is no longer an issue, there is still
137         no way to instruct the linker to "export everything", it also remains to be
138         seen whether 64-bit Windows will resurrect the segmented architecture that led
139         to this problem in the first place. Note also that the mangled names of
140         exported symbols are different from non-exported ones, so __declspec(dllimport)
141         is required in order to link to code within a dll).</p>
142      <p>In order to support the building of shared libraries on MS Windows your code
143         will have to prefix all the symbols that your library exports with a macro
144         (lets call it BOOST_WHATEVER_DECL) that your library will define to expand to
145         either __declspec(dllexport) or __declspec(dllimport) or nothing, depending
146         upon how your library is being built or used. Typical usage would look like
147         this:</p>
148      <pre>#ifndef BOOST_WHATEVER_HPP
149#define BOOST_WHATEVER_HPP
150
151#include &lt;boost/config.hpp&gt;
152
153#ifdef BOOST_HAS_DECLSPEC // defined in config system
154// we need to import/export our code only if the user has specifically
155// asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
156// libraries to be dynamically linked, or BOOST_WHATEVER_DYN_LINK
157// if they want just this one to be dynamically liked:
158#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_WHATEVER_DYN_LINK)
159// export if this is our own source, otherwise import:
160#ifdef BOOST_WHATEVER_SOURCE
161# define BOOST_WHATEVER_DECL __declspec(dllexport)
162#else
163# define BOOST_WHATEVER_DECL __declspec(dllimport)
164#endif  // BOOST_WHATEVER_SOURCE
165#endif  // DYN_LINK
166#endif  // BOOST_HAS_DECLSPEC
167//
168// if BOOST_WHATEVER_DECL isn't defined yet define it now:
169#ifndef BOOST_WHATEVER_DECL
170#define BOOST_WHATEVER_DECL
171#endif
172
173//
174// this header declares one class, and one function by way of examples:
175//
176class BOOST_WHATEVER_DECL whatever
177{
178   // details.
179};
180
181BOOST_WHATEVER_DECL whatever get_whatever();
182
183#endif
184</pre>
185      And then in the source code for this library one would use:
186      <pre> 
187//
188// define BOOST_WHATEVER SOURCE so that our library's
189// setup code knows that we are building the library (possibly exporting code),
190// rather than using it (possibly importing code):
191//
192#define BOOST_WHATEVER_SOURCE
193#include &lt;boost/whatever.hpp&gt; 
194
195// class members don't need any further annotation:
196whatever::whatever() { }
197// but functions do:
198BOOST_WHATEVER_DECL whatever get_whatever()
199{
200   return whatever();
201}
202</pre>
203      <H4>Importing/exporting dependencies</H4>
204      <P>As well as exporting your main classes and functions (those that are actually
205         documented), Microsoft Visual C++ will warn loudly and often if you try to
206         import/export a class whose dependencies are not also exported. Dependencies
207         include: any base classes, any user defined types used as data members, plus
208         all of the dependencies of your dependencies and so on. This causes particular
209         problems when a dependency is a template class, because although it is
210         technically possible to export these, it is not at all easy, especially if the
211         template itself has dependencies which are implementation-specific details. In
212         most cases it's probably better to simply suppress the warnings using:</P>
213      <PRE>#ifdef BOOST_MSVC
214#  pragma warning(push)
215#  pragma warning(disable : 4251 4231 4660)
216#endif
217
218// code here
219
220#ifdef BOOST_MSVC
221#pragma warning(pop)
222#endif
223</PRE>
224      <p>This is safe provided that there are no dependencies that are (template)
225         classes with non-constant static data members, these really do need exporting,
226         otherwise there will be multiple copies of the static data members in the
227         program, and that's really really bad.
228      </p>
229      <p>Historical note: on 16-bit Windows you really did have to export all
230         dependencies or the code wouldn't work, however since the latest Visual Studio
231         .NET supports the import/export of individual member functions, it's a
232         reasonably safe bet that Windows compilers won't do anything nasty - like
233         changing the class's ABI - when importing/exporting a class.</p>
234      <h4>Rationale:</h4>
235      <p><EM>Why bother - doesn't the import/export mechanism take up more code that the
236            classes themselves?</EM></p>
237      <P>A good point, and probably true, however there are some circumstances where
238         library code must be placed in a shared library - for example when the
239         application consists of multiple dll's as well as the executable, and more than
240         one those dll's link to the same Boost library - in this case if the library
241         isn't dynamically linked and it contains any global data (even if that data is
242         private to the internals of the library) then really bad things can happen -
243         even without global data, we will still get a code bloating effect.
244         Incidentally, for larger applications, splitting the application into multiple
245         dll's can be highly advantageous - by using Microsoft's "delay load" feature
246         the application will load only those parts it really needs at any one time,
247         giving the impression of a much more responsive and faster-loading application.</P>
248      <p><EM>Why static linking by default? </EM>
249      </p>
250      <P>In the worked example above, the code assumes that the library will be
251         statically linked unless the user asks otherwise. Most users seem to prefer
252         this (there are no separate dll's to distribute, and the overall distribution
253         size is often significantly smaller this way as well: i.e. you pay for what you
254         use and no more), but this is a subjective call, and some libraries may even
255         only be available in dynamic versions (Boost.threads for example).</P>
256      <h3><A name="auto-link"></A>Automatic Library Selection and Linking with <a href="../boost/config/auto_link.hpp">
257            auto_link.hpp</a></h3>
258      <p>Many Windows compilers ship with multiple runtime libraries - for example
259         Microsoft Visual Studio .NET comes with 6 versions of the C and C++ runtime. It
260         is essential that the Boost library that the user links to is built against the
261         same C runtime as the program is built against. If that is not the case, then
262         the user will experience linker errors at best, and runtime crashes at worst.
263         The Boost build system manages this by providing different build variants, each
264         of which is build against a different runtime, and gets a slightly different
265         mangled name depending upon which runtime it is built against. For example the
266         regex libraries get named as follows when built with Visual Studio .NET 2003:</p>
267      <pre>boost_regex-vc71-mt-1_31.lib
268boost_regex-vc71-mt-gd-1_31.lib
269libboost_regex-vc71-mt-1_31.lib
270libboost_regex-vc71-mt-gd-1_31.lib
271libboost_regex-vc71-mt-s-1_31.lib
272libboost_regex-vc71-mt-sgd-1_31.lib
273libboost_regex-vc71-s-1_31.lib
274libboost_regex-vc71-sgd-1_31.lib
275</pre>
276      <p>The difficulty now is selecting which of these the user should link his or her
277         code to.</p>
278      <p>In contrast, most Unix compilers typically only have one runtime (or sometimes
279         two if there is a separate thread safe option). For these systems the only
280         choice in selecting the right library variant is whether they want debugging
281         info, and possibly thread safety.
282      </p>
283      <p>Historically Microsoft Windows compilers have managed this issue by providing a
284         #pragma option that allows the header for a library to automatically select the
285         library to link to. This makes everything automatic and extremely easy for the
286         end user: as soon as they include a header file that has separate source code,
287         the name of the right library build variant gets embedded in the object file,
288         and as long as that library is in the linker search path, it will get pulled in
289         by the linker without any user intervention.</p>
290      <p>Automatic library selection and linking can be enabled for a Boost library by
291         including the header &lt;boost/config/auto_link.hpp&gt;, after first defining
292         BOOST_LIB_NAME and, if applicable, BOOST_DYN_LINK.</p>
293      <pre>//
294// Automatically link to the correct build variant where possible.
295//
296#if !defined(BOOST_ALL_NO_LIB) &amp;&amp; !defined(BOOST_WHATEVER_NO_LIB) &amp;&amp; !defined(BOOST_WHATEVER_SOURCE)
297//
298// Set the name of our library, this will get undef'ed by auto_link.hpp
299// once it's done with it:
300//
301#define BOOST_LIB_NAME boost_whatever
302//
303// If we're importing code from a dll, then tell auto_link.hpp about it:
304//
305#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_WHATEVER_DYN_LINK)
306#  define BOOST_DYN_LINK
307#endif
308//
309// And include the header that does the work:
310//
311#include &lt;boost/config/auto_link.hpp&gt;
312#endif  // auto-linking disabled
313</pre>
314      <P></P>
315      <p>The library's user documentation should note that the feature can be disabled
316         by defining either BOOST_ALL_NO_LIB or BOOST_WHATEVER_NO_LIB:</p>
317      <P>If for any reason you need to debug this feature, the header
318         &lt;boost/config/auto_link.hpp&gt; will output some helpful diagnostic messages
319         if you first define BOOST_LIB_DIAGNOSTIC.</P>
320      <H2><A name="build_changes"></A>Changes Affecting the Build System</H2>
321      <H3><a name='build"'></a><A name="jamfile"></A>Creating the library Jamfile</H3>
322      <P>The Jamfile for building library "whatever" typically lives in
323         boost-root/libs/whatever/build, start by defining the project root for the
324         Jamfile:</P>
325      <PRE>subproject libs/whatever/build ; </PRE>
326      <P>Then add the static library build target (if supported):</P>
327      <PRE>lib
328   boost_whatever
329      : # list all the sources for this
330      library:
331   ../src/whatever.cpp
332      : # all build requirements go
333      here. # the "common-variant-tag" rule ensures that the library will
334      # be named according to the rules used by the install
335      # and auto-link features:
336      common-variant-tag
337      # set include path for Boost headers:
338      &lt;sysinclude&gt;$(BOOST_ROOT)
339   :
340      # list default build variants here
341      debug release
342   ; </PRE>
343      <P>Then add the dll build target (if supported).&nbsp;&nbsp;In this case the build
344         requirements section get an extra define: so that our sources know to export
345         their own symbols (and import those from any other boost libs on which we may
346         be dependent).&nbsp; We also restict shared library builds to dynamic-runtime
347         build variants, if we don't do this then dll's linked against static runtimes
348         are unlikely to function correctly (the dll will have a separate runtime from
349         the executable using it, this generally causing problems with new and
350         delete,&nbsp;as well as exception handling runtimes).</P>
351      <PRE>dll
352   boost_whatever
353      : # list all the sources for this
354      library:
355   ../src/whatever.cpp
356      : # all build requirements go
357      here. # the "common-variant-tag" rule ensures that the library will
358      # be named according to the rules used by the install
359      # and auto-link features:
360      common-variant-tag
361      # tell our source that we're building (and maybe using) dll's:
362      &lt;define&gt;BOOST_ALL_DYN_LINK=1
363      # only build this for dynamic runtimes:
364      &lt;runtime-link&gt;dynamic
365      # set include path for Boost headers:
366      &lt;sysinclude&gt;$(BOOST_ROOT)
367   :
368      # list default build variants here
369      debug release
370   ;
371</PRE>
372      <P>Now add an install target so that Boost.Install can find this library to
373         install:</P>
374      <pre>install whatever lib
375    : &lt;dll&gt;boost_whatever &lt;lib&gt;boost_whatever
376    ;
377</pre>
378      <P>Finally add a stage target that will copy the built libraries to a common
379         sub-directory (boost-root/stage/lib):</P>
380      <PRE>stage stage/lib : &lt;lib&gt;boost_whatever &lt;dll&gt;boost_whatever
381    :
382        # copy to a path rooted at BOOST_ROOT:
383        &lt;locate&gt;$(BOOST_ROOT)
384        # make sure the names of the libraries are correctly named:
385        common-variant-tag
386        # add this target to the "stage" and "all" psuedo-targets:
387        &lt;target&gt;stage
388        &lt;target&gt;all
389    :
390        debug release
391    ;
392</PRE>
393      <H3><A name="testing"></A>Testing Auto-linking</H3>
394      <P>Testing the auto-link feature&nbsp;reasonable straightforward using
395         the&nbsp;Boost.build system: we need to build the "whatever" library's test
396         files without explicitly specifying the library to link to in the Jamfile, for
397         example:</P>
398      <PRE>subproject libs/whatever/test/auto-link-test ;
399
400# bring in the rules for testing
401import testing ;
402
403# start with a static linking version:
404
405run
406   # sources
407      ../whatever_test.cpp
408   :
409   :    # input files
410   :    # requirements
411      &lt;library-path&gt;../../../../stage/lib
412      &lt;define&gt;BOOST_LIB_DIAGNOSTIC=1
413   :    # program name
414      whatever_test         
415   ;
416
417   # and then a dll linking version:
418   run
419   # sources
420      ../whatever_test.cpp
421   :
422   :    # input files
423   :    # requirements
424      &lt;library-path&gt;../../../../stage/lib
425      &lt;define&gt;BOOST_LIB_DIAGNOSTIC=1
426      &lt;define&gt;BOOST_ALL_DYN_LINK=1
427      &lt;runtime-link&gt;dynamic
428   :    # program name
429      whatever_test_dll         
430   ;
431
432</PRE>
433      <P>Please note however that this Jamfile will only build with compilers that do
434         actually support auto-linking, so it should not be added to the regular
435         regression tests.&nbsp; The Jamfile should also be built for all possible build
436         variants, for the Microsoft / Borland compilers that means doing a:</P>
437      <PRE>bjam -sBUILD="release debug &lt;threading&gt;multi/single &lt;runtime-link&gt;static/dynamic" test
438      </PRE>
439      <HR>
440      <p><A name="copyright"></A>Revised
441         <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan --> 
442         26 November, 2003<!--webbot bot="Timestamp" endspan i-checksum="39365" --></p>
443      <p><i>© Copyright John Maddock&nbsp;1998-
444            <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y" startspan -->  2003<!--webbot bot="Timestamp" endspan i-checksum="746" --></i></p>
445      <P><I>Use, modification and distribution are subject to the Boost Software License,
446            Version 1.0. (See accompanying file <a href="../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
447            or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>).</I></P>
448      <P><EM>The use of code snippets from this article does not require the reproduction
449            of this copyright notice and license declaration; if you wish to provide
450            attribution then please provide a link to this article.</EM></P>
451   </body>
452</html>
Note: See TracBrowser for help on using the repository browser.