Re: [boost] [system] Why is this not header-only?

I'd like to drop this custom class and instead use the ones provided by the recently introduced Boost.System. However, Boost.System is a binary library, while Boost.Process is currently a header-only library.
IIRC, someone asked recently why asio requires -lboost_system at link time. In my personal opinion, C++ wrappers for OS services should not be header-only. I would prefer asio, process, shmem and the like to be all consistent with boost.filesystem. Opinions?
Personally, I'd prefer to keep it that way if possible because it is much easier to use it in third-party code.
I don't think that we should follow masses and put everything in header files. There is an autolink on some systems, we could use this feature. The only problem is that people still "have to" follow an instruction for building those libraries. It would be interesting to take a big C++ project that depends on many boost libraries and consists of many shared libraries and analyze an overhead introduced by function defined in boost headers. I suspect many duplicates. -- Alexander Nasonov

Oh gosh yes. Having things in headers because it makes it 'easier to compile' hurts compile times in the long run. Its just not good practice and I suspect a non-empty subset of new boost users are also new to C++. The only executable code that should defined be in headers at all are templates (and even then, could possibly be split up into forward declarations and implementations) and inline functions. When I change implementation, I think "if I change this, how much recompilation is necessary?" If its more than just the immediate code, I double check. Even with templates, there are some things that can be moved to a separately compiled file. But I suspect this wasn't your real question :-D PS: Sorry for the TP. One day I will figure out "outlook web access" -----Original Message----- From: boost-bounces@lists.boost.org on behalf of Alexander Nasonov Sent: Mon 4/2/2007 7:35 AM To: boost@lists.boost.org Subject: Re: [boost] [system] Why is this not header-only?
I'd like to drop this custom class and instead use the ones provided by the recently introduced Boost.System. However, Boost.System is a binary library, while Boost.Process is currently a header-only library.
IIRC, someone asked recently why asio requires -lboost_system at link time. In my personal opinion, C++ wrappers for OS services should not be header-only. I would prefer asio, process, shmem and the like to be all consistent with boost.filesystem. Opinions?

Sohail Somani wrote:
Oh gosh yes. Having things in headers because it makes it 'easier to compile' hurts compile times in the long run.
Get a faster build machine and/or use pre-compiled headers -- really.
Its just not good practice and I suspect a non-empty subset of new boost users are also new to C++.
5 years ago I believed it was a serious issue too -- I've substantially changed my mind. And not in small part by using asio (and other boost libs) as header only. It's extremely nice to not need to figure out how to build and link. You can get started with so trivially with an all header library -- and I think that frequently it's trouble getting over that first hump that stops people from using libs. So if the barrier is lower more people will use the libs. Alexander Nasonov wrote:
IIRC, someone asked recently why asio requires -lboost_system at link time.
In my personal opinion, C++ wrappers for OS services should not be header-only. I would prefer asio, process, shmem and the like to be all consistent with boost.filesystem. Opinions?
I think they should, if practical, have an option to be used as header only. Implementations should be put in .ipp files and controlled by a macro like: BOOST_ALLOW_ALL_HEADER_WITH_SYSTEM_INCLUDES If you don't add this macro then you have to link the library -- otherwise it's header only. I realize it's a bit more work for the library developers, but that way we can have it both ways. I see this as like having an 'all inclusive' header for a library even though there are more granular headers -- it makes it easy to get started and it actually handles the majority of the cases where people don't care about optimizing 'include performance'. Jeff

Hello Jeff,
Alexander Nasonov wrote:
IIRC, someone asked recently why asio requires -lboost_system at link time.
In my personal opinion, C++ wrappers for OS services should not be header-only. I would prefer asio, process, shmem and the like to be all consistent with boost.filesystem. Opinions?
I think they should, if practical, have an option to be used as header only. Implementations should be put in .ipp files and controlled by a macro like:
BOOST_ALLOW_ALL_HEADER_WITH_SYSTEM_INCLUDES
If you don't add this macro then you have to link the library -- otherwise it's header only. I realize it's a bit more work for the library developers, but that way we can have it both ways. I see this as like having an 'all inclusive' header for a library even though there are more granular headers -- it makes it easy to get started and it actually handles the majority of the cases where people don't care about optimizing 'include performance'.
Although the discussion is slipping away from the original question, I must say I 100% agree with Jeff. The best solution is to give user a choice whether to link or to go header-only (where possible). And in my opinion such solution should be unified for all boost libs. We already have the BOOST_USE_WINDOWS_H macro, why not extend it to something like BOOST_USE_OS_NATIVE_HEADERS? I think this would settle the problem once and for all. The only problem is I'm not sure how such a transition should be organized. -- Best regards, Andrey mailto:andysem@mail.ru

On 02/04/2007, at 19:11, Andrey Semashev wrote:
Although the discussion is slipping away from the original question, I must say I 100% agree with Jeff. The best solution is to give user a choice whether to link or to go header-only (where possible). And in my opinion such solution should be unified for all boost libs. We already have the BOOST_USE_WINDOWS_H macro, why not extend it to something like BOOST_USE_OS_NATIVE_HEADERS? I think this would settle the problem once and for all. The only problem is I'm not sure how such a transition should be organized.
Although I liked this at first too, it seems to me it cannot be always implemented. I was now trying to add a singleton to my library and I can't do it with headers alone. I need to maintain the pointer to the global instance somewhere, and that means having a global variable which cannot be defined in a header (or otherwise you'll get duplicates). Unless I'm missing something, that is... -- Julio M. Merino Vidal <jmmv84@gmail.com>

----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Julio M. Merino Vidal Sent: 03 April 2007 17:00 To: boost@lists.boost.org Subject: Re: [boost] [system] Why is this not header-only?
On 02/04/2007, at 19:11, Andrey Semashev wrote:
Although the discussion is slipping away from the original question, I must say I 100% agree with Jeff. The best solution is to give user a choice whether to link or to go header-only (where possible). And in my opinion such solution should be unified for all boost libs. We already have the BOOST_USE_WINDOWS_H macro, why not extend it to something like BOOST_USE_OS_NATIVE_HEADERS? I think this would settle the problem once and for all. The only problem is I'm not sure how such a transition should be organized.
Although I liked this at first too, it seems to me it cannot be always implemented. I was now trying to add a singleton to my library and I can't do it with headers alone. I need to maintain the pointer to the global instance somewhere, and that means having a global variable which cannot be defined in a header (or otherwise you'll get duplicates). Unless I'm missing something, that is...
Static variable in an inline function. -- Martin Bonner Project Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com

