Target_include_directories before 2.8.12?

Our CMakeList.txt had target_include_directories creep. He crashed our lower-level clients, such as Ubuntu LTS, CentOS, and Solaris.

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

 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 pretty simple. They have one directory with header files, and one directory contains source files. This is by design, so users do not have problems with the debugger.

Is it possible to use the following configuration (it is not clear if @steveire's 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 instead of target_include_directories for 2.8.11 and earlier?

+4
source share
1 answer

Problem

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

Decision

If you use target_include_directories(my_target PRIVATE ...) , the equivalent will be set_property(TARGET my_target APPEND PROPERTY INCLUDE_DIRECTORIES ...) . But include_directories() , by contrast, sets these directories for all purposes in the current CMakeLists.txt and all of them add_subdirectory() siblings.

If you use target_include_directories(my_target INTERFACE/PUBLIC ...) , there is no such function in CMake before version 2.8.11. You can model the behavior of self-propagating include directories, but this is much more complicated.

Recommendation

Do not use the new command if you still want to support older versions of CMake. Because it is not just target_include_directories() (see Matrix / CMake Version Compatibility Commands ).

References

Backward compatibility target_include_directories()

The following code shows what older versions of CMake 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: calling my_update_inc_dirs() at the end is required):

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() 
+5
source

Source: https://habr.com/ru/post/1273556/


All Articles