【问题标题】:CMake and compiler warningsCMake 和编译器警告
【发布时间】:2012-12-23 06:26:37
【问题描述】:

我使用CMake 来生成unix makefile。之后,我使用make 实用程序编译项目。 问题是我看不到任何警告!例如,这会导致没有警告的干净构建:

#include <iostream>

class Foo
{
    int first;
    int second;
public:
    Foo(int a, int b)
    : second(a) // invalid initialization order
    , first(b)
    {
    }
};

int main(int argc, char** argv)
{
    int unused; // unused variable
    int x;
    double y = 3.14159;
    x = y; // invalid cast
    Foo foo(1,2);
    std::cout << y << std::endl;
    return 0;
}

未使用的变量和有损变量强制转换 - 没有警告!我的CMakeLists.txt 文件很简约:

cmake_minimum_required(VERSION 2.8)

add_executable(main main.cpp)

当我运行cmakemake 时,我的输出如下所示:

[100%] Building CXX object CMakeFiles/main.dir/main.cpp.o
Linking CXX executable main
[100%] Built target main

但是当我添加这行代码时:

#warning ("Custom warning")

结果输出包含警告:

[100%] Building CXX object CMakeFiles/main.dir/main.cpp.o
../src/main.cpp:15:2: warning: #warning ("Custom Warning") [-Wcpp]
Linking CXX executable main
[100%] Built target main

我使用 Ubuntu 12.04 LTS 和 GCC 作为编译器。也许 CMake 将一些标志传递给编译器,导致没有警告。我怎样才能检查它?我无法读取 CMake 生成的 makefile,它们有点神秘。

【问题讨论】:

标签: gcc cmake


【解决方案1】:

编译器警告的位置是分开的。有些包维护者会告诉你他们知道自己在做什么,无论如何都应该忽略编译器警告。 (我认为他们大错特错了。)但我想这就是为什么 CMake 主要不考虑警告设置的原因。

如果您想更复杂一点,请检查正在使用的编译器,并将标志添加到特定目标的特定属性。

应用于单个目标

if ( CMAKE_COMPILER_IS_GNUCC )
    target_compile_options(main PRIVATE -Wall -Wextra)
endif()
if ( MSVC )
    target_compile_options(main PRIVATE /W4)
endif()

应用于所有目标

if ( CMAKE_COMPILER_IS_GNUCC )
    set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -Wall -Wextra")
endif()
if ( MSVC )
    set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} /W4")
endif()

注意:为 GCC 添加 -Werror 或为 MSVC 添加 /WX 以将所有警告视为错误。这会将所有警告视为错误。这对于新项目强制执行警告严格性非常方便。

另外,-Wall -Wextra 并不意味着“所有错误”;从历史上看,-Wall 表示“所有错误每个人都可以同意”,-Wextra 表示“更多”。从它开始,然后仔细阅读 您的 GCC 版本的手册,并了解编译器在警告方面可以为您做什么else...

【讨论】:

  • @NormanBLancaster:感谢您建议的编辑,但我并不真正相信-Werror(不同的编译器版本会抛出不同的警告,默认情况下将它们变成错误会使构建变得脆弱)。在endif() 中重复条件会使代码更难阅读恕我直言。覆盖CMAKE_CXX_FLAGS 也不是一个好习惯...从好的方面来说,我添加了-Wextra,所以... ;-)
  • 我相信是target_compile_options,而不是target_compile_option
  • endif 的参数真的需要吗?
  • @QPaysTaxes:它适用于 CMake 的早期版本。它不再是,我不再使用它了。已编辑。
  • 现代方式是使用add_compile_options
【解决方案2】:

用这行代码解决问题:

add_definitions ("-Wall")

结果现在如下所示:

[100%] Building CXX object CMakeFiles/main.dir/main.cpp.o
../src/main.cpp:15:2: warning: #warning ("Custom warning") [-Wcpp]
../src/main.cpp: In constructor ‘WarnSrc::WarnSrc(int, int)’:
../src/main.cpp:6:9: warning: ‘WarnSrc::second’ will be initialized after [-Wreorder]
../src/main.cpp:5:9: warning:   ‘int WarnSrc::first’ [-Wreorder]
../src/main.cpp:8:5: warning:   when initialized here [-Wreorder]
../src/main.cpp: In function ‘int main(int, char**)’:
../src/main.cpp:19:9: warning: unused variable ‘unused’ [-Wunused-variable]
../src/main.cpp:20:9: warning: variable ‘x’ set but not used [-Wunused-but-set-variable]
Linking CXX executable main
[100%] Built target main

【讨论】:

  • 奇怪的是默认没有启用。
  • 这是个坏主意! add_definitions 在不期望 -W 选项的上下文中传递,例如MinGW 的 Windres,它会立即断裂。可能还有其他人。
  • 虽然这可能并不理想,但这个答案很有帮助,因此我认为它值得点赞。堆栈溢出的意义在于提供答案,对于一个问题的不同方法和答案越多越好,只要人们意识到利弊。
猜你喜欢
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-21
  • 1970-01-01
相关资源
最近更新 更多