Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake: target_link_libraries include as SYSTEM to suppress compiler warnings

Tags:

To suppress compiler warnings that originate from libraries I use in my application, I manually include their directories with target_include_directories(myapp SYSTEM ...) as system libraries before adding them with target_link_libraries like so:

add_executable(myapp myapp.cpp) target_include_directories(myapp SYSTEM   PRIVATE "extern/lib/include" ) target_link_libraries(myapp lib::lib) 

However, that kind of feels hacky and will also break if the developers of lib decide to change the include path. This wouldn't be a problem if using only target_link_library but then, of course, they are included via -I and again I would get compiler warnings coming from this include.

Is there any more elegant and fail-safe way of doing this? It would be great if target_link_libraries had a SYSTEM option to tell cmake to include it as a system library.

like image 243
sebastian Avatar asked Sep 02 '18 10:09

sebastian


People also ask

How do you stop warnings in Cmake?

cmake:48 (include) CMakeLists. txt:208 (find_package) This warning is for project developers. Use -Wno-dev to suppress it. You can disable the warning like this when you are configuring your build.

What does Cmake Target_link_libraries do?

Specify libraries or flags to use when linking a given target and/or its dependents. Usage requirements from linked library targets will be propagated. Usage requirements of a target's dependencies affect compilation of its own sources.


1 Answers

I defined a function to handle this for me:

function(target_link_libraries_system target)   set(libs ${ARGN})   foreach(lib ${libs})     get_target_property(lib_include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES)     target_include_directories(${target} SYSTEM PRIVATE ${lib_include_dirs})     target_link_libraries(${target} ${lib})   endforeach(lib) endfunction(target_link_libraries_system) 

I can now call target_link_libraries_system(myapp lib::lib) and the include directories are read from the target's properties.

This can be extended to optionally specify the PUBLIC|PRIVATE|INTERFACE scope:

function(target_link_libraries_system target)   set(options PRIVATE PUBLIC INTERFACE)   cmake_parse_arguments(TLLS "${options}" "" "" ${ARGN})   foreach(op ${options})     if(TLLS_${op})       set(scope ${op})     endif()   endforeach(op)   set(libs ${TLLS_UNPARSED_ARGUMENTS})    foreach(lib ${libs})     get_target_property(lib_include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES)     if(lib_include_dirs)       if(scope)         target_include_directories(${target} SYSTEM ${scope} ${lib_include_dirs})       else()         target_include_directories(${target} SYSTEM PRIVATE ${lib_include_dirs})       endif()     else()       message("Warning: ${lib} doesn't set INTERFACE_INCLUDE_DIRECTORIES. No include_directories set.")     endif()     if(scope)       target_link_libraries(${target} ${scope} ${lib})     else()       target_link_libraries(${target} ${lib})     endif()   endforeach() endfunction(target_link_libraries_system) 

This extended version will also print a warning if a library didn't set its INTERFACE_INCLUDE_DIRECTORIES property.

like image 67
sebastian Avatar answered Sep 21 '22 11:09

sebastian