Search code examples
cmakecmake-scopes

Transfer between scopes in cmake


I do have a multi-component application, modeled with having one parent and two childs. The first one defines libraries, include files, etc. The second one wants to use that information. How can I do that, without coding those names manually?

parent/CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
set(MYNAME1 MyName1)
set(MYLINKNAME MyLinkName)
add_subdirectory(sub1)
message("Parent1: " ${MYNAME1} " " ${MYNAME2} " " ${MYNAME3} " " ${MYLINKNAME})
add_subdirectory(sub2)
message("Parent2: " ${MYNAME1} " " ${MYNAME2} " " ${MYNAME3} " " ${MYLINKNAME})

sub1/CMakeLists.txt

set(MYNAME1 MySub1 PARENT_SCOPE)
set(MYNAME2 MySub2 PARENT_SCOPE)
set(MYNAME3 MySub3)
set(MYLINKNAME IsLinked)
message("Sub1: " ${MYNAME1} " " ${MYNAME2} " " ${MYNAME3} " " ${MYLINKNAME})

sub1/CMakeLists.txt

message("Sub2: " ${MYNAME1} " " ${MYNAME2} " " ${MYNAME3} " " ${MYLINKNAME})
set(MYNAME2 OtherName)

The result is:

Sub1: MyName1  MySub3 IsLinked
Parent1: MySub1 MySub2  MyLinkName
Sub2: MySub1 MySub2  MyLinkName
Parent1: MySub1 MySub2  MyLinkName

Which means that I can transfer information using PARENT_SCOPE from sub1 to sub2. However, I would like to avoid patching packages for testing, logging, etc. Any suggestions?


Solution

  • Replying to the question in your comment:

    Transferring the location of the include files from a standard package to your main program

    You can find an example for this in the official FindZLIB.cmake module:

    add_library(ZLIB::ZLIB UNKNOWN IMPORTED)
    set_target_properties(ZLIB::ZLIB PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}")
    

    The find-module creates an imported library ZLIB::ZLIB and set its INTERFACE_INCLUDE_DIRECTORIES property to the location of the zlib include files.

    Later, in your main program you invoke the find-module:

    find_package(ZLIB REQUIRED)
    

    add your main target:

    add_executable(mymain main.cpp)
    

    and add ZLIB as dependency:

    target_link_libraries(mymain ZLIB::ZLIB)
    

    The location of the zlib include files will be available in main.cpp but you can also query it in your CMakeLists.txt:

    get_target_property(zlib_incl_dirs ZLIB::ZLIB INTERFACE_INCLUDE_DIRECTORIES)
    

    The same method works also for

    • config-module which is like a find-module but it's shipped with the library
    • child-projects:

    In main/child1/CMakeLists.txt you can write:

    add_library(child1 ...)
    target_include_directories(child1 ... PUBLIC ... )
    

    In main/child2/CMakeLists.txt you can write

    add_executable(child2 child2.cpp)
    target_link_libraries(child2 child1)
    

    In child2.cpp the PUBLIC include directories will be added to the include path. You can also query it in your main/child2/CMakeLists.txt:

    get_target_property(child1_incl_dirs child1 INTERFACE_INCLUDE_DIRECTORIES)