Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make imported target GLOBAL afterwards?

From the FindBoost.cmake module of CMake 3.8:

foreach(COMPONENT ${Boost_FIND_COMPONENTS})
  if(_Boost_IMPORTED_TARGETS AND NOT TARGET Boost::${COMPONENT})
    string(TOUPPER ${COMPONENT} UPPERCOMPONENT)
    if(Boost_${UPPERCOMPONENT}_FOUND)
      if(Boost_USE_STATIC_LIBS)
        add_library(Boost::${COMPONENT} STATIC IMPORTED)
      else()
        # Even if Boost_USE_STATIC_LIBS is OFF, we might have static
        # libraries as a result.
        add_library(Boost::${COMPONENT} UNKNOWN IMPORTED)
      endif()

and the corresponding comment from the docu of that module:

It is important to note that the imported targets behave differently than variables created by this module: multiple calls to find_package(Boost) in the same directory or sub-directories with different options (e.g. static or shared) will not override the values of the targets created by the first call.

I see the rational for having the targets not being GLOBAL.

However, what is the preferred way of making them global?

I'm used to defining the dependencies of my project in a sub-directory including any find_package(...) calls. Consequently, the Boost imported targets are not available in another directory, e.g. /tests/CMakeLists.txt:

<project_root>
  /3rdparty
    /git-submodule-of-a-small-lib
    /CMakeLists.txt
  /include
    /...
  /tests
    /CMakeLists.txt
  /CMakeLists.txt
like image 914
Torbjörn Avatar asked Jul 30 '17 15:07

Torbjörn


1 Answers

There is a IMPORTED_GLOBAL target property for this in CMake >= 3.11:

set_target_properties(Boost::unit_test_framework PROPERTIES IMPORTED_GLOBAL TRUE)

For older versions: find_package() uses standard add_library() calls, so you can always change/extend its functionality to have IMPORTED targets always GLOBAL with something like:

3rdparty\CMakeLists.txt

function(add_library)
    set(_args ${ARGN})
    if ("${_args}" MATCHES ";IMPORTED")
        list(APPEND _args GLOBAL)
    endif()
    _add_library(${_args})
endfunction()

find_package(Boost REQUIRED COMPONENTS unit_test_framework)

Disclaimer

As @CraigScott has commented overwriting CMake's build-in functions is dangerous:

  • [CMake] infinite loop when using function overriding
  • CMake Issue #14357: Defining an override macro/function of add_library more than once causes a segmentation fault

References

  • CMake Issue #1254: Add new target-property IMPORTED_GLOBAL
  • CMake Issue #1222: [Threads, Boost] Option to create IMPORTED targets with GLOBAL scope
  • CMake Issue #17256: Possibility to promote IMPORTED target to IMPORTED GLOBAL
like image 194
Florian Avatar answered Sep 28 '22 13:09

Florian