[CMake] What is the best way to *export* the transitive dependencies of a library?

Cfyz cfyzium at gmail.com
Thu Jun 23 13:31:41 EDT 2016


Say the executable Exe uses some static library Foo which uses other
libraries, e. g. Bar:

  Exe --> Foo --> Bar

As the developer of Foo and I want to make it easy to link against:

  find_package(Foo REQUIRED)
  target_link_libraries(Exe PRIVATE Foo)

The problem lies with the various dependencies of Foo necessary to use it:
definitions, include directories, libraries. The Foo is a complex
multimedia-processing library with a wide range of configuration options,
so there is a reason why a lot of information may be necessary to use it in
another project.

The official (and quite neat) way to prepare a configuration module
(FooConfig.cmake) is to use install/export commands:

  install(TARGETS Foo EXPORT FooExport DESTINATION lib)
  install(EXPORT FooExport DESTINATION lib/cmake/Foo FILE FooConfig.cmake)

That, however does not export transitive properties of the target. If, for
example there was some Bar dependency:

  find_package(Bar REQUIRED)
  target_link_libraries(Foo PUBLIC Bar)

Then it will indeed use INTERFACE_xxx properties of Bar while building Foo.
But FooConfig.cmake will only list a lone Bar dependency in the
INTERFACE_LINK_LIBRARIES property of an imported Foo target:

  add_library(Foo STATIC IMPORTED)
  set_target_properties(Foo PROPERTIES ... INTERFACE_LINK_LIBRARIES
"...;Bar")

Which, obviously, is not enough to link against the Foo target in another
project. This behavior is mentioned a bit in CMake documentation:

  "Note that it is not advisable to populate the INTERFACE_LINK_LIBRARIES
of
  a target with paths for dependencies. That would hard-code into installed
  packages the include directory paths for dependencies as found on the
machine
  the package was made on."

Which is probably the reason why CMake does not export interface part of
dependencies itself. But I do not see any way around it. By not including
transitive dependencies in configuration module, the responsibility to
search for those dependencies is shifted to the Exe project. But Exe cannot
know which dependencies were enabled during particular Foo's configuration
or where to search for them.

Is this a bug? I'd expect there to be at least an option to include
transitive dependencies during the export. There is
EXPORT_LINK_INTERFACE_LIBRARIES option but it uses deprecated properties
and has no visible effect.

Or am I missing something here? What is the proper way to go around this
issue?

It is not hard to come up with a workaround, in fact. It should be enough
to populate the INTERFACE_xxx (COMPILE_DEFINITIONS, INCLUDE_DIRECTORIES,
LINK_LIBRARIES, maybe SYSTEM_INCLUDE_DIRECTORIES as well) properties of Foo
with contents of respective INTERFACE_xxx properties of all Foo's
dependencies. That, however, will require to include a rather noticeable
piece of homebrew (and somewhat obscure) code to every project trying to
export imported dependencies. Not elegant, will probably break in some
corner case and hard to sell while advertising CMake to collegues.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20160623/0dd71e64/attachment.html>


More information about the CMake mailing list