当前位置: 首页 > 知识库问答 >
问题:

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

庾和昶
2023-03-14

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

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

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

在配置项目的MSVC部分时,我没有任何问题。许多这些设置都有“理智”的默认值,“只是工作”,正如我所期望的那样。然而,当谈到Clang时,我遇到了一个问题:

我似乎无法禁用第三方库头文件的警告。我目前正在使用亲爱的Imgui和SFML图书馆。因为Dear Imgui不是预编译的,所以我只需在我的< code>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"
)

我从< code>GLOB-ing我的库源文件开始(注意:我知道< code>GLOB通常被轻视,但是我觉得将它与第三方库文件一起使用是很好的,因为它们不应该被改变)。然后,我将它们传递给< code > set _ source _ files _ properties 函数,以应用< code>-Wno-everything标志,这似乎可以适当地抑制这些文件中的所有错误和警告。

一切似乎都很好,除了一个警告,如果不在代码中使用#pragma指令,我似乎无法禁用该警告(我想避免)。当编译包含SFML标头的空main函数时,我收到有关其. 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)

我试过的其他html" target="_blank">方法都不管用:

  • .h/.hpp 文件放在set_source_files_properties CMake 函数中(与.cpp文件一起)。适用于亲爱的Imgui,但它的所有错误都在.cpp文件中,而不是其标题。不适用于 SFML 的标头。
  • (不适用于 SFML,但适用于亲爱的 Imgui)将目录作为系统包含以抑制警告。似乎无法在视窗上工作。使用SFML无法真正做到这一点,因为我使用的是CMake的find_package函数,而不是手动执行所有操作。
  • 使用#pragma说明。虽然这有效,但每个SFML文件都有数十个不同的错误,我想避免在任何地方使用#pragma(或者将SFML的标头包装在我自己的标头中,这些标头只是将#include指令包装在#pragma中)。

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

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

共有2个答案

淳于煌
2023-03-14

有一种方法可以以CMake的方式抑制来自第三方标头的警告。

target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

系统关键字很可能是您想要的。

If SYSTEM is specified, the compiler will be told 
the directories are meant as system include directories on some platforms

< code>SYSTEM关键字为GCC/Clang添加-is SYSTEM。而不是像对待普通的包含目录一样对待该目录。

# GCC docs
Warnings from system headers are normally suppressed.
On the assumption that they usually do not indicate real problems
and would only make the compiler output harder to read.

直到最近,在 CMake 3.22 中,才有一段时间没有针对 MSVC 的解决方案,因为 MSVC 编译器最终添加了对此的支持。

这是MSVC的博客文章,其中他们谈到了新的编译器功能。

The “Ninja” and “NMake Makefiles” generators now use
the MSVC “-external:I” flag for system includes. 
This became available as of VS 16.10 
(toolchain version 14.29.30037).
施超
2023-03-14

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

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>)

它构建时没有错误。

 类似资料:
  • 我有一个.h文件,该文件包含在C和C源文件中。其内容被包装在 然而,当我将它包含在. cpp文件中时,clang-tidy会发出特定于C的消息,比如 < li >警告:在C #中包含“stdbool.h”没有任何效果;请考虑删除它[hicpp-deprecated-headers,genesize-deprecated-headers] < li >警告:包含不推荐使用的C头文件“stdlib .

  • 我正在开发一个使用OpenCV和加速的C项目。不幸的是,在编译时,我的编译器从这些库的包含文件中给了我数百个警告。即使有一个空的主函数,没有其他代码,我仍然从包含语句中得到这些警告。我听说这是Qt等其他第三方库的问题。所有伟大的图书馆。如何抑制 MSVC 中的所有第三方警告。 我知道这些解决方案: 在GCC中:#pragma GCC system_header#include“real_3rd_p

  • 问题内容: 我们正在Java 1.6.0_13下运行一个Java应用程序。崩溃时,它将创建普通的hs_err_pid文件。即使应用程序崩溃,我也不想创建此文件。java命令行上有没有办法抑制这种情况?我熟悉- XX:ErrorFile选项。如果我将其设置为空字符串,将抑制它吗? 问题答案: 如果您使用的是Unix / Linux系统,请尝试设置为(或者,如果您使用的是Windows,请尝试)。

  • 我使用以下命令行参数创建一个5秒的视频从一个单一的png文件。视频包含视频底部附近的输出文件名。我想从视频中抑制文件名,但到目前为止,我所尝试的一切都不起作用。 这可能是一件非常简单的事情,但我却无法理解。 有人能告诉我我需要从这个命令行中添加或减去什么,使它只产生没有文本的视频吗? ffmpeg-loop 1-i img001。png-c:v libx264-t5-pix_fmt yuvj444

  • 问题内容: 每次我都会收到警告: 抑制它的最佳方法是什么?所有软件包都是最新的。 Conf: OSX带有Brew Python 2.7.10(默认,2015年7月13日,12:05:58),pandas == 0.17.0和matplotlib == 1.5.0 问题答案: 您可以禁止所有警告:

  • 问题内容: 我有一个适用于Android的Adobe AIR应用程序。用于此AIR 3.0和Flash Builder 4.6。我需要制作MyANEFile.ane- 必须包含2个外部.jar文件:Flurry.jar + Tapjoy.jar。但是当我制作.ane文件时- 它不起作用。如何将这2个jar文件添加到我的主应用程序jar文件中,以正确制作.ane文件?谢谢。 它向我显示了dalvik