[CMake] Problems with transitive dependencies

Chris Wilson chris+cmake at qwirx.com
Mon Dec 7 14:43:27 EST 2015


Dear CMake users,

I'm trying to use CMake to replace the complex hand-built Visual Studio
configuration of our open source project, Box Backup. And I'm having
trouble making it generate the correct transitive dependencies between
modules, particularly for include directories.

We have a lot of modules whose header files need to be part of the public
interface to link to these modules. I thought from the manual that "The
usage requirements of a target can transitively propagate to dependents"
but I can't make it work (for anything except link libraries).

Here is a toy example taken from the manual:

add_library(archive archive.cpp)
target_compile_definitions(archive PUBLIC USING_ARCHIVE_LIB)

add_library(serialization serialization.cpp)
target_compile_definitions(serialization INTERFACE USING_SERIALIZATION_LIB)

add_library(archiveExtras extras.cpp)
target_link_libraries(archiveExtras PUBLIC archive)
target_link_libraries(archiveExtras PRIVATE serialization)
# archiveExtras is compiled with -DUSING_ARCHIVE_LIB
# and -DUSING_SERIALIZATION_LIB

add_executable(consumer consumer.cpp)
# consumer is compiled with -DUSING_ARCHIVE_LIB
target_link_libraries(consumer archiveExtras)


My understanding is that the target_compile_definitions are part of the
public interface of the archive module, and should be added to anything
that links to it, which archiveExtras does. But if I add some debugging
messages after the above code:

foreach (lib archive serialization archiveExtras consumer)
  get_property(ill TARGET ${lib} PROPERTY INTERFACE_LINK_LIBRARIES)
  get_property(ll TARGET ${lib} PROPERTY LINK_LIBRARIES)
  get_property(icd TARGET ${lib} PROPERTY INTERFACE_COMPILE_DEFINITIONS)
  get_property(cd TARGET ${lib} PROPERTY COMPILE_DEFINITIONS)
  message(STATUS "${lib}: INTERFACE_LINK_LIBRARIES = \"${ill}\" "
    "LINK_LIBRARIES = \"${ll}\"")
  message(STATUS "${lib}: INTERFACE_COMPILE_DEFINITIONS = \"${icd}\" "
    "COMPILE_DEFINITIONS = \"${cd}\"")
endforeach()


I can see that archiveExtras inherits the link libraries of archive, *but
not its compile_definitions* (nor the include directories if I try to
inherit them instead):

-- archive: INTERFACE_LINK_LIBRARIES = "" LINK_LIBRARIES = ""
-- archive: INTERFACE_COMPILE_DEFINITIONS = "USING_ARCHIVE_LIB"
COMPILE_DEFINITIONS = "USING_ARCHIVE_LIB"

-- serialization: INTERFACE_LINK_LIBRARIES = "" LINK_LIBRARIES = ""
-- serialization: INTERFACE_COMPILE_DEFINITIONS = "USING_SERIALIZATION_LIB"
COMPILE_DEFINITIONS = ""

-- archiveExtras: INTERFACE_LINK_LIBRARIES =
"archive;$<LINK_ONLY:serialization>" LINK_LIBRARIES =
"archive;serialization"
-- archiveExtras: INTERFACE_COMPILE_DEFINITIONS = "" COMPILE_DEFINITIONS =
""

-- consumer: INTERFACE_LINK_LIBRARIES = "archiveExtras" LINK_LIBRARIES =
"archiveExtras"
-- consumer: INTERFACE_COMPILE_DEFINITIONS = "" COMPILE_DEFINITIONS = ""


The COMPILE_DEFINITIONS of archiveExtras is empty; it has not inherited
anything.

The manual says:

Because archive is a PUBLIC dependency of archiveExtras, the usage
> requirements of it are propagated to consumer too. Because serialization is
> a PRIVATE dependency of archive, the usage requirements of it are not
> propagated to consumer...
>


"Usage requirements are propagated by reading the INTERFACE_ variants of
> target properties from dependencies and appending the values to the
> non-INTERFACE_ variants of the operand. For example, the
> INTERFACE_INCLUDE_DIRECTORIES of dependencies is read and appended to the
> INCLUDE_DIRECTORIES of the operand."


I would assume that the same happens for COMPILE_DEFINITIONS: it should be
copied from the INTERFACE_COMPILE_DEFINITIONS of the dependencies. But this
doesn't appear to be happening, as far as I can tell. Nor is the "consumer
compiled with -DUSING_ARCHIVE_LIB", contrary to the comment (at least it's
not in the COMPILE_DEFINITIONS).

Can anyone tell me what I'm doing wrong? Specifiying "dependencies" the
wrong way? I would really appreciate some help :) Do I have to hard-code or
script all the transitive dependencies myself, or is there something I'm
missing?

Thanks in advance, Chris.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20151207/253c24d3/attachment.html>


More information about the CMake mailing list