如何在 CMakeLists.txt 文件中的第三方库头文件中抑制 Clang 警告?

mic*_*190 10 c++ cmake clang suppress-warnings

我目前正在尝试使用 Visual Studio 2019 的新 CMake 功能(特别是将 Clang 和 Ninja 与 CMake 和 VS2019 结合使用)来设置一个项目,该项目将使用多个编译器(包括 Clang、MSVC 和 GCC)。

我正在使用 CMake 将项目配置为“与编译器无关”,这样我就不需要编辑代码本身来通过预处理器指令或#pragma指令处理不同的编译器

这个项目需要进行配置,以具有较高的警告级别(/W4对于MSVC, ,-Wall-Wextra-Wpedantic为锵),并且必须将警告视为错误。

在配置项目的 MSVC 部分时,我没有任何问题。很多这些设置都有“正常”的默认值,正如我所期望的那样“正常工作”。但是,当涉及到 Clang 时,我遇到了一个问题:

我似乎无法禁用第三方库头文件的警告。我目前正在使用Dear ImguiSFML库。由于 Dear Imgui 未预编译,因此我只需在我的CMakeLists.txt文件中执行以下操作即可将其包含在内:

include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/libs/imgui
)
Run Code Online (Sandbox Code Playgroud)

我使用 SFML 的静态链接版本,因此我执行以下操作以包含它:

