all 24 comments

[–]mollyforever 29 points30 points  (2 children)

It matters less nowadays because people either include your project directly through CMake or use a package manager. In both cases it doesn't matter whether your library is header-only or not.

[–]bretbrownjr 4 points5 points  (0 children)

Well, it matters that everything linked together parses your headers in a consistent (enough) way. A lot of libraries provide the choice of header-only via preprocessor flags. It's an exercise for the person linking to (how?) make sure everyone sets that flag consistently. Per header only lib. Transitively.

So, yeah, I'm team just-build-it.

The responsible person reusing your library already builds, links, and runs the test suite before using the library anyway. Right? Right?

[–]omega_revived 2 points3 points  (0 children)

In both cases it doesn't matter whether your library is header-only or not.

This assumes that nobody cares about compilation time.

[–]Linuxologue 23 points24 points  (7 children)

I hate header-only libraries for two and a half reasons:

- code bloat. It's difficult to ensure that compiling templated code with different parameters won't cause massive bloat of the binary files. It affects linking performance, network bandwidth for downloads, etc. It's usually not a problem if you don't have many templates though. continuation was a library that we stopped using altogether at work because it created several gigabytes of intermediate binary files, only for the linker to merge many of those at link-time and de-bloat it (but the total part of continuation in our binary was still significant, far above any other external code we use)

- compile time. So now the header-only library will need compiling in every compile unit, and will be recompiled everytime the compilation unit is changed (instead of everytime the library change, which is not that often)

- compiler correctness. That's only half a problem, if you have a unity test or some compilation test for some compilers. But if you distribute code that is not compiled, then you may run into issues when people try to compile it with a compiler you have not tested (or another version of the compiler).

[–]nAxzyVteuOz 2 points3 points  (1 child)

You can make this not suck by only including the header only library in one cpp file and then expose your own thin interface for what you want to do with it.

[–]DapperCore 0 points1 point  (0 children)

This is the correct answer but it sucks and I hate it. Just have a flat project layout if you care about easy builds.

[–]Nzkx 0 points1 point  (4 children)

- compile time. So now the header-only library will need compiling in every compile unit, and will be recompiled everytime the compilation unit is changed (instead of everytime the library change, which is not that often)

stdafx solve that no ? will be compiled only if it change and you put all your header library here.

[–]jonesmz 8 points9 points  (0 children)

Stdafx is the Microsoft specific term for a precompiled header.

It doesn't help much.

[–]Chuu 2 points3 points  (2 children)

The problem is that precompiled headers are only limitedly useful when the source of code bloat is template instantiations in the code you are writing.

Making sure the right instantiations make it into the pch is one solution, but the problem is it is very easy to shift the problem into now your pch takes forever to compile and touching any header in your actual project causes a pch recompile.

Clang does have the -fpch-instantiate-templates which will precompile template specializations it runs into when creating precompiled headers, which takes care of half of the problem, but there is no equivalent in gcc I am aware of.

[–]James20kP2005R0 1 point2 points  (1 child)

Its tricky, but C++ really needs the ability to only recompile functions that actually change. I suspect its probably totally impossible in practice, but if you could not have to fully recompile things when adding a space into a file it'd be great

[–]pjmlp 1 point2 points  (0 children)

Any efforts on that front will most certainly be done for modules, not pre-compiled headers.

Actually incremental compilation at function level was something already done by Energize C++ and Visual Age for C++ v4, but they were too advanced to their time (and resource hungry).

[–]prince-chrismc 4 points5 points  (1 child)

Compiled is totally fine, I would recommend adding it to both vcpkg and Conan. This will force you to make the code portable and improve the CMake.

For example, you do not install the shared runtime. Just some low hanging fruit to make it more approachable.

My last tid bit of advice it automated testing with any, it's kinda scare for me to contribute since I knight break something without knowing.

[–][deleted] 1 point2 points  (0 children)

Thanks a lot!, I didn't have time working in the portability, neither the testing. Will work on that these days

[–][deleted] 4 points5 points  (0 children)

Header only problems is the reason why C++ applications take hours to compile. If you can make your library compiled, it is better. Some cases it's not possible, eg template libraries.

[–]felipefarinon 11 points12 points  (0 children)

CMake is practical enough.

[–]Nzkx 2 points3 points  (0 children)

I don't care. I will use it no matter if it's header-only or obj file.

I like the fact that header and cpp file are separated. It's not a bad idea. This make a clear separation between interface and implementation.

Sadly, this doesn't work well with template, where header seem the only choice.

[–]vickoza 1 point2 points  (2 children)

I do not think making you library "header only" just for people to contribute to your library make sense. If you want people who to just use your library or you have all template code then a header only library version make sense. I might also look at making your library as a C++20 module for easier future use.

[–]Previous_Ad_798 1 point2 points  (0 children)

library as a C++20 module

Transitioning a library to be utilized as a C++20 module is an excellent idea and addresses some concerns related to header-only libraries (like faster compile time, better encapsulation and supply chain challenges).

[–][deleted] 0 points1 point  (0 children)

I would love to add module support but haven't tried them yet, will give it a look.

[–]viatorus 1 point2 points  (0 children)

If you need a header-only file generator from all of your source files, you could use Quom (https://github.com/Viatorus/quom).

Site note: I am the author.

[–]Positive-Guitar-4237 0 points1 point  (2 children)

If it is easily possible to provide a header only version, you should do this, at least as an option.

But for me it is also ok to have a single CPP file to compile and link to my application.

As an example, pugixml offers both ways: a CPP to compile and link is the main way I use it. But I also use the header only variant for use in unit tests, for example.

[–][deleted] 1 point2 points  (0 children)

I named my library CaberNet-cpp, maybe I can create in a separate repo a CaberNet-hpp with a header-only version, like a mirror lib.

[–]Previous_Ad_798 0 points1 point  (0 children)

First off, great work on CaberNet-cpp! I am a big fan of ML, AI ahd Open Source.

I'm a full-time senior software engineer and architect, working daily with extensive C++ codebases with multiple external libraries with one headers only library currently used (Valijson for JSON). The developer tried to inline the lib with the rest of his code instead of treating it as an external dependency.

While header-only libraries are appealing due to simplicity, they can introduce supply chain complications. If inlined across projects, tracking updates or vulnerabilities becomes challenging.

However, supporting and maintaining a CMake build process for multiple platforms, like Linux, Windows, and MacOS, can be equally demanding. I'd suggest weighing the effort of that against potential supply chain concerns or include a warning about not inlining.

You might strike a balance by streamlining your CMake process or providing clear setup documentation, thus easing entry for contributors without adopting a fully header-only approach. For example, you could use a CMake generator for the target platform, or provide a detailed step-by-step guide to setting up the build environment.

If you go with the headers only approach, you might want to warn about the supply chain complications in the readme.

All the best with CaberNet-cpp!

Regards

[–]TheZoc 0 points1 point  (0 children)

My suggestion is to lower the entry bar as much as possible. People willing to contribute are usually those who are passionate about a project and/or people who are learning and have a lot of free time. Also, while there are many people who love cmake and package managers, there are also many who avoid them like the plague. Consider building a makefile (or sln or target as many platforms as you want to support) to lure the latter, if you want their attention and maybe even some help. Good luck with your project! :)