| | 1 | = Guidelines for Authors of Boost Libraries Containing Separate Source = #intro |
| | 2 | |
| | 3 | These guidelines are designed for the authors of Boost |
| | 4 | libraries which have separate source that need compiling in |
| | 5 | order to use the library. Throughout, this guide refers to a |
| | 6 | fictitious "whatever" library, so replace all occurrences of |
| | 7 | "whatever" or "WHATEVER" with your own library's name when |
| | 8 | copying the examples. |
| | 9 | |
| | 10 | == Changes Affecting Source Code == #source_changes |
| | 11 | |
| | 12 | === Preventing Compiler ABI Clashes === #abi |
| | 13 | |
| | 14 | There are some compilers (mostly Microsoft Windows compilers |
| | 15 | again!), which feature a range of compiler switches that alter |
| | 16 | the ABI of C++ classes and functions. By way of example, |
| | 17 | consider Borland's compiler which has the following |
| | 18 | options: |
| | 19 | {{{ |
| | 20 | -b (on or off - effects enum sizes). |
| | 21 | -Vx (on or off - empty members). |
| | 22 | -Ve (on or off - empty base classes). |
| | 23 | -aX (alignment - 5 options). |
| | 24 | -pX (Calling convention - 4 options). |
| | 25 | -VmX (member pointer size and layout - 5 options). |
| | 26 | -VC (on or off, changes name mangling). |
| | 27 | -Vl (on or off, changes struct layout). |
| | 28 | }}} |
| | 29 | |
| | 30 | These options are provided in addition to those affecting |
| | 31 | which runtime library is used (more on which later); the total |
| | 32 | number of combinations of options can be obtained by |
| | 33 | multiplying together the individual options above, so that |
| | 34 | gives 2*2*2*5*4*5*2*2 = 3200 combinations! |
| | 35 | |
| | 36 | The problem is that users often expect to be able to build |
| | 37 | the Boost libraries and then just link to them and have |
| | 38 | everything just plain work, no matter what their project |
| | 39 | settings are. Irrespective of whether this is a reasonable |
| | 40 | expectation or not, without some means of managing this issue, |
| | 41 | the user may well find that their program will experience |
| | 42 | strange and hard to track down crashes at runtime unless the |
| | 43 | library they link to was built with the same options as their |
| | 44 | project (changes to the default alignment setting are a prime |
| | 45 | culprit). One way to manage this is with "prefix and suffix" |
| | 46 | headers: these headers invoke compiler specific #pragma |
| | 47 | directives to instruct the compiler that whatever code follows |
| | 48 | was built (or is to be built) with a specific set of compiler |
| | 49 | ABI settings. |
| | 50 | |
| | 51 | Boost.config provides the macro `BOOST_HAS_ABI_HEADERS` which |
| | 52 | is set whenever there are prefix and suffix headers available |
| | 53 | for the compiler in use, typical usage in a header like |
| | 54 | this: |
| | 55 | {{{ |
| | 56 | #ifndef BOOST_WHATEVER_HPP |
| | 57 | #define BOOST_WHATEVER_HPP |
| | 58 | |
| | 59 | #include <boost/config.hpp> |
| | 60 | |
| | 61 | // this must occur after all of the includes and before any code appears: |
| | 62 | #ifdef BOOST_HAS_ABI_HEADERS |
| | 63 | # include BOOST_ABI_PREFIX |
| | 64 | #endif |
| | 65 | // |
| | 66 | // this header declares one class, and one function by way of examples: |
| | 67 | // |
| | 68 | class whatever |
| | 69 | { |
| | 70 | // details. |
| | 71 | }; |
| | 72 | |
| | 73 | whatever get_whatever(); |
| | 74 | |
| | 75 | // the suffix header occurs after all of our code: |
| | 76 | #ifdef BOOST_HAS_ABI_HEADERS |
| | 77 | # include BOOST_ABI_SUFFIX |
| | 78 | #endif |
| | 79 | |
| | 80 | #endif |
| | 81 | }}} |
| | 82 | |
| | 83 | You can include this code in your library source files as |
| | 84 | well if you want, although you probably shouldn't need to: |
| | 85 | |
| | 86 | * If you ''don't'' use these in the library source |
| | 87 | files (but do in your library's headers) and the user |
| | 88 | attempts to compile the library source with a non-default ABI |
| | 89 | setting, then they will get compiler errors if there are any |
| | 90 | conflicts. |
| | 91 | * If you ''do'' include them in both the library's |
| | 92 | headers and the library source files, then the code should |
| | 93 | always compile no matter what the compiler settings used, |
| | 94 | although the result might not match what the user was |
| | 95 | expecting: since we've forced the ABI back into default |
| | 96 | mode. |
| | 97 | |
| | 98 | ==== Rationale: ==== #abi.rationale |
| | 99 | |
| | 100 | Without some means of managing this issue, users often |
| | 101 | report bugs along the line of "Your silly library always |
| | 102 | crashes when I try and call it" and so on. These issues can be |
| | 103 | extremely difficult and time consuming to track down, only to |
| | 104 | discover in the end that it's a compiler setting that's changed |
| | 105 | the ABI of the class and/or function types of the program |
| | 106 | compared to those in the pre-compiled library. The use of |
| | 107 | prefix/suffix headers can minimize this problem, although |
| | 108 | probably not remove it completely. |
| | 109 | |
| | 110 | ===== Counter Argument #1: ===== #abi.counter1 |
| | 111 | |
| | 112 | Trust the user, if they want 13-byte alignment (!) let them |
| | 113 | have it. |
| | 114 | |
| | 115 | ===== Counter Argument #2: ===== #abi.counter2 |
| | 116 | |
| | 117 | Prefix/suffix headers have a tendency to "spread" to other |
| | 118 | boost libraries - for example if boost::shared_ptr<> |
| | 119 | forms part of your class's ABI, then including prefix/suffix |
| | 120 | headers in your code will be of no use unless shared_ptr.hpp |
| | 121 | also uses them. Authors of header-only boost libraries may not |
| | 122 | be so keen on this solution - with some justification - since |
| | 123 | they don't face the same problem. |
| | 124 | |
| | 125 | === Static or Dynamic Libraries === #static_or_dynamic |
| | 126 | |
| | 127 | When the users runtime is dynamically linked the Boost |
| | 128 | libraries can be built either as dynamic libraries (.so's on |
| | 129 | Unix platforms, .dll's on Windows) or as static libraries (.a's |
| | 130 | on Unix, .lib's on Windows). So we have a choice as to which is |
| | 131 | supported by default: |
| | 132 | |
| | 133 | * On Unix platforms it typically makes no difference to the |
| | 134 | code: the user just selects in their makesfile which library |
| | 135 | they prefer to link to. |
| | 136 | * On Windows platforms, the code has to be specially |
| | 137 | annotated to support DLL's, so we need to pick one option as |
| | 138 | the default and one as an alternative. |
| | 139 | * On Windows platforms, we can inject special code to |
| | 140 | automatically select which library variant to link against: |
| | 141 | so again we need to decide which is to be the default (see |
| | 142 | the section on auto-linking below). |
| | 143 | |
| | 144 | The recomendation is to pick static linking by default. |
| | 145 | |
| | 146 | ==== Rationale: ==== #static-or-dynamic.rationale |
| | 147 | |
| | 148 | There is no one policy that fits all here. |
| | 149 | |
| | 150 | The rationale for the current behaviour was inherited from |
| | 151 | Boost.Regex (and it's ancestor regex++): this library |
| | 152 | originally used dynamic linking by default whenever the runtime |
| | 153 | was dynamic. It's actually safer that way should you be using |
| | 154 | regex from a dll for example. However, this behavior brought a |
| | 155 | persistent stream of user complaints: mainly about deployment, |
| | 156 | all asking if static linking could be the default. After regex |
| | 157 | changed behavior the complaints stopped, and the author hasn't |
| | 158 | had one complaint about static linking by default being the |
| | 159 | wrong choice. |
| | 160 | |
| | 161 | Note that other libraries might need to make other choices: |
| | 162 | for example libraries that are intended to be used to implement |
| | 163 | dll pluggin's would like need to use dynamic linking in almost |
| | 164 | all cases. |
| | 165 | |
| | 166 | === Supporting Windows Dll's === #windows-dlls |
| | 167 | |
| | 168 | On most Unix-like platforms no special annotations of source |
| | 169 | code are required in order for that source to be compiled as a |
| | 170 | shared library because all external symbols are exposed. |
| | 171 | However the majority of Windows compilers require that symbols |
| | 172 | that are to be imported or exported from a dll, be prefixed |
| | 173 | with `__declspec(dllimport)` or `__declspec(dllexport)`. Without |
| | 174 | this mangling of source code, it is not possible to correctly |
| | 175 | build shared libraries on Windows (historical note - originally |
| | 176 | these declaration modifiers were required on 16-bit Windows |
| | 177 | where the memory layout for exported classes was different from |
| | 178 | that of "local" classes - although this is no longer an issue, |
| | 179 | there is still no way to instruct the linker to "export |
| | 180 | everything", it also remains to be seen whether 64-bit Windows |
| | 181 | will resurrect the segmented architecture that led to this |
| | 182 | problem in the first place. Note also that the mangled names of |
| | 183 | exported symbols are different from non-exported ones, so |
| | 184 | `__declspec(dllimport)` is required in order to link to code |
| | 185 | within a dll). |
| | 186 | |
| | 187 | In order to support the building of shared libraries on MS |
| | 188 | Windows your code will have to prefix all the symbols that your |
| | 189 | library exports with a macro (lets call it `BOOST_WHATEVER_DECL`) |
| | 190 | that your library will define to expand to either |
| | 191 | `__declspec(dllexport)` or `__declspec(dllimport)` or nothing, |
| | 192 | depending upon how your library is being built or used. Typical |
| | 193 | usage would look like this: |
| | 194 | {{{ |
| | 195 | #ifndef BOOST_WHATEVER_HPP |
| | 196 | #define BOOST_WHATEVER_HPP |
| | 197 | |
| | 198 | #include <boost/config.hpp> |
| | 199 | |
| | 200 | #ifdef BOOST_HAS_DECLSPEC // defined in config system |
| | 201 | // we need to import/export our code only if the user has specifically |
| | 202 | // asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost |
| | 203 | // libraries to be dynamically linked, or BOOST_WHATEVER_DYN_LINK |
| | 204 | // if they want just this one to be dynamically liked: |
| | 205 | #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_WHATEVER_DYN_LINK) |
| | 206 | // export if this is our own source, otherwise import: |
| | 207 | #ifdef BOOST_WHATEVER_SOURCE |
| | 208 | # define BOOST_WHATEVER_DECL __declspec(dllexport) |
| | 209 | #else |
| | 210 | # define BOOST_WHATEVER_DECL __declspec(dllimport) |
| | 211 | #endif // BOOST_WHATEVER_SOURCE |
| | 212 | #endif // DYN_LINK |
| | 213 | #endif // BOOST_HAS_DECLSPEC |
| | 214 | // |
| | 215 | // if BOOST_WHATEVER_DECL isn't defined yet define it now: |
| | 216 | #ifndef BOOST_WHATEVER_DECL |
| | 217 | #define BOOST_WHATEVER_DECL |
| | 218 | #endif |
| | 219 | |
| | 220 | // |
| | 221 | // this header declares one class, and one function by way of examples: |
| | 222 | // |
| | 223 | class BOOST_WHATEVER_DECL whatever |
| | 224 | { |
| | 225 | // details. |
| | 226 | }; |
| | 227 | |
| | 228 | BOOST_WHATEVER_DECL whatever get_whatever(); |
| | 229 | |
| | 230 | #endif |
| | 231 | }}} |
| | 232 | |
| | 233 | And then in the source code for this library one would use: |
| | 234 | |
| | 235 | {{{ |
| | 236 | |
| | 237 | // |
| | 238 | // define BOOST_WHATEVER SOURCE so that our library's |
| | 239 | // setup code knows that we are building the library (possibly exporting code), |
| | 240 | // rather than using it (possibly importing code): |
| | 241 | // |
| | 242 | #define BOOST_WHATEVER_SOURCE |
| | 243 | #include <boost/whatever.hpp> |
| | 244 | |
| | 245 | // class members don't need any further annotation: |
| | 246 | whatever::whatever() { } |
| | 247 | // but functions do: |
| | 248 | BOOST_WHATEVER_DECL whatever get_whatever() |
| | 249 | { |
| | 250 | return whatever(); |
| | 251 | } |
| | 252 | }}} |
| | 253 | |
| | 254 | ==== Importing/exporting dependencies ==== #importing-exporting |
| | 255 | |
| | 256 | As well as exporting your main classes and functions (those |
| | 257 | that are actually documented), Microsoft Visual C++ will warn |
| | 258 | loudly and often if you try to import/export a class whose |
| | 259 | dependencies are not also exported. Dependencies include: any |
| | 260 | base classes, any user defined types used as data members, plus |
| | 261 | all of the dependencies of your dependencies and so on. This |
| | 262 | causes particular problems when a dependency is a template |
| | 263 | class, because although it is technically possible to export |
| | 264 | these, it is not at all easy, especially if the template itself |
| | 265 | has dependencies which are implementation-specific details. In |
| | 266 | most cases it's probably better to simply suppress the warnings |
| | 267 | using: |
| | 268 | |
| | 269 | {{{ |
| | 270 | #ifdef BOOST_MSVC |
| | 271 | # pragma warning(push) |
| | 272 | # pragma warning(disable : 4251 4231 4660) |
| | 273 | #endif |
| | 274 | |
| | 275 | // code here |
| | 276 | |
| | 277 | #ifdef BOOST_MSVC |
| | 278 | #pragma warning(pop) |
| | 279 | #endif |
| | 280 | }}} |
| | 281 | |
| | 282 | This is safe provided that there are no dependencies that |
| | 283 | are (template) classes with non-constant static data members, |
| | 284 | these really do need exporting, otherwise there will be |
| | 285 | multiple copies of the static data members in the program, and |
| | 286 | that's really really bad. |
| | 287 | |
| | 288 | Historical note: on 16-bit Windows you really did have to |
| | 289 | export all dependencies or the code wouldn't work, however |
| | 290 | since the latest Visual Studio .NET supports the import/export |
| | 291 | of individual member functions, it's a reasonably safe bet that |
| | 292 | Windows compilers won't do anything nasty - like changing the |
| | 293 | class's ABI - when importing/exporting a class. |
| | 294 | |
| | 295 | ==== Rationale: ==== #importing-exporting.rationale |
| | 296 | |
| | 297 | ''Why bother - doesn't the import/export mechanism take up |
| | 298 | more code that the classes themselves?'' |
| | 299 | |
| | 300 | A good point, and probably true, however there are some |
| | 301 | circumstances where library code must be placed in a shared |
| | 302 | library - for example when the application consists of multiple |
| | 303 | dll's as well as the executable, and more than one those dll's |
| | 304 | link to the same Boost library - in this case if the library |
| | 305 | isn't dynamically linked and it contains any global data (even |
| | 306 | if that data is private to the internals of the library) then |
| | 307 | really bad things can happen - even without global data, we |
| | 308 | will still get a code bloating effect. Incidentally, for larger |
| | 309 | applications, splitting the application into multiple dll's can |
| | 310 | be highly advantageous - by using Microsoft's "delay load" |
| | 311 | feature the application will load only those parts it really |
| | 312 | needs at any one time, giving the impression of a much more |
| | 313 | responsive and faster-loading application. |
| | 314 | |
| | 315 | ''Why static linking by default?'' |
| | 316 | |
| | 317 | In the worked example above, the code assumes that the |
| | 318 | library will be statically linked unless the user asks |
| | 319 | otherwise. Most users seem to prefer this (there are no |
| | 320 | separate dll's to distribute, and the overall distribution size |
| | 321 | is often significantly smaller this way as well: i.e. you pay |
| | 322 | for what you use and no more), but this is a subjective call, |
| | 323 | and some libraries may even only be available in dynamic |
| | 324 | versions (Boost.threads for example). |
| | 325 | |
| | 326 | === Automatic Library Selection and Linking with [http://www.boost.org/doc/libs/release/boost/config/auto_link.hpp auto_link.hpp] === #auto-link |
| | 327 | |
| | 328 | Many Windows compilers ship with multiple runtime libraries |
| | 329 | - for example Microsoft Visual Studio .NET comes with 6 |
| | 330 | versions of the C and C++ runtime. It is essential that the |
| | 331 | Boost library that the user links to is built against the same |
| | 332 | C runtime as the program is built against. If that is not the |
| | 333 | case, then the user will experience linker errors at best, and |
| | 334 | runtime crashes at worst. The Boost build system manages this |
| | 335 | by providing different build variants, each of which is build |
| | 336 | against a different runtime, and gets a slightly different |
| | 337 | mangled name depending upon which runtime it is built against. |
| | 338 | For example the regex libraries get named as follows when built |
| | 339 | with Visual Studio .NET 2003: |
| | 340 | |
| | 341 | {{{ |
| | 342 | boost_regex-vc71-mt-1_31.lib |
| | 343 | boost_regex-vc71-mt-gd-1_31.lib |
| | 344 | libboost_regex-vc71-mt-1_31.lib |
| | 345 | libboost_regex-vc71-mt-gd-1_31.lib |
| | 346 | libboost_regex-vc71-mt-s-1_31.lib |
| | 347 | libboost_regex-vc71-mt-sgd-1_31.lib |
| | 348 | libboost_regex-vc71-s-1_31.lib |
| | 349 | libboost_regex-vc71-sgd-1_31.lib |
| | 350 | }}} |
| | 351 | |
| | 352 | The difficulty now is selecting which of these the user |
| | 353 | should link his or her code to. |
| | 354 | |
| | 355 | In contrast, most Unix compilers typically only have one |
| | 356 | runtime (or sometimes two if there is a separate thread safe |
| | 357 | option). For these systems the only choice in selecting the |
| | 358 | right library variant is whether they want debugging info, and |
| | 359 | possibly thread safety. |
| | 360 | |
| | 361 | Historically Microsoft Windows compilers have managed this |
| | 362 | issue by providing a #pragma option that allows the header for |
| | 363 | a library to automatically select the library to link to. This |
| | 364 | makes everything automatic and extremely easy for the end user: |
| | 365 | as soon as they include a header file that has separate source |
| | 366 | code, the name of the right library build variant gets embedded |
| | 367 | in the object file, and as long as that library is in the |
| | 368 | linker search path, it will get pulled in by the linker without |
| | 369 | any user intervention. |
| | 370 | |
| | 371 | Automatic library selection and linking can be enabled for a |
| | 372 | Boost library by including the header |
| | 373 | <boost/config/auto_link.hpp>, after first defining |
| | 374 | BOOST_LIB_NAME and, if applicable, BOOST_DYN_LINK. |
| | 375 | |
| | 376 | {{{ |
| | 377 | // |
| | 378 | // Automatically link to the correct build variant where possible. |
| | 379 | // |
| | 380 | #if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_WHATEVER_NO_LIB) && !defined(BOOST_WHATEVER_SOURCE) |
| | 381 | // |
| | 382 | // Set the name of our library, this will get undef'ed by auto_link.hpp |
| | 383 | // once it's done with it: |
| | 384 | // |
| | 385 | #define BOOST_LIB_NAME boost_whatever |
| | 386 | // |
| | 387 | // If we're importing code from a dll, then tell auto_link.hpp about it: |
| | 388 | // |
| | 389 | #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_WHATEVER_DYN_LINK) |
| | 390 | # define BOOST_DYN_LINK |
| | 391 | #endif |
| | 392 | // |
| | 393 | // And include the header that does the work: |
| | 394 | // |
| | 395 | #include <boost/config/auto_link.hpp> |
| | 396 | #endif // auto-linking disabled |
| | 397 | }}} |
| | 398 | |
| | 399 | The library's user documentation should note that the |
| | 400 | feature can be disabled by defining either BOOST_ALL_NO_LIB or |
| | 401 | BOOST_WHATEVER_NO_LIB: |
| | 402 | |
| | 403 | If for any reason you need to debug this feature, the header |
| | 404 | <boost/config/auto_link.hpp> will output some helpful |
| | 405 | diagnostic messages if you first define |
| | 406 | BOOST_LIB_DIAGNOSTIC. |
| | 407 | |
| | 408 | == Changes Affecting the Build System == #build_changes |
| | 409 | |
| | 410 | === Creating the library Jamfile === #jamfile |
| | 411 | |
| | 412 | The Jamfile for building library "whatever" typically lives |
| | 413 | in boost-root/libs/whatever/build, the only extra step required |
| | 414 | is to add a <define> requirement to the library target so |
| | 415 | that your code knows whether it's building a dll or static |
| | 416 | library, a typical Jamfile would like like this: |
| | 417 | |
| | 418 | {{{ |
| | 419 | lib boost_regex : ../src/whatever.cpp : |
| | 420 | <link>shared:<define>BOOST_WHATEVER_DYN_LINK=1 ; |
| | 421 | }}} |
| | 422 | |
| | 423 | === Testing Auto-linking === #testing |
| | 424 | |
| | 425 | Testing the auto-link feature is somewhat convoluted, and |
| | 426 | requires access to a compiler that supports the feature: refer |
| | 427 | to |
| | 428 | [http://www.boost.org/doc/libs/release/libs/config/test/link/test/Jamfile.v2 libs/config/test/link/test/Jamfile.v2] |
| | 429 | for an example. |