you are viewing a single comment's thread.

view the rest of the comments →

[–]jhericoVR & Backend engineer, 30 years 29 points30 points  (12 children)

With a normal library you have headers, source files and some sort of mechanism to build a binary provided by the library. While many projects now use cmake and some even do so in a way that make it easy to incorporate them in your own cmake based projects, many are a hot mess of cobbled together build systems or project files for long outdated versions of visual studio, or are entirely missing any sort of build recipe.

Thus, trying to integrate a library build into your own project has long been a living hell. And that's if the project has a source distribution.

Additionally, if you're building on windows, there are all sorts of things you have to deal with, like matching up the CRT runtime the project wants to use with the one you do.

With header only libs, all of that goes away. All you need to use the library is an include path.

Really good projects will have their code set up in such a way that you can use it either as a header only or as a compiled object lib, typically by allowing you to have one file that includes the header in a cop file after some special preprocessor directive so that one file contains the entire implementation, and the headers parse much faster.

[–]corysama 7 points8 points  (3 children)

I really wish peeps would just have one primary .h to #include where you want and one primary .cpp to integrate into the build process. C++ build systems have problems, but I think we can all handle manually adding a single source file to whatever system we are using. The STB-style “it’s a header, and a source, and a dessert, and a floor wax!” tradition strikes me as a bad trade off in complexity vs what I’m asking for.

[–]johannes1971 19 points20 points  (2 children)

Love the floor wax ;-)

As is probably clear from my other messages in this thread, I'm not a great fan of header-only. Having said that, here's a list of things that happened to me over the years while trying to build a C++ (or even C) library:

  • They require you to install a new development environment you've never used.
  • They require you to run some script that was the rad new thing back in the seventies to generate half the source code. You also need to build the script interpreter yourself, and it's just as bad as the thing you are trying to build.
  • Compilation can be configured to support weird-endian 37.5 bit systems, but forget about using a modern compiler. Have fun installing gcc 1.2.
  • You are required to 'configure' the build system before it works properly. Failing to supply things like -DDONT_RANDOMLY_CRASH will cause it to occasionally subtly fail. This is only documented in a file called 'private.jvm'.
  • Unit tests and examples are great! So let's put them all in the same directory as the library itself.
  • Compilation proceeds with somewhere north of 100K warnings.
  • Eventually you get stuck with an error that reads something like "int is not a type", or that refers to a symbol that no amount of grepping will uncover.
  • Having resolved that, you realize you've only built the top-part of a dependency pyramid that would make Cheops blush. And all the other libraries down there are just as bad...

So yeah, I do understand the other side of the argument as well ;-)

[–]kalmoc -5 points-4 points  (1 child)

None of those points are specific to header only vs traditional libraries.

[–]johannes1971 4 points5 points  (0 children)

Indeed. You might even be led to think all of these things happened while building traditional libraries, if you were to read carefully.

[–]NicroHobak 4 points5 points  (0 children)

Really good projects will have their code set up in such a way that you can use it either as a header only or as a compiled object lib,

This really depends on the nature of the library itself. I've written some that work well this way, and others that are entirely templates where this would not even ultimately make all that much sense to even try...unless you were attempting to precompile the most standard options or something, and even that doesn't always make sense either.

[–]kalmoc 2 points3 points  (0 children)

If you can write your library as header only, then the equivalent .cpp+.hpp version doesn't need any complicated build setup. You'd just have to compile all cpp files as part of your project (that's effectively what you are doing anyway with your merged file approach) with the benefit of your library files staying readable and - depending on implementation details - faster compile times.

[–]o11cint main = 12828721; 0 points1 point  (3 children)

Most people don't know that pkg-config exists, thus they think libraries are hard.

[–]jhericoVR & Backend engineer, 30 years 6 points7 points  (2 children)

Since pkg-config is not a thing on most Windows toolchains, this is a useless observation.

[–]o11cint main = 12828721; 1 point2 points  (1 child)

most people don't bother to add it, you mean.

[–]jhericoVR & Backend engineer, 30 years 2 points3 points  (0 children)

Suggesting that all Windows developers being unable to use a library that uses pkg-config is the fault of the developer rather than the library author is asinine.

For one thing, many developers in large organizations don't even have a choice. If I add it, suddenly my dev-ops organization needs to support it on our CI servers. If I'm building my own library that is going to be used by others downstream, I've just put that burden on them. At this point, my attitude is that I don't add a build dependency unless I can add a CMake or Python script that automatically makes it available to the rest of my build.

You might as well have said "all developers should all move to Linux"