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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With