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

标签 c++ cmake clang suppress-warnings

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

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

此项目需要配置为具有高警告级别( /W4 对于 MSVC, -Wall-Wextra-Wpedantic 对于 Clang),并且必须将警告视为错误。

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

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

include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/libs/imgui
)

我使用 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
)

遗憾的是,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
)

使用上述配置会导致 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"
)

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

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

这个:
#include <SFML/Graphics.hpp>

int main()
{
}

导致以下警告/错误:
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]

在这些各自的 SFML 文件中:
ThreadLocal.hpp (57)
Keyboard.hpp (161)
Event.hpp (105)
PrimitiveType.hpp (52)

我尝试过的其他方法不起作用:
  • .h/.hpp set_source_files_properties 中的文件CMake 函数(与 .cpp 文件一起)。适用于 Dear Imgui,但所有错误都在 .cpp 中文件,而不是它的标题。不适用于 SFML 的 header 。
  • (不是针对SFML,而是针对Dear Imgui)包括目录为SYSTEM包括抑制警告。似乎在 Windows 上不起作用。不能用 SFML 真正做到这一点,因为我使用的是 CMake 的 find_package功能,而不是手动完成所有操作。
  • 使用 #pragma指示。虽然这有效,但每个 SFML 文件都有几十个不同的错误,我想避免使用 #pragma s 无处不在(或将 SFML 的 header 包装在我自己的 header 中,这些 header 只是将 #include 指令包装在 #pragma s 中)。

  • 甚至可以在没有 #pragma 的情况下抑制我的库标题的这些警告?我以前从未真正使用过 Clang,所以如果这看起来是一个简单的问题,我深表歉意,但在线搜索并没有真正给我任何有用的东西:
  • 在命令行之外(我在 CMake 中使用 Visual Studio)。
  • 在 Windows 上(系统标志似乎不适用于此设置)。
  • 这将特别适用于 CMake。
  • 最佳答案

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

    include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/libs/imgui)
    
    set_target_properties(sfml-system PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-system,INTERFACE_INCLUDE_DIRECTORIES>)
    set_target_properties(sfml-audio PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-audio,INTERFACE_INCLUDE_DIRECTORIES>)
    set_target_properties(sfml-window PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-window,INTERFACE_INCLUDE_DIRECTORIES>)
    set_target_properties(sfml-graphics PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:sfml-graphics,INTERFACE_INCLUDE_DIRECTORIES>)
    
    例如,这个虚拟项目:
    project(example)
    cmake_minimum_required(VERSION 3.18)
    
    add_library(dep INTERFACE)
    target_include_directories(dep INTERFACE include)
    file(WRITE include/header.h "static int a;")
    
    add_library(lib STATIC lib.c)
    target_link_libraries(lib PRIVATE dep)
    target_compile_options(lib PRIVATE -Wunused -Werror)
    file(WRITE lib.c "#include <header.h>")
    
    失败:
    $ cmake . && make
    include/header.h:1:12: error: ‘a’ defined but not used [-Werror=unused-variable]
    
    但是在添加这一行之后:
    set_target_properties(dep PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:dep,INTERFACE_INCLUDE_DIRECTORIES>)
    
    它构建没有错误。

    关于c++ - 如何在 CMakeLists.txt 文件中的第三方库头文件中抑制 Clang 警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56707123/

    相关文章:

    c++ - lcov 将带有函数声明的行标记为可达但未被覆盖

    c++ - 哪个 Clang 警告等同于 GCC 的 Wzero-as-null-pointer-constant?

    c++ - 如何处理 void decltype();

    c++ - 不同的条件检查方式

    c++ - Android Studio 中的 Gradle 任务排序问题

    c++ - KDevelop4 : Setting up a project using cmake

    c++ - 为什么我不能在此代码中获得返回值优化?

    c++ - QWizard::setField:无法写入属性

    c++ - 为 clion (windows) 配置 SFML

    c - 使用 GCC 构建的变量参数的 EDK2 Shell 应用程序在运行时会导致页面错误