Предупреждения CMake и компилятора

Я использую CMake для создания make файлов unix. После этого я скомпилирую проект с помощью утилиты 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)

Когда я запускаю CMake, а затем make мой вывод выглядит следующим образом:

[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 передает некоторый флаг компилятору, что приводит к отсутствию предупреждений. Как я могу проверить это? Я не могу читать make файлы, созданные CMake, они немного загадочны.

Ответ 1

Позиции в предупреждениях компилятора разделены. Есть сторонники пакетов, которые скажут вам, что они знают, что они делают, а предупреждения компилятора следует игнорировать в любом случае. (Я думаю, что они не могут быть более ошибочными.) Но я думаю, именно поэтому CMake в основном оставляет настройки предупреждения самостоятельно.

Если вы хотите быть немного более сложным в этом вопросе, проверьте использование компилятора и добавьте флаг к определенному свойству конкретной цели.

Применить к одной цели

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

Применить ко всем целям

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

Примечание: добавьте -Werror для GCC или /WX для MSVC, чтобы обрабатывать все предупреждения как ошибки. Это относится ко всем предупреждениям как к ошибкам. Это может быть удобно для новых проектов для обеспечения строгости предупреждения.

Кроме того, -Wall не означает "все ошибки"; исторически это означало "все ошибки, которые все могли бы согласовать". Начните с -Wall -Wextra, затем прочтите руководство для своей версии GCC и найдите, что еще может сделать компилятор для вас в отношении предупреждений.

Ответ 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