[CMake] Problems with transitive dependencies

Mueller-Roemer, Johannes Sebastian Johannes.Sebastian.Mueller-Roemer at igd.fraunhofer.de
Tue Dec 8 02:34:21 EST 2015


You are evaluating those properties at the wrong time. Transitive properties are not passed on at configure time (they can’t be), but at generation time. Therefore to debug those values you will have to use generator expressions (except they don’t work for link_libraries). Or just look at the generated project…

--
Johannes S. Mueller-Roemer, MSc
Wiss. Mitarbeiter - Interactive Engineering Technologies (IET)

Fraunhofer-Institut für Graphische Datenverarbeitung IGD
Fraunhoferstr. 5  |  64283 Darmstadt  |  Germany
Tel +49 6151 155-606  |  Fax +49 6151 155-139
johannes.mueller-roemer at igd.fraunhofer.de  |  www.igd.fraunhofer.de

From: CMake [mailto:cmake-bounces at cmake.org] On Behalf Of Chris Wilson
Sent: Monday, December 07, 2015 20:43
To: cmake at cmake.org
Subject: [CMake] Problems with transitive dependencies

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/20151208/80d622ae/attachment.html>


More information about the CMake mailing list