target_include_directories之前的2.8.12? [英] target_include_directories prior to 2.8.12?

查看:1014
本文介绍了target_include_directories之前的2.8.12?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的 CMakeList.txt 有一个 target_include_directories creep。它打破了我们的下层客户端,如Ubuntu LTS,CentOS和Solaris。



我知道我可以通过以下方式保护它(感谢 ZW ),但我需要一些Cmake版本2.8.11和更早版本( ??? )。

  cmake_minimum_required(VERSION 2.8.5 FATAL_ERROR)
...

if(NOT CMAKE_VERSION VERSION_LESS 2.8.12)
target_include_directories ...)
else()

endif()

我们的目录结构相当简单。有一个目录,其中有头文件,同一个目录中有源文件。这是通过设计使用户在调试器下没有麻烦。



使用下面的配置是可以的(如果 @steveire答案适用于我们):

  if(NOT CMAKE_VERSION VERSION_LESS 2.8.12)
target_include_directories(...)
else()
include_directories($ {ROOT_SOURCE_DIR})
endif b $ b

如果没有,应该使用 target_include_directories



target_include_directories() 命令与 include_directories() 。所以我同意@Tsyvarev,它主要取决于你如何使用 target_include_directories()





如果您使用 target_include_directories(my_target PRIVATE ...) $ c> set_property(TARGET my_target APPEND PROPERTY INCLUDE_DIRECTORIES ...)。但是 include_directories()相反,为当前 CMakeLists.txt 中的所有目标设置那些目录, code> add_subdirectory() siblings。



如果使用 target_include_directories(my_target INTERFACE / PUBLIC ... )在CMake版本2.8.11之前没有这样的功能。



建议



如果您仍然希望支持旧版本的CMake,请不要使用新命令。因为这不仅仅是 target_include_directories()(请参阅 CMake版本兼容性矩阵/命令)。



参考





向后兼容 target_include_directories()


$ b b

以下代码显示了什么旧的CMake版本将模拟 target_include_directories()

  function(target_include_directories _target)
set_property(GLOBAL APPEND PROPERTY GLOBAL_TARGETS$ {_ target})
set(_modePRIVATE)
foreach
if(_arg MATCHESSYSTEM | BEFORE)
消息(FATAL_ERRORtarget_include_directories:SYSTEM或BEFORE不支持)
endif()
if(_arg MATCHES INTERFACE | PUBLIC | PRIVATE)
set(_mode$ {_ arg})
else()
get_filename_component(_inc_dir$ {_ arg}ABSOLUTE)
if _mode MATCHESPUBLIC | PRIVATE)
set_property(TARGET $ {_ target} APPEND PROPERTY INCLUDE_DIRECTORIES$ {_ inc_dir})
endif()
if(_mode MATCHESINTERFACE | PUBLIC)
set_property(TARGET $ {_ target} APPEND PROPERTY MY_INTERFACE_INCLUDE_DIRECTORIES$ {_ inc_dir})
endif()
endif()
endforeach()
endfunction(target_include_directories)

函数(target_link_libraries _target)
set_property(GLOBAL APPEND PROPERTY GLOBAL_TARGETS$ {_ target})
set(_modePUBLIC)
foreach(_arg $ { ARGN})
if(_arg MATCHESINTERFACE | PUBLIC | PRIVATE | LINK_PRIVATE | LINK_PUBLIC | LINK_INTERFACE_LIBRARIES)
set(_mode$ {_ arg})
else()
if(NOT _arg MATCHESdebug | optimized | general)
set_property(TARGET $ {_ target} APPEND PROPERTY MY_LINK_LIBARIES$ {_ arg})
endif()
endif $ b endforeach()
_target_link_libraries($ {_ target} $ {ARGN})
endfunction(target_link_libraries)

函数(my_update_depending_inc_dirs _targets _target _dep_target)
get_property TARGET $ {_ dep_target} PROPERTY MY_LINK_LIBARIES)
if(NOT _libs)
return()
endif()
foreach(_lib $ {_ libs})
list _targets$ {_ lib}_idx)
if(NOT _idx EQUAL -1)
get_property(_inc_dirs TARGET $ {_ lib} PROPERTY MY_INTERFACE_INCLUDE_DIRECTORIES)
set_property(TARGET $ {_ target} APPEND PROPERTY INCLUDE_DIRECTORIES $ {_ inc_dirs})
#防止循环依赖使我们陷入无限循环
#从列表中删除我们已经处理的目标
list(REMOVE_AT _targets $ {_ idx})
my_update_depending_inc_dirs($ {_ targets}$ {_ target}$ {_ lib})
endif()
endforeach()
endfunction(my_update_depending_inc_dirs)

函数(my_update_inc_dirs)
get_property(_targets GLOBAL PROPERTY GLOBAL_TARGETS)
列表(REMOVE_DUPLICATES _targets)
foreach(_target $ {_ targets})
my_update_depending_inc_dirs($ {_ targets }$ {_ target}$ {_ target})
endforeach()
endfunction(my_update_inc_dirs)

使用以下代码测试(注意:需要 my_update_inc_dirs()调用结束):

CMakeLists.txt

  cmake_minimum_required 2.6)

项目(TargetIncludeDirectories)

...

add_library(PLib plib / source / plib.cpp)
target_include_directories PLib PRIVATE plib / source PUBLIC plib / include)

add_library(lib lib / source / lib.cpp)
target_include_directories(Lib PRIVATE lib / source PUBLIC lib / include)
target_link_libraries (Lib PRIVATE PLib)

add_executable(App main.cpp)
target_include_directories(App PRIVATE。 PUBLIC include)
target_link_libraries(App PRIVATE Lib)

