[CMake] Why do executables link static libs that shared libs were built from?

Paul Smith paul at mad-scientist.net
Sun Jun 16 12:04:22 EDT 2019


Let me just mention up-front that I spent about 2 weeks earlier this
year completely converting our circa-2011 cmake environment to ultra-
modern cmake: switching completely to TLL, interfaces, removing
virtually all if-statements and converting them into generator
expressions, etc.  So I'm very familiar with CMake's model for PRIVATE,
PUBLIC, and INTERFACE and how inheritance works.

And, I see the paradigm you're operating under where a shared library
provides a single "interface" that is public.

But, that's not the only way to use shared libraries.  I'm trying to
collect a number of static libraries with different interfaces into a
single shared library that can be linked with executables (in my case I
have 220 unit test programs which, when linked statically, not only
take a very long time and a lot of memory, but use about 45G of disk
space per build--I am collecting these into a shared library that can
be linked with our unit tests.  In my testing this reduces the size of
a sample unit test executable from 400M down to about 8M).

So: I need my shared library to export a combination of ALL the public
interfaces of the static libraries it was built from, but not,
obviously, export the static libraries themselves.


On Sat, 2019-06-15 at 23:10 -0700, Craig Scott wrote:
> The behaviour is correct according to what you are telling CMake to
> do. If you use PUBLC in a target_link_libraries() call, you are
> saying that anything that links to your shared library should also
> link to the static library.

That simply does not make sense, from the point of view of how a
program and a linker work (I understand it's how CMake works).

Let me work backwards, starting with a fact that hopefully we can all
agree on:

   It is NEVER appropriate to put a static library into the
   INTERFACE_LINK_LIBRARIES of a shared library.

I'd be interested to hear counter-arguments, but even if there are any
reasons for it my position is that in those very rare cases you should
be listing the static library in the TLL of the executable directly.

If we can agree on that, then using the current rules of CMake
inheritance this implies that we can NEVER add a static library as a
PUBLIC TLL for a shared library.

Which seems, to me, quite ridiculous because why shouldn't you want to
allow INTERFACE_COMPILE_DEFINITIONS, INTERFACE_COMPILE_OPTIONS, and
INTERFACE_COMPILE_DIRECTORIES of the static library to be inherited by
the shared library into its PUBLIC interface?  That seems like a quite
reasonable thing to want to do.



More information about the CMake mailing list