CPack: distributing both shared and static libraries

Before switching to CMake we were able to distribute tarballs containing our library as both a static library and a shared library (at least on Linux and macOS). What is the preferred way to do this with CMake 3.16+?

(Check Section 26.3: Multi Configuration Packages of my book). If you are using CMake 3.16 or later, definitely look at using the cpack -C command line option. CMake 3.16 or later allows you to pass multiple configurations to this option. You are responsible for ensuring that each configuration has already been built when you run cpack. This option only really makes sense if you’re using a multi-config generator, but since there’s now the Ninja Multi-Config generator (since CMake 3.17), this is possible on all major platforms. It can be done with earlier CMake versions and/or single-config generators, but it is much more involved and much less intuitive.

So this would entail creating custom configurations? Like “RelWithDebInfoStatic”, for example? And would our users be able to pick which to use when they run find_package somehow?

No it shouldn’t add any additional requirements unless you want builds that provide both static and shared versions of a target. That isn’t going to work out so good anyway because one target cannot have two different representations (static and shared). You would need to have two different targets in that case. One approach I’ve seen people suggest is to create blahStatic and blahShared targets, then define a blah interface target that links to one of those based on the value of BUILD_SHARED_LIBS or some similar option. Consumers should then only link against blah and the blahStatic and blahShared libraries are somewhat of an internal implementation detail. I say “somewhat” because it would still probably impact consumers in terms of things they might need to add to their own packages, depending on how they are incorporating your library.

Well, I would like to provide both, but mutually exclusively is fine. Maybe like a variable that’s set ahead of find_package(Halide) (in my case) that has it load the appropriate set of exports.

You might want to see how HDF5 did it, not perfect solution but usuable.


Allen - it looks like HDF5 uses separate packages for static and shared? I was specifically asking how to avoid that. Am I missing something?

No, it packages both into a single install. Only the builds are separated.
In the case of tools, there are static () and shared (-shared).
Libraries are static (lib.lib) and shared (.lib)

Not perfect, but workable. And the find_package can request either or both.