Search code examples
c++cmakeclang-tidy

How to supress clang-tidy warnings from an upstream library in cmake


I am using CMake as my build system generator. I want to use spdlog and clang-tidy. I add spdlog to my project_packages like this:

find_package("spdlog" REQUIRED)
target_link_libraries("project_packages" INTERFACE "spdlog::spdlog")

I set up clang-tidy like this:

option("ENABLE_CLANG_TIDY" "Enable static analysis with clang-tidy" ON)

if(ENABLE_CLANG_TIDY)
    find_program("CLANGTIDY" "clang-tidy")
    if(CLANGTIDY)
        set("CMAKE_CXX_CLANG_TIDY" "${CLANGTIDY}")
    else()
        message(SEND_ERROR "clang-tidy requested but executable not found")
    endif()
endif()

I install spdlog with my system package manager sudo pacman -Syu spdlog and can use spdlog in my code. But, when clang-tidy is enabled I get the error:

/usr/include/spdlog/tweakme.h:81:9: error: 'SPDLOG_FMT_EXTERNAL' macro redefined [clang-diagnostic-macro-redefined,-warnings-as-errors]
#define SPDLOG_FMT_EXTERNAL
        ^
note: previous definition is here
101500 warnings generated.
Suppressed 101499 warnings (101499 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning treated as error

I can disable checking for redefinitions or commenting out line 81 in /usr/include/spdlog/tweakme.h, but this is obviously a hack. I want the macro defined and warnings, I just don't care that it is being redefined multiple times by upstream. tweakme.h is where the system config for the library is located.

It appears that the correct way of suppressing a system library warnings generated by clang-tidy using cmake is to be declaring it to be a SYSTEM library.

https://cmake.org/cmake/help/latest/command/target_include_directories.html

If SYSTEM is specified, the compiler will be told the directories are meant as system include directories on some platforms. This may have effects such as suppressing warnings or skipping the contained headers in dependency calculations (see compiler documentation).

clang-tidy does not emit warnings for files when SYSTEM is specified. But I am using target_link_libraries which does not support the SYSTEM keyword. I have not been able to get target_include_directories to work even though it appears to do almost what I want.

Inline way to disable clang-tidy checks only explains how to disable errors for one line, so disabling clang-tidy before including the header and re-enabling clang-tidy after the include doesn't appear possible.

So I need to find a way to tell cmake that the library I am trying to link is a SYSTEM library so clang-tidy will suppress the error. Is this possible to do, or is their another solution that will let my get my program to compile when upstream is triggering warnings.

Here is a minimal example of what I've got so far: https://hastebin.com/share/oxefeworup


Solution

  • I don't think you need to do anything for targets added by find_package, which are/should be specified as IMPORTED. IMPORTED targets are SYSTEM by default.

    For non-imported targets if your project's cmake_minimum_required(VERSION ...) is v3.25, use the SYSTEM target property (set_property(TARGET spdlog PROPERTY SYSTEM TRUE)) (and for FetchContent and add_subdirectory dependencies in particular, see Is there a way to get -isystem for FetchContent targets? (TL;DR use the SYSTEM argument). For CMake 2.34 and below, use a workaround to move the target's INTERFACE_INCLUDE_DIRECTORIES to its INTERFACE_SYSTEM_INCLUDE_DIRECTORIES described the previous linked Q&A.