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-roe...@igd.fraunhofer.de  |  www.igd.fraunhofer.de

From: CMake [mailto:cmake-boun...@cmake.org] On Behalf Of Chris Wilson
Sent: Monday, December 07, 2015 20:43
To: cmake@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.


-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake

Reply via email to