Hello Martin, Tuesday, April 3, 2007, 8:07:38 PM, you wrote: [snip]
Although I liked this at first too, it seems to me it cannot be always implemented. I was now trying to add a singleton to my library and I can't do it with headers alone. I need to maintain the pointer to the global instance somewhere, and that means having a global variable which cannot be defined in a header (or otherwise you'll get duplicates). Unless I'm missing something, that is...
Static variable in an inline function.
Or a static member of a template class, which is instantiated with only one template parameters set. But, as Jeff Garland noted, this is only suitable if your header is used only in one module. Otherwise the singleton should be extracted to a separate module (.dll or .so). Though this is not necessary on Linux. -- Best regards, Andrey mailto:andysem@mail.ru

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Martin Bonner
Although I liked this at first too, it seems to me it cannot be always implemented. I was now trying to add a singleton to my library and I can't do it with headers alone. I need to maintain the pointer to the global instance somewhere, and that means having a global variable which cannot be defined in a header (or otherwise you'll get duplicates). Unless I'm missing something, that is...
Static variable in an inline function.
Oh come on guys, aren't we just getting silly? To avoid what? Adding cpp files to the build?

Sohail Somani wrote:
Oh come on guys, aren't we just getting silly? To avoid what? Adding cpp files to the build?
Yeah, actually. Here's a response to your earlier mail: Sohail Somani wrote:
This is a non-issue. With header-only libraries, step 1 is the only thing that disappears and you might even be lucky enough to disable language extensions in your project.
I assure you, given the number of posts on this list and the -user list, building boost is something people have issues with. I've had to answer the 'link errors' question many times for date-time -- even though this is basic knowledge that all developers should have, and it's "all in the docs".
Actually, step 1 is replaced with "try build with bjam, send emails to the mailing list"
Right, and best case, you're into an hour or two of fiddling around that had nothing to do with what you were trying to accomplish -- which is simply to read the docs and use the library. And while I understand the sentiment the C++ programmers have been dealing with this for years, etc, etc.. it's still really nice when getting started with a new lib that the barrier to entry is more like a scripting language than traditional C/C++ libs. Jeff