my_update_inc_dirs()


Our CMakeList.txt had a target_include_directories creep in. It broke our downlevel clients, like Ubuntu LTS, CentOS and Solaris.

I know I can guard it with the following (thanks ZW), but I need something for Cmake versions 2.8.11 and earlier (the ???).

cmake_minimum_required(VERSION 2.8.5 FATAL_ERROR)
...

if (NOT CMAKE_VERSION VERSION_LESS 2.8.12)
  target_include_directories(...)
else()
  ???
endif()

Our directory structure is rather simple. There's one directory with header files in them, and the same directory has the source files in them. This is by design so users don't have troubles under a debugger.

Is it OK to use the following given our configuration (its not clear to me if @steveire answer applies to us):

if (NOT CMAKE_VERSION VERSION_LESS 2.8.12)
  target_include_directories(...)
else()
  include_directories("${ROOT_SOURCE_DIR}")
endif()

If not, what should be used in place of target_include_directories for 2.8.11 and earlier?

解决方案

Problem

The target_include_directories() command has extended functionality compared to include_directories(). So I agree with @Tsyvarev that it mainly depends on how you use target_include_directories().

Solution

If you use target_include_directories(my_target PRIVATE ...) the equivalent would be set_property(TARGET my_target APPEND PROPERTY INCLUDE_DIRECTORIES ...). But include_directories() in contrast does set those directories for all targets in the current CMakeLists.txt and all of it's add_subdirectory() siblings.

If you use target_include_directories(my_target INTERFACE/PUBLIC ...) there is no such functionality in CMake prior to version 2.8.11. You can simulate the behavior of self-propagating include directories, but that's much more complex.

Recommendation

Don't use the new command if you still want to support older versions of CMake. Because this not just target_include_directories() (see CMake Version Compatibility Matrix/Commands).

References

Backward Compatible target_include_directories()

The following code shows what older CMake versions would have to do to simulate target_include_directories():

function(target_include_directories _target)
    set_property(GLOBAL APPEND PROPERTY GLOBAL_TARGETS "${_target}")
    set(_mode "PRIVATE")
    foreach(_arg ${ARGN})
        if (_arg MATCHES "SYSTEM|BEFORE")
            message(FATAL_ERROR "target_include_directories: SYSTEM or BEFORE not supported")
        endif()
        if (_arg MATCHES "INTERFACE|PUBLIC|PRIVATE")
            set(_mode "${_arg}")
        else()
            get_filename_component(_inc_dir "${_arg}" ABSOLUTE)
            if (_mode MATCHES "PUBLIC|PRIVATE")
                set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES "${_inc_dir}")
            endif()            
            if (_mode MATCHES "INTERFACE|PUBLIC")
                set_property(TARGET ${_target} APPEND PROPERTY MY_INTERFACE_INCLUDE_DIRECTORIES "${_inc_dir}")
            endif()            
        endif()
    endforeach()
endfunction(target_include_directories)

function(target_link_libraries _target)
    set_property(GLOBAL APPEND PROPERTY GLOBAL_TARGETS "${_target}")
    set(_mode "PUBLIC")
    foreach(_arg ${ARGN})
        if (_arg MATCHES "INTERFACE|PUBLIC|PRIVATE|LINK_PRIVATE|LINK_PUBLIC|LINK_INTERFACE_LIBRARIES")
            set(_mode "${_arg}")
        else()
            if (NOT _arg MATCHES "debug|optimized|general")
                set_property(TARGET ${_target} APPEND PROPERTY MY_LINK_LIBARIES "${_arg}")
            endif()
        endif()
    endforeach()
    _target_link_libraries(${_target} ${ARGN})
endfunction(target_link_libraries)

function(my_update_depending_inc_dirs _targets _target _dep_target)
    get_property(_libs TARGET ${_dep_target} PROPERTY MY_LINK_LIBARIES)
    if (NOT _libs)
        return()
    endif()
    foreach(_lib ${_libs})
        list(FIND _targets "${_lib}" _idx)
        if (NOT _idx EQUAL -1)
            get_property(_inc_dirs TARGET ${_lib} PROPERTY MY_INTERFACE_INCLUDE_DIRECTORIES)
            set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES "${_inc_dirs}")
            # to prevent cyclic dependencies getting us into an endless loop
            # remove the target we already processed from the list
            list(REMOVE_AT _targets ${_idx})
            my_update_depending_inc_dirs("${_targets}" "${_target}" "${_lib}")
        endif()
    endforeach()
endfunction(my_update_depending_inc_dirs)

function(my_update_inc_dirs)
    get_property(_targets GLOBAL PROPERTY GLOBAL_TARGETS)
    list(REMOVE_DUPLICATES _targets)
    foreach(_target ${_targets})
        my_update_depending_inc_dirs("${_targets}" "${_target}" "${_target}")
    endforeach()
endfunction(my_update_inc_dirs)

Tested with the following code (NOTE: needs the my_update_inc_dirs() call at the end):

CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

project(TargetIncludeDirectories)

...

add_library(PLib plib/source/plib.cpp)
target_include_directories(PLib PRIVATE plib/source PUBLIC plib/include)

add_library(Lib lib/source/lib.cpp)
target_include_directories(Lib PRIVATE lib/source PUBLIC lib/include)
target_link_libraries(Lib PRIVATE PLib)

add_executable(App main.cpp)
target_include_directories(App PRIVATE . PUBLIC include)
target_link_libraries(App PRIVATE Lib)

my_update_inc_dirs()

这篇关于target_include_directories之前的2.8.12?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