# Find SFML and link statically to it.
# Note: We need to set the SFML_DIR variable manually.
set(SFML_STATIC_LIBRARIES TRUE)
set(SFML_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libs/SFML-2.5.1/lib/cmake/SFML")
find_package(SFML 2.5.1 COMPONENTS system audio window graphics REQUIRED)

target_link_libraries(${PROJECT_NAME}
    PRIVATE
        sfml-system
        sfml-audio
        sfml-window
        sfml-graphics
)
Run Code Online (Sandbox Code Playgroud)

遗憾的是,SFML 目前没有遵循当前的 CMake 标准添加库的方式,因此通过 CMake 使用或配置它有点奇怪。

现在,当涉及到在我的项目中包含库时,上面的方法工作得很好(但它可能是我需要更改的内容,因此我已将其包含在帖子中)。当我在使用 Clang 时尝试将警告和警告作为错误配置强加给他们时,问题就出现了。

以下是我的CMakeLists.txt文件中处理 Clang 和 C++ 配置的部分:

# Set project to use C++ 17 standard.
set_target_properties(
    ${PROJECT_NAME}
    PROPERTIES
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED ON
)


target_compile_options(${PROJECT_NAME} PRIVATE
    # All warnings, warnings as errors, be pedantic.
    -Wall
    -Wextra
    -Werror
    -Wpedantic

    # Disable warnings about C++98 incompatibility. We're using C++17 features...
    -Wno-c++98-compat
    -Wno-c++98-compat-pedantic
)
Run Code Online (Sandbox Code Playgroud)

使用上述配置会在 Dear Imgui 的源文件中导致数百个警告/错误(由于使用了“老派”C++/C 风格的代码),以及在 SFML 自己的源文件和头文件中的一大堆警告/错误文件。

在确定以下解决方案之前,我一直在寻找解决此问题的方法近一个星期(这并不完全有效,稍后会详细介绍):

set(LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/libs")
set(IMGUI_FOLDER "${LIBS_FOLDER}/imgui")
set(SFML_FOLDER "${LIBS_FOLDER}/SFML-2.5.1/include/SFML")

file(GLOB LIBRARY_FILES
    # Dear-imgui
    "${IMGUI_FOLDER}/*.cpp"
    "${IMGUI_FOLDER}/misc/freetype/*.cpp"
    "${IMGUI_FOLDER}/misc/fonts/*.cpp"
    "${IMGUI_FOLDER}/misc/cpp/*.cpp"

    # SFML
    "${SFML_FOLDER}/Audio/*.cpp"
    "${SFML_FOLDER}/Graphics/*.cpp"
    "${SFML_FOLDER}/Network/*.cpp"
    "${SFML_FOLDER}/System/*.cpp"
    "${SFML_FOLDER}/Window/*.cpp"
)

set_source_files_properties(
    ${LIBRARY_FILES}
    PROPERTIES
    COMPILE_FLAGS
    "-Wno-everything"
)
Run Code Online (Sandbox Code Playgroud)

我首先GLOB-ing 我的库源文件(注意:我知道GLOB通常被看不起,但我觉得将它与第三方库文件一起使用很好,因为无论如何它们都不应该改变)。然后我将它们传递给set_source_files_properties函数以应用-Wno-everything标志,这似乎正确地抑制了来自这些文件的所有错误和警告。

一切似乎都很好,除了一个警告,如果不使用#pragma我的代码中的指令(我想避免),我似乎无法禁用该警告。编译main包含 SFML 标头的空函数时,我收到有关其.hpp文件的警告(无法传递给set_source_files_properties函数)。

这个:

#include <SFML/Graphics.hpp>

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

导致以下警告/错误:

zero as null pointer constant [-Werror,-Wzero-as-null-pointer-constant]
declaration is marked with '\deprecated' command but does not have a deprecation attribute [-Werror,-Wdocumentation-deprecated-sync]
declaration is marked with '\deprecated' command but does not have a deprecation attribute [-Werror,-Wdocumentation-deprecated-sync]
declaration is marked with '\deprecated' command but does not have a deprecation attribute [-Werror,-Wdocumentation-deprecated-sync]
Run Code Online (Sandbox Code Playgroud)

在这些各自的 SFML 文件中:

ThreadLocal.hpp (57)
Keyboard.hpp (161)
Event.hpp (105)
PrimitiveType.hpp (52)
Run Code Online (Sandbox Code Playgroud)

我尝试过的其他方法不起作用:

  • .h/.hpp文件放在set_source_files_propertiesCMake 函数中(与.cpp文件一起)。适用于 Dear Imgui,但它的所有错误都在.cpp文件中,而不是其标题中。不适用于 SFML 的标头。
  • (不是针对 SFML,而是针对 Dear Imgui)将目录包含为SYSTEM包含以抑制警告。似乎在 Windows 上不起作用。不能用 SFML 真正做到这一点,因为我使用的是 CMake 的find_package函数而不是手动完成所有事情。
  • 使用#pragma说明。虽然这有效,但每个 SFML 文件都有几十个不同的错误,我想避免#pragma在任何地方使用s(或者将 SFML 的头文件包装在我自己的头文件中,这些头文件只是将#include指令包装在#pragmas 中)。

甚至可以在没有#pragmas 的情况下抑制我的库标题的这些警告吗?我以前从未真正使用过 Clang,所以如果这看起来是一个简单的问题,我深表歉意,但在线搜索并没有真正给我任何有用的东西:

  • 在命令行之外(我在 CMake 中使用 Visual Studio)。
  • 在 Windows 上(系统标志似乎不适用于此设置)。
  • 这将特别适用于 CMake。

Atn*_*nNn 13

您可以将包含路径标记为SYSTEM。大多数编译器不会在系统头中报告警告。在你的情况下,可能看起来像这样:

\n
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/libs/imgui)\n\nset_target_properties(sfml-system PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-system,INTERFACE_INCLUDE_DIRECTORIES>)\nset_target_properties(sfml-audio PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-audio,INTERFACE_INCLUDE_DIRECTORIES>)\nset_target_properties(sfml-window PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-window,INTERFACE_INCLUDE_DIRECTORIES>)\nset_target_properties(sfml-graphics PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-graphics,INTERFACE_INCLUDE_DIRECTORIES>)\n
Run Code Online (Sandbox Code Playgroud)\n

例如,这个虚拟项目:

\n
project(example)\ncmake_minimum_required(VERSION 3.18)\n\nadd_library(dep INTERFACE)\ntarget_include_directories(dep INTERFACE include)\nfile(WRITE include/header.h "static int a;")\n\nadd_library(lib STATIC lib.c)\ntarget_link_libraries(lib PRIVATE dep)\ntarget_compile_options(lib PRIVATE -Wunused -Werror)\nfile(WRITE lib.c "#include <header.h>")\n
Run Code Online (Sandbox Code Playgroud)\n

失败:

\n
$ cmake . && make\ninclude/header.h:1:12: error: \xe2\x80\x98a\xe2\x80\x99 defined but not used [-Werror=unused-variable]\n
Run Code Online (Sandbox Code Playgroud)\n

但添加这一行后:

\n
set_target_properties(dep PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:dep,INTERFACE_INCLUDE_DIRECTORIES>)\n
Run Code Online (Sandbox Code Playgroud)\n

它构建没有错误。

\n