[mailto:boost-bounces@lists.boost.org] On Behalf Of Jeff Garland
Sohail Somani wrote:
Oh come on guys, aren't we just getting silly? To avoid what? Adding cpp files to the build?
Yeah, actually. Here's a response to your earlier mail:
Sorry I must have missed it.
Sohail Somani wrote:
This is a non-issue. With header-only libraries, step 1 is the only thing that disappears and you might even be lucky enough to disable language extensions in your project.
I assure you, given the number of posts on this list and the -user list, building boost is something people have issues with. I've had to answer the 'link errors' question many times for date-time -- even though this is basic knowledge that all developers should have, and it's "all in the docs".
I'm going to say that people have problems building boost with bjam unless you can prove otherwise. In my opinion, bjam is the blocker. Not the fact that you have to build some files. Boost.Config is the key to making it easy.
Actually, step 1 is replaced with "try build with bjam, send emails to the mailing list"
Right, and best case, you're into an hour or two of fiddling around that had nothing to do with what you were trying to accomplish -- which is simply to read the docs and use the library. And while I understand the sentiment the C++ programmers have been dealing with this for years, etc, etc.. it's still really nice when getting started with a new lib that the barrier to entry is more like a scripting language than traditional C/C++ libs.
Agreed. I don't see why "add boost/libs/<lib>/src/*.cpp to your 'visual studio project'" is harder than export PYTHONPATH=/path/to/my/fancy/new/lib:$PYTHONPATH. Indeed, on Windows, this is even more annoying. If the policy is: *Don't* depend on bjam for your build, and I've found most separately compiled Boost libraries *don't* do this, then add src/*.cpp to your build is the better solution. Am I the only one on this list who thinks this way (or is willing to speak up about it)? I've seen developers refuse to work on a library until they've factored it into appropriate separately compiled units. Sohail

Sohail Somani wrote:
[mailto:boost-bounces@lists.boost.org] On Behalf Of Jeff Garland
Sohail Somani wrote:
Oh come on guys, aren't we just getting silly? To avoid what? Adding cpp files to the build? Yeah, actually. Here's a response to your earlier mail:
Sorry I must have missed it.
No, I wrote it and then never sent it :-)
I'm going to say that people have problems building boost with bjam unless you can prove otherwise. In my opinion, bjam is the blocker. Not the fact that you have to build some files. Boost.Config is the key to making it easy.
Nope, but realize, it's not just bjam -- it's more complicated than that. That might have actually compiled boost. At a minimum, though they have to pick the right lib version: debug-multithread, release-nomulththread, etc -- so there's a bit of work there. date-time is a bit special in that it turns out you can use most of it as header only. So they start doing that, and then they call to_simple_string and suddenly their code won't link. They never bothered to read the docs that explain it. But I understand -- I hate to read the docs too when I'm learning a new library.
Agreed. I don't see why "add boost/libs/<lib>/src/*.cpp to your 'visual studio project'" is harder than export PYTHONPATH=/path/to/my/fancy/new/lib:$PYTHONPATH. Indeed, on Windows, this is even more annoying.
If the policy is: *Don't* depend on bjam for your build, and I've found most separately compiled Boost libraries *don't* do this, then add src/*.cpp to your build is the better solution.
I"m a little confused. The official build system is bjam for all libs, tests, examples. Some libs provide other options. As you say, it's not that hard in some IDE's to include the files into your own library, but it's not really that hard to run bjam either. My only point is that it's harder and it's off-task.
Am I the only one on this list who thinks this way (or is willing to speak up about it)? I've seen developers refuse to work on a library until they've factored it into appropriate separately compiled units.
I'm completely lost what you mean now... Jeff

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jeff Garland
I'm going to say that people have problems building boost with bjam unless you can prove otherwise. In my opinion, bjam is the blocker. Not the fact that you have to build some files. Boost.Config is the key to making it easy.
Nope, but realize, it's not just bjam -- it's more complicated than that. That might have actually compiled boost. At a minimum, though they have to pick the right lib version: debug-multithread, release-nomulththread, etc -- so there's a bit of work there.
Yes but if you compile boost along with your code, what is the problem? I used to be of the opinion that I should use pre-built boost. Not anymore. I prefer building it myself. Why should I compile a piece of code more than once in a specific build? If 3 different libraries in my build use boost regex, well damnit I don't want to build boost regex 3 times!
I"m a little confused. The official build system is bjam for all libs, tests, examples. Some libs provide other options. As you say, it's not that hard in some IDE's to include the files into your own library, but it's not really that hard to run bjam either. My only point is that it's harder and it's off-task.
It is *definitely* harder to run bjam than add the cpp files to your "project". I think I can say this as a Boost user. I say this also while watching another email popping into the inbox with "Troubles with build boost". Ok, self-configuring hpp files are great. Why not have self-configuring cpp files? Another reason is that I am of the opinion that if boost regex cannot be built with certain warnings on, that should not affect the rest of my code. Well, with header-only, it does. Should I be punished for this?
Am I the only one on this list who thinks this way (or is willing to speak up about it)? I've seen developers refuse to work on a library until they've factored it into appropriate separately compiled units.
I'm completely lost what you mean now...
I mean, there have been cases where people have had to work on a library where a sh*tload of code is in the header, but they refused to work on that code until it was separately compiled, appropriately inlined functions and templates excluded obviously. Sohail PS: I already get punished with boost.thread if I disable language extensions with MSVC. I've come to terms with it.

Sohail Somani wrote:
-----Original Message-----
Yes but if you compile boost along with your code, what is the problem? I used to be of the opinion that I should use pre-built boost. Not anymore. I prefer building it myself.
That's your choice, but the whole point of this is that it's empirically harder to deal with built-libraries. It's not a theory, as far as I'm concerned, it's a fact based on reading this mailing list for years. With libraries like smart_ptr the 'how to build' issue just doesn't come up because it's simply effortless. With 'built' libs it comes up frequently.
Why should I compile a piece of code more than once in a specific build? If 3 different libraries in my build use boost regex, well damnit I don't want to build boost regex 3 times!
Ok, with template code "inclusion" != "compile". It's not free, but it's not as expensive as a full compile either.
It is *definitely* harder to run bjam than add the cpp files to your "project". I think I can say this as a Boost user. I say this also while watching another email popping into the inbox with "Troubles with build boost".
In my case, I typically don't use and IDE, so bjam is far easier than writing a Makefile. But the nice thing about bjam is that, like emacs, it behaves basically the same on every platform. So I don't have to learn some fancy platform specific ide to run and test on a different platform. So, there are some real benefits to bjam for cross-platform development that 'whatever-ide' does not posses.
Ok, self-configuring hpp files are great. Why not have self-configuring cpp files?
Another reason is that I am of the opinion that if boost regex cannot be built with certain warnings on,
Patches, I'm sure, would be graciously accepted ;-)
that should not affect the rest of my code. Well, with header-only, it does. Should I be punished for this?
No worries. If it can't be fixed, use //darn regex has warnings -- turn it off! #pragma warning(push) #pragma warning(disable : xxxx) #include "boost/regex.hpp" #pragma warning(pop) Of course, regex isn't 'all header' so I'm not sure why we're discussing it as an example. And with VC8 you have to do this for much of the standard library as well: http://www.boost.org/tools/build/v1/vc-8_0-tools.html
I mean, there have been cases where people have had to work on a library where a sh*tload of code is in the header, but they refused to work on that code until it was separately compiled, appropriately inlined functions and templates excluded obviously.
Well, I assume you're talking about in your own developers because I'm not aware of a boost library that doesn't meet the 'appropriately inlined or template' exclusion.
PS: I already get punished with boost.thread if I disable language extensions with MSVC. I've come to terms with it.
At the risk of going off-topic, what was the punishment? I'm guessing you might be using an old version of msvc which can't handle thread (or stl for that matter) without the 'extensions'? In any case, have you reported it? If you have, it's always possible the fix is bottled up in the 1.34 release process... Jeff

Since what I have to say is not a response to any specific message, I'm only answering to the thread. I'm very inclined to build libraries, rather than header-only. And that's not *only* because of compile-times. But visual C++ chokes on very big translation files, emiting errors about the compiler being out of keys. The only workaround I found was splitting it in more files and hiding some dependencies. This is quite common when using together very big libraries, e.g. serialization, multi_index, spirit, etc. Most of the time I don't need them together, but there are times when the same function uses more than one. Splitting it means an artificial separation and harder maintenance. -- Felipe Magno de Almeida

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Felipe Magno de Almeida Sent: Wednesday, April 04, 2007 2:25 PM Subject: Re: [boost] [system] Why is this not header-only?
Since what I have to say is not a response to any specific message, I'm only answering to the thread. I'm very inclined to build libraries, rather than header-only. And that's not *only* because of compile-times. But visual C++ chokes on very big translation files, emiting errors about the compiler being out of keys. The only workaround I found was splitting it in more files and hiding some dependencies. This is quite common when using together very big libraries, e.g. serialization, multi_index, spirit, etc. Most of the time I don't need them together, but there are times when the same function uses more than one. Splitting it means an artificial separation and harder maintenance.
There are other reasons: * It's easier to put standalone libs into shared libs (i.e. for smaller executable sizes, text segment sharing, whatever) * With header-only libs you loose almost all the flexibility for fine-grained adjustments to the binary code (optimisation, abi etc.) That's not to say, that header-only libs are bad. But it would be bad to require all libs to be header-only or even to officially state they are preferred for boost, at least IMHO. cheers, aa -- Andreas Ames | Programmer | Comergo GmbH | ames AT avaya DOT com Sitz der Gesellschaft: Stuttgart Registergericht: Amtsgericht Stuttgart - HRB 22107 Geschäftsführer: Andreas von Meyer zu Knonow, Udo Bühler, Thomas Kreikemeier

----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Sohail Somani Sent: 03 April 2007 22:22 To: boost@lists.boost.org Subject: Re: [boost] [system] Why is this not header-only?
[mailto:boost-bounces@lists.boost.org] On Behalf Of Jeff Garland
Sohail Somani wrote:
Oh come on guys, aren't we just getting silly? To avoid what? Adding cpp files to the build?
Yeah, actually. Here's a response to your earlier mail:
Sorry I must have missed it.
Sohail Somani wrote:
This is a non-issue. With header-only libraries, step 1 is the only thing that disappears and you might even be lucky enough to disable language extensions in your project.
I assure you, given the number of posts on this list and the -user list, building boost is something people have issues with. I've had to answer the 'link errors' question many times for date-time -- even though this is basic knowledge that all developers should have, and it's "all in the docs".
I'm going to say that people have problems building boost with bjam unless you can prove otherwise. In my opinion, bjam is the blocker. Not the fact that you have to build some files. Boost.Config is the key to making it easy.
Actually, step 1 is replaced with "try build with bjam, send emails to the mailing list"
Right, and best case, you're into an hour or two of fiddling around that had nothing to do with what you were trying to accomplish -- which is simply to read the docs and use the library. And while I understand the sentiment the C++ programmers have been dealing with this for years, etc, etc.. it's still really nice when getting started with a new lib that the barrier to entry is more like a scripting language than traditional C/C++ libs.
Agreed. I don't see why "add boost/libs/<lib>/src/*.cpp to your 'visual studio project'" is harder than export PYTHONPATH=/path/to/my/fancy/new/lib:$PYTHONPATH. Indeed, on Windows, this is even more annoying.
If the policy is: *Don't* depend on bjam for your build, and I've found most separately compiled Boost libraries *don't* do this, then add src/*.cpp to your build is the better solution.
Am I the only one on this list who thinks this way (or is willing to speak up about it)? I've seen developers refuse to work on a library until they've factored it into appropriate separately compiled units.
I don't know if you're the ONLY one, but I would have to be pretty pushed to touch the internals of a library (as in, if there's an easily patchable bug, I would prefer to work around it until the next release). If shared_ptr had not been header only, I am pretty sure I could not have got it in use in my company. There is a BIG difference between "I've added a header tree to the 'install' folder in Source Control", and "you need to install this chunky library on your system in order to be able to develop this project". -- Martin Bonner Project Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com

On 03/04/2007, at 22:54, Jeff Garland wrote:
Right, and best case, you're into an hour or two of fiddling around that had nothing to do with what you were trying to accomplish -- which is simply to read the docs and use the library. And while I understand the sentiment the C++ programmers have been dealing with this for years, etc, etc.. it's still really nice when getting started with a new lib that the barrier to entry is more like a scripting language than traditional C/C++ libs.
Exactly. I have recently been experimenting with other languages, and their ability to painlessly install and use external modules is great. In C/C++, it's certainly more difficult, and in the case of Boost, it is painful for binary libraries. And I know what I'm talking about fairly well: I'm the maintainer of the Boost packages in pkgsrc (a package system that runs under e.g. NetBSD and OS X) and I had a very hard time to get the packages to work and to get those programs that need the binary libs to compile fine. The "suffixes" and versioning of Boost make things more complex when compared to those libraries built by the typical automake/autoconf/libtool system. (I have almost no experience with Win32, so I don't know what problems arise there though.) When I was suggested to code Boost.Process as headers-only, I was reluctant at first but came to like it in the end. The easiness in using the resulting library is very convenient, and you avoid all the problems of binary libraries. I wish I could avoid having to convert the library to binary just because Boost.System... but I've been told recently that Boost.Asio has the same problem... -- Julio M. Merino Vidal <jmmv84@gmail.com>

On Tue, 3 Apr 2007 23:57:21 +0200 "Julio M. Merino Vidal" <jmmv84@gmail.com> wrote:
programs that need the binary libs to compile fine. The "suffixes" and versioning of Boost make things more complex when compared to those libraries built by the typical automake/autoconf/libtool system. (I have almost no experience with Win32, so I don't know what problems arise there though.)
I don't mind the suffixes. In fact, I like them. It gives me flexibility and my build environment automatically selects the proper ones. The part that bothers me is the Boost.Build system itself. It is extremely complex, hard to use, and difficult to manage anything other than "out of the box" builds. If you want to make any teeny-tiny-minor change, it's like pulling a bad tooth from a pregnant walrus.

Jeff Garland wrote:
Sohail Somani wrote:
Oh come on guys, aren't we just getting silly? To avoid what? Adding cpp files to the build?
Yeah, actually. Here's a response to your earlier mail:
Sohail Somani wrote:
This is a non-issue. With header-only libraries, step 1 is the only thing that disappears and you might even be lucky enough to disable language extensions in your project.
I assure you, given the number of posts on this list and the -user list, building boost is something people have issues with. I've had to answer the 'link errors' question many times for date-time -- even though this is basic knowledge that all developers should have, and it's "all in the docs".
I fully agree with you that building Boost has been somewhat of a headache in the past but without knowing the Build system's version 2 I am hoping this would improve on 1.34 and up. Maybe that is because I would like to believe that understanding bjam in V2 will be easier than for V1, or that the docuentation for doing so will be better, and therefore fixing any problems locally might be easier. I think that the general reason for putting code in a library rather than a header file has not been touched upon, and that is that header files will have inline code as opposed to a library. For template programmers this is normal because of the way that templates are largely used in C++, which is from header files where the declarations and definitions all reside. For non-template programming, or even some template programming where a good deal of code may be outside of template definitions, using library with the header files is more of a standard, at least for people who have been trained that way. It is quite possible that inline code is not an issue and that the tradeoff of greater size for the slightly faster speed of inline code in these days of multi-gigabyte computer memory is not that important anymore. But I know that I was trained to consider large amounts of inline code to be bad as opposed to a reusable library, and it is hard to break old habits. But I do understand that templates are a different case in C++ and largely require a different model.

----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Edward Diener Sent: 03 April 2007 23:31 To: boost@lists.boost.org Subject: Re: [boost] [system] Why is this not header-only?
I think that the general reason for putting code in a library rather than a header file has not been touched upon, and that is that header files will have inline code as opposed to a library.
It will have lots of functions that are declared "inline".
It is quite possible that inline code is not an issue and that the tradeoff of greater size for the slightly faster speed of inline code
Are you under the impression that having functions declared "inline" means that the compiler will always inline them? Certainly for the compiler I use (Visual C++) this is very far from the case. It will inline small functions, but doesn't bother for larger ones. This does mean the same function is present in many object files, but there will be only one copy in the final exe (or rather, one copy in each exe and dll that uses the function). -- Martin Bonner Project Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com

Martin Bonner wrote:
----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Edward Diener Sent: 03 April 2007 23:31 To: boost@lists.boost.org Subject: Re: [boost] [system] Why is this not header-only?
I think that the general reason for putting code in a library rather than a header file has not been touched upon, and that is that header files will have inline code as opposed to a library.
It will have lots of functions that are declared "inline".
Right.
It is quite possible that inline code is not an issue and that the tradeoff of greater size for the slightly faster speed of inline code
Are you under the impression that having functions declared "inline" means that the compiler will always inline them? Certainly for the compiler I use (Visual C++) this is very far from the case. It will inline small functions, but doesn't bother for larger ones. This does mean the same function is present in many object files, but there will be only one copy in the final exe (or rather, one copy in each exe and dll that uses the function).
Thanks for the heads up. I was too quickly and erroneously thinking that functions in a header file, as opposed to a .cpp source file, were automatically "inline". That comes from my own practice with non-template code of always putting function declarations in header files and their definitions in the .cpp source files, and never putting code in header files. Now I realize that putting code in header files, for non-templates, is the equivalent of adding .cpp files to a compilation. In this header file distribution model for non-template code, one is adding the code to each module using it, somewhat like a static library, as opposed to sharing it in a separate shared library if it uses common code. I still prefer the latter for non-template code when it comes to reusability. I do not think the problem in Boost has been an all header file distribution versus a mixed header file and library distribution so much as it has been the fact that building libraries via bjam has led to problems with certain distributions. Perhaps with version 2 of the build system along with better documentation in using it, most of the previous problems will go away.

Hello Sohail, Wednesday, April 4, 2007, 12:18:44 AM, you wrote:
Although I liked this at first too, it seems to me it cannot be always implemented. I was now trying to add a singleton to my library and I can't do it with headers alone. I need to maintain the pointer to the global instance somewhere, and that means having a global variable which cannot be defined in a header (or otherwise you'll get duplicates). Unless I'm missing something, that is...
Static variable in an inline function.
Oh come on guys, aren't we just getting silly? To avoid what? Adding cpp files to the build?
These files have to be added to every project that uses the lib which looks a bit strange in the first place. Or were you speaking about compiling these .cpp into .lib or .dll and linking? Externally linked modules (.dll or .so) often give a lot of headache, though sometimes they are really needed. The most common problems are: - The dll needs to be built first. That means I have to go read the docs how to do it, what it depends on and compile. - Not all compilers have auto-link feature (GCC, doesn't, BTW). So I have to modify my projects to link against it. Note that this also implies that the import .lib or .so has to be available during this process. This may be easy to guarantee in small local builds but gives additional problems when running large distributed and parallel automatic (nightly) builds. - After building the application I will need this dll somewhere in my PATH or LD_LIBRARYPATH to execute the app. This means configuration problems - everywhere the app needs to be executed the dll should be available in one of the aforementioned paths. - Even if the dll is available, I still don't know wether it is _my_ dll, not the one that user or another application forgot to delete. This is where funny things like "why the hell it crashes on your PC? it works perfectly for me" happen. As a special case of this, I'm not sure the dll is linked with the same CRT as the application either. - On Linux (at least, may be not only there) there are a lot of problems with symbols visibility and their aliasing, especially in relatively large applications. Often such problems are quite difficult to track and isolate. - There may be problems with some core C++ features like RTTI and exceptions when used across dll boundaries. Linux is more affected to this. I guess, this may also take place when compiled by different compatible compilers modules interact (i.e. different versions of the same compiler or compatible compilers like VC and ICL). - There are various problems related to dll load/unload order and dependencies between them. - Finally, I have to redistribute the dll with my application and make sure that it will be correctly installed on the user's machine. And in return I only get reduced compilation time and application binary size (the dll will still be needed to run and distribute, but in case of a quick update I may provide only a small-sized exe without the unaffected dll). Honestly, after all experience I had so far I almost always prefer header-only solution, where possible and reasonable. -- Best regards, Andrey mailto:andysem@mail.ru

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Andrey Semashev
Hello Sohail,
Hi Andrey, thanks for joining in the fun :-)
Wednesday, April 4, 2007, 12:18:44 AM, you wrote:
Oh come on guys, aren't we just getting silly? To avoid what? Adding cpp files to the build?
These files have to be added to every project that uses the lib which looks a bit strange in the first place. Or were you speaking about compiling these .cpp into .lib or .dll and linking?
Well I was talking about getting the samples running which I thought is the biggest barrier to using Boost. But I was assuming that eventually the user would be happy enough to then compile it into a library themselves or figure out the magic of bjam. The thing is, I've had these issues so many times (3rd-party libraries) that my build can basically handle any weird build requirements. So for me, building a new library is easy-peasy. I feel I will be getting punished because I solved the problem in a somewhat non-stupid way. I can't imagine any C++ developer not having solved this problem for themselves. Indeed the boost guys did by writing Boost Jam.
Externally linked modules (.dll or .so) often give a lot of headache, though sometimes they are really needed. The most common problems are:
- The dll needs to be built first. That means I have to go read the docs how to do it, what it depends on and compile.
Ok, and? You have to do this with everything you use. If you start shipping "header-only" libraries, then you're just delaying the problem because you ship all the "libraries". The equivalent would be to compile all boost libraries into one giant dll. If you start shipping libraries separately (i.e. out of sequence releases - which is in the plan, I believe), the problem reappears.
- Not all compilers have auto-link feature (GCC, doesn't, BTW). So I have to modify my projects to link against it. Note that this also implies that the import .lib or .so has to be available during this process. This may be easy to guarantee in small local builds but gives additional problems when running large distributed and parallel automatic (nightly) builds.
Use a build system that can handle it. This is C++ after all.
- After building the application I will need this dll somewhere in my PATH or LD_LIBRARYPATH to execute the app. This means configuration problems - everywhere the app needs to be executed the dll should be available in one of the aforementioned paths
Use a static library if this is a real issue for you.
- Even if the dll is available, I still don't know wether it is _my_ dll, not the one that user or another application forgot to delete. This is where funny things like "why the hell it crashes on your PC? it works perfectly for me" happen. As a special case of this, I'm not sure the dll is linked with the same CRT as the application either.
Same as above.
- On Linux (at least, may be not only there) there are a lot of problems with symbols visibility and their aliasing, especially in relatively large applications. Often such problems are quite difficult to track and isolate.
Use a linker script. Its pretty straightforward.
- There may be problems with some core C++ features like RTTI and exceptions when used across dll boundaries. Linux is more affected to this. I guess, this may also take place when compiled by different compatible compilers modules interact (i.e. different versions of the same compiler or compatible compilers like VC and ICL)
I'll have to say that the best C++ interface is a C interface. Unless you ship your source. Which boost does. \o/
- There are various problems related to dll load/unload order and dependencies between them.
You'll have to specify where this is an issue with boost.
- Finally, I have to redistribute the dll with my application and make sure that it will be correctly installed on the user's machine.
Use a static library.
And in return I only get reduced compilation time and application binary size (the dll will still be needed to run and distribute, but in case of a quick update I may provide only a small-sized exe without the unaffected dll). Honestly, after all experience I had so far I almost always prefer header-only solution, where possible and reasonable.
Same as above.

Hello Sohail, Wednesday, April 4, 2007, 2:58:33 AM, you wrote:
Well I was talking about getting the samples running which I thought is the biggest barrier to using Boost. But I was assuming that eventually the user would be happy enough to then compile it into a library themselves or figure out the magic of bjam.
But don't we need to compile Boost first in order to run examples? IMO, we're walking circles here.
The thing is, I've had these issues so many times (3rd-party libraries) that my build can basically handle any weird build requirements. So for me, building a new library is easy-peasy. I feel I will be getting punished because I solved the problem in a somewhat non-stupid way. I can't imagine any C++ developer not having solved this problem for themselves. Indeed the boost guys did by writing Boost Jam.
You see, I, as a library single user, would like to "plug'n'play" the lib, not putting any effort in the building process. Sure, in industrial-sized development world the building process is settled this or that way, but still someone has to put a lot effort in it.
Externally linked modules (.dll or .so) often give a lot of headache, though sometimes they are really needed. The most common problems are:
- The dll needs to be built first. That means I have to go read the docs how to do it, what it depends on and compile.
Ok, and? You have to do this with everything you use. If you start shipping "header-only" libraries, then you're just delaying the problem because you ship all the "libraries". The equivalent would be to compile all boost libraries into one giant dll. If you start shipping libraries separately (i.e. out of sequence releases - which is in the plan, I believe), the problem reappears.
I think, you got me a bit wrong here. I only noted that one has to put effort to build the lib instead of just using it on spot. In regard of boost releases separation, I don't quite see how header-onlyness is connected to this. The library is a library, wether or not it is header-only. We might separately ship Boost.Any, for example. The only thing we have to do is to define libs it depends on and their least versions that are required for the specific library release.
- Not all compilers have auto-link feature (GCC, doesn't, BTW). So I have to modify my projects to link against it. Note that this also implies that the import .lib or .so has to be available during this process. This may be easy to guarantee in small local builds but gives additional problems when running large distributed and parallel automatic (nightly) builds.
Use a build system that can handle it. This is C++ after all.
See my previous arguments about "plug'n'play". In commercial development it's time=money, in a personal builds it's just time and effort. [snip]
- There may be problems with some core C++ features like RTTI and exceptions when used across dll boundaries. Linux is more affected to this. I guess, this may also take place when compiled by different compatible compilers modules interact (i.e. different versions of the same compiler or compatible compilers like VC and ICL)
I'll have to say that the best C++ interface is a C interface. Unless you ship your source. Which boost does. \o/
<sigh> I was hoping C++ libs could have C++ interface. Actually the problem is present regardless of the source availability.
- There are various problems related to dll load/unload order and dependencies between them.
You'll have to specify where this is an issue with boost.
I wasn't speaking about specifically boost here. [snip] The bottom line. I agree that these problems have solutions. But in a header-only case they wouldn't have even exist in the first place. I must also say I agree that many libraries _should_ be dll (just imagine something like xerces or ICU header-only... boo) but mostly these are large and heavy libs. Small libs (like singleton) and various wrapper-style libs (e.g. thread, asio) should have a header-only option, if possible. And since we have different opinions here, the user-defined configuration is the best choice, IMHO. -- Best regards, Andrey mailto:andysem@mail.ru

2007/4/4, Martin Bonner <Martin.Bonner@pi-shurlok.com>: Static variable in an inline function.
Yes, I agree. Something like: // st.h class st { private: st(){} public: static st* get_instance() { static st* inst = new st; return inst; } };

On Thursday 05 April 2007, Kevin Yuan wrote:
2007/4/4, Martin Bonner <Martin.Bonner@pi-shurlok.com>: Static variable in an inline function.
Am I missing something or static variables in inline functions are considered BAD PRACTICE?
Yes, I agree. Something like:
// st.h class st { private: st(){} public: static st* get_instance() { static st* inst = new st; return inst; } };
IIRC if get_instance() will be inlined and 2 translation units will have their own copy of get_instance() then there will be two st instances in the finall app... witch in case of a singleton is BAD. ps: i only had 2 zips of coffee so i might be missing something ... -- Best Regards, Iulian Margarintescu http://www.erata.net eti@erata.net (spamassassin & pf & spamd all said it's OK to make it public ;-) ) Key ID: 0x03176E5CEDEFF7AB I prefer plain text email

Iulian M <eti@erata.net> writes:
On Thursday 05 April 2007, Kevin Yuan wrote:
2007/4/4, Martin Bonner <Martin.Bonner@pi-shurlok.com>: Static variable in an inline function.
Am I missing something or static variables in inline functions are considered BAD PRACTICE?
Yes, I agree. Something like:
// st.h class st { private: st(){} public: static st* get_instance() { static st* inst = new st; return inst; } };
IIRC if get_instance() will be inlined and 2 translation units will have their own copy of get_instance() then there will be two st instances in the finall app... witch in case of a singleton is BAD.
ps: i only had 2 zips of coffee so i might be missing something ...
Have another cup of coffee then, because you are missing something. The compiler is required to ensure that there is only one copy of statics declared in inline functions, even if that function is defined in more than one translation unit, because otherwise you get precisely the problem you describe. Anthony -- Anthony Williams Just Software Solutions Ltd - http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL

Anthony Williams wrote:
Iulian M <eti@erata.net> writes:
IIRC if get_instance() will be inlined and 2 translation units will have their own copy of get_instance() then there will be two st instances in the finall app... witch in case of a singleton is BAD.
ps: i only had 2 zips of coffee so i might be missing something ...
Have another cup of coffee then, because you are missing something.
The compiler is required to ensure that there is only one copy of statics declared in inline functions, even if that function is defined in more than one translation unit, because otherwise you get precisely the problem you describe.
It can, in fact, trivially happen. Try linking in a couple static libs on windows that call this function...you'll get 2. Jeff

Jeff Garland wrote:
Anthony Williams wrote:
Iulian M <eti@erata.net> writes:
IIRC if get_instance() will be inlined and 2 translation units will have their own copy of get_instance() then there will be two st instances in the finall app... witch in case of a singleton is BAD.
ps: i only had 2 zips of coffee so i might be missing something ...
Have another cup of coffee then, because you are missing something.
The compiler is required to ensure that there is only one copy of statics declared in inline functions, even if that function is defined in more than one translation unit, because otherwise you get precisely the problem you describe.
It can, in fact, trivially happen. Try linking in a couple static libs on windows that call this function...you'll get 2.
You will on MSVC 6.0 because of a compiler bug. Inlining doesn't change semantics.

Kevin Yuan wrote:
2007/4/4, Martin Bonner <Martin.Bonner@pi-shurlok.com>: Static variable in an inline function.
Yes, I agree. Something like:
// st.h class st { private: st(){} public: static st* get_instance() { static st* inst = new st; return inst; } };
Yeah sure, classic Meyer's singleton. Couple problems. It's not thread safe and you could easily inline this code into multiple translation units. In both cases you might wind up with multiple copies of your singleton in the process. It's this sort of thing that makes true singletons devilishly hard to do... Jeff

----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jeff Garland Sent: 05 April 2007 14:55 To: boost@lists.boost.org Subject: Re: [boost] [system] Why is this not header-only?
Kevin Yuan wrote:
2007/4/4, Martin Bonner <Martin.Bonner@pi-shurlok.com>: Static variable in an inline function.
Yes, I agree. Something like:
// st.h class st { private: st(){} public: static st* get_instance() { static st* inst = new st; return inst; } };
Yeah sure, classic Meyer's singleton. Couple problems.
It's not thread safe
Granted. (And this could be a major issue).
and you could easily inline this code into multiple translation units. That's harmless. The compiler is supposed to make sure there is only one copy of the singleton variable.
BUT The standard doesnt recognize the existance of DLLs/SOs - and you WILL get multiple copies of the singleton variable in different DLLs.
It's this sort of thing that makes true singletons devilishly hard to do...
No argument there! -- Martin Bonner Project Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com

2007/4/5, Jeff Garland <jeff@crystalclearsoftware.com>:
Yeah sure, classic Meyer's singleton. Couple problems. It's not thread safe
It may be not thread safe. If it is first called in the "single thread initialization phase"(or a term like that) there wil be no thread safty problem, but no "lazy instantiation" as well.
and you could easily inline this code into multiple translation units.
I don't agree. Compiler should not make multiple instances of a <b>static local</b> variable,
In both cases you might wind up with multiple copies of your singleton in the process. It's this sort of thing that makes true singletons devilishly hard to do...

Kevin Yuan wrote:
2007/4/5, Jeff Garland <jeff@crystalclearsoftware.com>:
Yeah sure, classic Meyer's singleton. Couple problems. It's not thread safe
It may be not thread safe. If it is first called in the "single thread initialization phase"(or a term like that) there wil be no thread safty problem, but no "lazy instantiation" as well.
Well, now you've added a requirement that to use this correctly I need a 'single threaded' init? I assure you, that's sometimes just not possible. I've seen plenty of software where the first thing that happens is multiple threads are spawned (before 'main' even gets invoked) so it's not always that easy. And when you throw dll loading into the mix it's basically impossible to guarantee a startup order.
and you could easily inline this code into multiple translation units.
I don't agree. Compiler should not make multiple instances of a <b>static local</b> variable,
See other mail/discussion regarding complexities caused by dlls on Windows. Yes, "in theory" this is prevented by the compiler, but the compiler isn't all to a typical real-world build process. Jeff

2007/4/5, Jeff Garland <jeff@crystalclearsoftware.com>:
I assure you, that's sometimes just not possible. I've seen plenty of software where the first thing that happens is multiple threads are spawned (before 'main' even gets invoked) so it's not always that easy.
Yep. It is true that sometimes 'single threaded' init is not possible to guarantee and it is also true that 'single threaded' init is not impossible to guarantee if you want.
And when you throw dll loading into the mix it's basically impossible to guarantee a startup order. ... ... See other mail/discussion regarding complexities caused by dlls on Windows.
Yes, I admit dll is another thing.

Jeff Garland <jeff@crystalclearsoftware.com> wrote:
Yeah sure, classic Meyer's singleton. Couple problems. It's not thread safe and you could easily inline this code into multiple translation units. In both cases you might wind up with multiple copies of your singleton in the process. It's this sort of thing that makes true singletons devilishly hard to do...
My only big design regret from my last project was using Singletons in an infrastructure library layer used by multiple applications. I will never do it again. Promise! My design policy now is to never embed Singletons in a library - if an application wants to instantiate a library object as a Singleton, let the app take responsibility and manage it accordingly (of course a good generic Singleton library in Boost would help ease some of the not-trivial issues with Singletons). Here's an example from ACE, that caused untold wasted hours in problem analysis: ACE Reactors have a Singleton interface, allowing simple and easy Reactor instantiation and use. Two different application layers (written by different teams) were using the ACE Reactor Singleton in the same application. Depending on what event handlers were registered with the Reactor and which events were processed, unexpected results occurred. Unit tests were absolutely clean, since the unit tests only tested the event handlers from one layer. If the separate layers had each instantiated their own Reactor objects, interference would not have happened. And don't get me started on the initialization, dynamic library loading, and multi-threaded issues I've had to work through with Singletons ... Cliff

Cliff Green wrote:
Jeff Garland <jeff@crystalclearsoftware.com> wrote:
My only big design regret from my last project was using Singletons in an infrastructure library layer used by multiple applications. I will never do it again. Promise!
My design policy now is to never embed Singletons in a library - if an application wants to instantiate a library object as a Singleton, let the app take responsibility and manage it accordingly (of course a good generic Singleton library in Boost would help ease some of the not-trivial issues with Singletons).
I agree with the design philosophy...it's really pretty rare that the singleton is absolutely required. Oh, and btw, the standard library has been burned by this too -- the instantiation weight of std::cout, std::err, etc make the inclusion of the iostream header a killer for embedded apps (several K size increase in the executable just by including)... There has been a boost.singleton proposed and I believe rejected and probably given up on by now.
Here's an example from ACE, that caused untold wasted hours in problem analysis: ACE Reactors have a Singleton interface, allowing simple and easy Reactor instantiation and use. Two different application layers (written by different teams) were using the ACE Reactor Singleton in the same application. Depending on what event handlers were registered with the Reactor and which events were processed, unexpected results occurred. Unit tests were absolutely clean, since the unit tests only tested the event handlers from one layer. If the separate layers had each instantiated their own Reactor objects, interference would not have happened.
And don't get me started on the initialization, dynamic library loading, and multi-threaded issues I've had to work through with Singletons ...
Ok -- here's another fun one: destruction order of co-dependent singletons crashing the process on exit -- that's always a fun one to fix ;-) Jeff

Julio M. Merino Vidal wrote:
On 02/04/2007, at 19:11, Andrey Semashev wrote:
Although the discussion is slipping away from the original question, I must say I 100% agree with Jeff. The best solution is to give user a choice whether to link or to go header-only (where possible). And in my opinion such solution should be unified for all boost libs. We already have the BOOST_USE_WINDOWS_H macro, why not extend it to something like BOOST_USE_OS_NATIVE_HEADERS? I think this would settle the problem once and for all. The only problem is I'm not sure how such a transition should be organized.
Although I liked this at first too, it seems to me it cannot be always implemented. I was now trying to add a singleton to my library and I can't do it with headers alone.
oh, oh...
I need to maintain the pointer to the global instance somewhere, and that means having a
because?
global variable which cannot be defined in a header (or otherwise you'll get duplicates). Unless I'm missing something, that is...
Moving it to a library won't solve all the problems either -- you'll be constrained to a dll on windows to guarantee a singleton unless you jump through some big hoops (thread lib had this problem -- still does AFAIK). The problem comes about if 2 dll's link with your static lib...they'll create 2 copies of you singleton at dll init time. Really, I'd rethink the singleton design if at all possible. Jeff

Jeff Garland wrote:
Sohail Somani wrote:
Oh gosh yes. Having things in headers because it makes it 'easier to compile' hurts compile times in the long run.
Get a faster build machine and/or use pre-compiled headers -- really.
Its just not good practice and I suspect a non-empty subset of new boost users are also new to C++.
5 years ago I believed it was a serious issue too -- I've substantially changed my mind. And not in small part by using asio (and other boost libs) as header only. It's extremely nice to not need to figure out how to build and link. You can get started with so trivially with an all header library -- and I think that frequently it's trouble getting over that first hump that stops people from using libs. So if the barrier is lower more people will use the libs.
Sorry, but I disagree. The effect of header only libraries on build times is still unacceptable and not everybody can convince their bosses that they need more powerful machines every six months or so. One of the mistakes I came to regret most in the project I'm working on is to have a very small template metaprogram in a header that's used just about everywhere. But I learned my lesson and now I'm happy that I hid Boost.DateTime behind a class of my own. Note that we're using Borland's compiler, which is considered a very fast one and that we do use pre-compiled headers; this, by the way, are not a panacaea, among other things because a sizable portion of your savings in sheer compilation time is lost in much increased dependency checking. As to binary libraries stopping people using Boost, I don't think that's much of a problem per se: after all people programming in C++ and C have been accustomed to static and shared libraries for ages. Rather what may constitute a problem is the complexity and general unfriendliness of the Boost Build system. Still, the time taken to find out how to build libraries for one's own use is mostly spent once, and can be delegated to a single team member; excessive build times impact the whole team all the time. One instructive exercise is to run g++ -H -P -E on a C++ source file chosen at random; it doesn't even need to use Boost, it's sufficient to include, say, <vector> on Windows. The resulting tree of included headers is disenheartening and a clear symptom of what I consider a very serious problem. Cheers, Nicola Musatti

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jeff Garland Sent: Monday, April 02, 2007 8:41 AM To: boost@lists.boost.org Subject: Re: [boost] [system] Why is this not header-only?
Sohail Somani wrote:
Oh gosh yes. Having things in headers because it makes it 'easier to compile' hurts compile times in the long run.
Get a faster build machine and/or use pre-compiled headers -- really.
Seems to me you're saying replace something that is a bit annoying (compile it yourself) with something that is even less likely to be done correctly. But your point is well taken, and that is something I should look into. However, one should still prefer a codebase that doesn't require the user to make up for slow compiles with these compiler-specific features.
Its just not good practice and I suspect a non-empty subset of new boost users are also new to C++.
5 years ago I believed it was a serious issue too -- I've substantially changed my mind. And not in small part by using asio (and other boost libs) as header only. It's extremely nice to not need to figure out how to build and link. You can get started with so trivially with an all header library -- and I think that frequently it's trouble getting over that first hump that stops people from using libs. So if the barrier is lower more people will use the libs.
But if you have a policy of saying: don't make your build totally dependent on bjam, I don't think this is an issue. Just add the cpp files to your build and off you go. In my opinion, bjam is the biggest obstacle to new users. If the instructions for using boost thread (for example) were this: 0) Create a new VS.NET project 1) Add the files in boost/libs/thread/src to your project 2) Add the include path for boost to your project (with some instructions on how to do so) 3) Copy and paste the following into main.cpp This is a non-issue. With header-only libraries, step 1 is the only thing that disappears and you might even be lucky enough to disable language extensions in your project. Sohail

-----Original Message----- From: Sohail Somani
0) Create a new VS.NET project 1) Add the files in boost/libs/thread/src to your project 2) Add the include path for boost to your project (with some instructions on how to do so) 3) Copy and paste the following into main.cpp
This is a non-issue. With header-only libraries, step 1 is the only thing that disappears and you might even be lucky enough to disable language extensions in your project.
Actually, step 1 is replaced with "try build with bjam, send emails to the mailing list"

Jeff Garland wrote:
Its just not good practice and I suspect a non-empty subset of new boost users are also new to C++.
5 years ago I believed it was a serious issue too -- I've substantially changed my mind.
Oh yeah, same here. Although I don't have any problem using libraries which require building, I really like using these header-only libraries in boost. Regarding new user, don't forget when we test/try some new libraries, we are all new users. Even when we write some write-test-throw experiment code, it is a great convenience with a header-only library.

On Monday 02 April 2007 17:41, Jeff Garland wrote:
Sohail Somani wrote:
Its just not good practice and I suspect a non-empty subset of new boost users are also new to C++.
5 years ago I believed it was a serious issue too -- I've substantially changed my mind. And not in small part by using asio (and other boost libs) as header only. It's extremely nice to not need to figure out how to build and link. You can get started with so trivially with an all header library -- and I think that frequently it's trouble getting over that first hump that stops people from using libs. So if the barrier is lower more people will use the libs.
I'd just like to second this aspect. I know that my first attempts at getting Boost.Thread to work were fruitless, because the behaviour and complexity of the build-system were so intimidating and frustrating that I simply gave up. I guess that many think so, at least I have had a lot of discussions that went into that direction on the Usenet. Now, what I did here was to create an additional file that can be included as "boost/thread/inplace_link.cpp". All that this file does is #include the sourcefiles from lib/thread/src. Now, in order to use threads, all you need to do is to include this file into exactly one translation unit, that's it. Really, that is all! Apart from static linking, this has an additional advantage: ABI independence. If you have a bunch of C++ compilers on your machine, you need just as many SOs/DLLs, which all have to be built. Using GCC, those don't even have different names, so there is no way to use different ones alongside. Considering STLport, it can at least be distinguished from the native one, but STLport 5.1 is not binary compatible with STLport 5.0, so the problems remain. Note: I haven't tried it on MS Windows yet (only on vanilla Debian/Linux/x86), but I guess that due to the dllexport/dllimport stuff, you might have to set a switch so that static linking takes place, at least for the inplace-linked Boost libs. The reason is that otherwise the symbols get decorated with dllimport attributes which we don't want, since we are linking in place. I don't remember, what was the default link type there? If it is static, we are all set. Also, I used to call this 'inplace-link', but 'inplace-compile' would be more suitable. Further, note that this does not replace the existing mechanisms for dynamic or static linking but enhances them. If you want, you can still use dynamic or static precompiled libs, but otherwise it significantly lowers the entry barrier by skipping any precompilation requirement. Uli

Ulrich Eckhardt wrote:
Now, what I did here was to create an additional file that can be included as "boost/thread/inplace_link.cpp". All that this file does is #include the sourcefiles from lib/thread/src. Now, in order to use threads, all you need to do is to include this file into exactly one translation unit, that's it. Really, that is all! Apart from static linking, this has an additional advantage: ABI independence.
If you have a bunch of C++ compilers on your machine, you need just as many SOs/DLLs, which all have to be built. Using GCC, those don't even have different names, so there is no way to use different ones alongside. Considering STLport, it can at least be distinguished from the native one, but STLport 5.1 is not binary compatible with STLport 5.0, so the problems remain.
(sorry this is a bit of a rant, but this topic has caused me *so* much pain in the past) I *very* strongly agree to that. ABI compatibility is already a problem in windows (I saw lots of refreences to msvc on this thread so it seemed to me that many people come from that side). But you can at least just dump the suitable boost .dll files into your application dir and windows does "The right Thing(tm)". On linux the situation is a totally different matter. There are two options if you distribute your application in source, neither of them practical: * Supply your own boost sources, and compile it alongside your project. Its probably easy enough to include the boost build, but with the time boost takes for a full build, do you really want to do that ? And if the boost build breaks do you want to do support the support calls? * Rely on the system supplied boost libs. Works reasonably well when your app is compiled form source, you only need to anticipate which version of boost will be installed. If you distribute binaries the situation becomes even worse: * Supply your own boost dynamic libs. This sounds easy, but considering things like LD_LIBRARY_PATH it is actually not failsafe and cannot be trusted. Apart from the fact that your boost libs need to be linked against the correct libstdc++ version, etc. or they won't work in the first place. * Rely on the system boost libs. This is right out. Unless you have exactly the same compiler version with exactly the same setup on your build machine as the enduser i would not expect the program to do anything. * Link statically. This only leaves you with the usual linux c++ ABI madness but at least boost will work properly. This is what we do, and I think its the only way that will work guaranteed. It introduces code bloat, but thats a small price to pay for developer sanity ;-) Of course, if i am going to link statically anyway, having header only libs is pretty much the same except that long link times are split into multiple longer compile times, and that i do not have to worry about which lib to include. So as has been said: shared objects have their advantages and their uses, and during the debugging cycle it would certainly speed things up, but for a final release build shared library only is not really a good option. In that sense: choice ftw. Michael Lacher
participants (19)
-
Alexander Nasonov
-
Ames Andreas
-
Andrey Semashev
-
Anthony Williams
-
Cliff Green
-
Edward Diener
-
Felipe Magno de Almeida
-
gchen
-
Iulian M
-
Jeff Garland
-
Jody Hagins
-
Julio M. Merino Vidal
-
Kevin Yuan
-
Martin Bonner
-
Michael Lacher
-
Nicola Musatti
-
Peter Dimov
-
Sohail Somani
-
Ulrich Eckhardt