【发布时间】:2019-11-04 12:32:15
【问题描述】:
我目前正在尝试使用 Visual Studio 2019 的新 CMake 功能(尤其是将 Clang 和 Ninja 与 CMake 和 VS2019 结合使用)来设置一个使用多个编译器(包括 Clang、MSVC 和 GCC)的项目。
我正在使用 CMake 将项目配置为“与编译器无关”,因此 我不需要通过预处理器指令或 @ 来编辑代码本身来处理不同的编译器 987654324@指令。
此项目需要配置为具有高警告级别(/W4 用于 MSVC,-Wall、-Wextra 和 -Wpedantic 用于 Clang),并且必须将警告视为错误。
在配置项目的 MSVC 部分时,我没有任何问题。许多这些设置具有“正常”的默认值,正如我所期望的那样“正常工作”。然而,当谈到 Clang 时,我遇到了一个问题:
我似乎无法禁用第三方库头文件的警告。我目前正在使用Dear Imgui 和SFML 库。由于 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 指令(我想避免),我似乎无法禁用它。在编译包含 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)
我尝试过的其他方法不起作用:
- 将
.h/.hpp文件放入set_source_files_propertiesCMake 函数(与.cpp文件一起)。适用于 Dear Imgui,但其所有错误都在.cpp文件中,而不是其标题中。不适用于 SFML 的标头。 - (不适用于 SFML,但适用于 Dear Imgui)将目录包含为
SYSTEM包括禁止警告。似乎不适用于 Windows。 SFML 无法真正做到这一点,因为我使用的是 CMake 的find_package函数,而不是手动执行所有操作。 - 使用
#pragma指令。虽然这有效,但每个 SFML 文件都有几十个不同的错误,我想避免在任何地方使用#pragmas(或者将 SFML 的标头包装在我自己的标头中,只是将#include指令包装在#pragmas 中)。李>
在没有#pragmas 的情况下,甚至可以为我的库标题抑制这些警告吗?我以前从未真正使用过 Clang,如果这似乎是一个简单的问题,我深表歉意,但在线搜索并没有真正给我任何有用的东西:
- 在命令行之外(我正在使用带有 CMake 的 Visual Studio)。
- 在 Windows 上(系统标志似乎不适用于此设置)。
- 这特别适用于 CMake。
【问题讨论】:
-
我知道 gcc 并且可能还会禁用系统包含文件的一些警告。因此,如果您使用 -isystem 命令行选项代替 -I 指定标题目录,它应该可以工作。使用 cmake,您可以使用
target_include_directories(<target> SYSTEM <dir>).指定它 -
@Oliv 如帖子中所述,我不能真正为 SFML 使用
SYSTEM关键字,因为我自己不包括它的目录,我正在使用find_package命令,其中包括SFML 目录以自己的方式。 -
对不起,我没有阅读你所有的长问题。您仍然可以执行 target_include_directories(
SYSTEM )。您可以使用 get_property 获取 。 gcc 和可能 clang 也认为使用 -I 和 -isystem 指定的目录是系统目录。 -
@Oliv 刚刚尝试将 SFML 包含目录添加到我的
target_include_directories函数(使用SYSTEM关键字),但它似乎不起作用。我还尝试在find_package和target_link_libraries函数之前和之后放置函数,但它仍然不起作用。可能是因为警告/错误是头文件本身? -
我遇到过这个问题,简短的故事:VS 有一个与
-isystem相当的实验性等效项(参见devblogs.microsoft.com/cppblog/broken-warnings-theory),因此clang-cl不明确支持它。你仍然可以使用-Xclang -isystem /path/to/libs/imgui破解它。但是...它似乎有问题,可能导致导入的标头无法编译...您必须自己检查它。 (稍后我会尝试使用一些代码示例将其转换为答案,但我需要查看我正在处理的代码)。
标签: c++ cmake clang suppress-warnings