[CMake] Using target_link_libraries INTERFACE with static libraries

Luis Caro Campos julius.caro at gmail.com
Thu Jun 1 07:11:48 EDT 2017


I have the following scenario where I have 2 static libraries, where one
uses symbols from the other, and the executable needs to link against both
in order to build properly.

Library 'Bar' uses symbols from library 'Foo' internally, but 'Foo' is not
part of the "interface" of Bar, i.e., the calling library/application only
needs to include headers from 'Bar', and use symbols from Bar.

---
#static libraries, assuming BUILD_SHARED_LIBS is off
add_library(Foo)
add_library(Bar)
target_include_directories(Foo PRIVATE ... )
target_include_directories(Foo INTERFACE ...)
target_include_directories(Bar PRIVATE ...)
target_include_directories(Bar INTERFACE ..)

# this will expose Bar to Foo's interface include directories
target_link_libraries(Bar PUBLIC|PRIVATE Foo)


add_executable(MyApp)
target_link_libraries(MyApp PRIVATE Bar)

---

In order to for the executable "MyApp" to build successfully, which uses
static library Bar, "Foo" also needs be in the link statement otherwise
I'll get missing symbols. If 'Bar' doesn't include this information in the
target link interface, I'll have to explicitly link against "Foo" for MyApp.

My question is, in this case, which is the correct keyword for use when
calling "target_link_libraries" between Bar and Foo?

Technically, 'Foo' is not part of Bar's public interface, so it would be
PRIVATE. However, this would force me to have to expressly link against Foo
in MyApp.
The other alternative is PUBLIC, as that would take care of the dependency.
I think strictly speaking, it is an "interface link dependency", but not an
"interface" dependency. I know that there are LINK_PUBLIC and LINK_PRIVATE
keywords for target_link_libraries, however the documentation says they are
for compatibility only and the other ones should be favoured.

So in this scenario, I guess "PUBLIC" would be the best case, as that takes
care of the linking of MyApp.

Question (1): does this not have the downside of adding Foo's interface
include directories to MyApp's include path?

The second scenario would be if Foo was static and Bar was shared. In that
case, it would be crystal clear, the target_link_libraries call between Foo
and Bar should use the PRIVATE keyword.
However, what about if BUILD_SHARED_LIBS was set to on?
Both would be shared libraries, but MyApp doesn't need to link against
"Foo" anymore, however it is needed at runtime.

Question (2): toggling the BUILD_SHARED_LIBS flag then seems to require
altering the semantics of calls to target_link_libraries? What about the
"needed at runtime" but "no part of the interface case?

My conclusion is that I should perhaps explicitly declare those libraries
as static (foo and bar), and use the "PUBLIC" keyword when linking them.
Although I see two downsides:
1) Foo's interface include path is added to MyApp's include path (and it is
not needed)
2) Bar is now dependant on "Foo", so Foo needs to be built before. However,
from a compiler point of view, the binaries of Foo are not needed to
produce bar.

Any help would be appreciated, in case there are better ways to express
these dependencies that I'm ignoring.



Thanks,
Luis
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20170601/3459f2c4/attachment-0001.html>


More information about the CMake mailing list