129
votes

How to set the warning level for a project (not the whole solution) using CMake? Should work on Visual Studio and GCC.

I found various options but most seem either not to work or are not consistent with the documentation.

6

6 Answers

112
votes

In modern CMake, the following works well:

if(MSVC)
  target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX)
else()
  target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
endif()

My colleague suggested an alternative version:

target_compile_options(${TARGET_NAME} PRIVATE
  $<$<CXX_COMPILER_ID:MSVC>:/W4 /WX>
  $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic -Werror>
)

Replace ${TARGET_NAME} with the actual target name. -Werror is optional, it turns all warnings into errors.

Or use add_compile_options(...) if you want to apply it to all targets as suggested by @aldo in the comments.

Also, be sure to understand the difference between PRIVATE and PUBLIC (public options will be inherited by targets that depend on the given target).

102
votes

UPDATE: This answer predates the Modern CMake era. Every sane CMake user should refrain from fiddling with CMAKE_CXX_FLAGS directly and call the target_compile_options command instead. Check the mrts' answer which presents the recommended best practice.

You can do something similar to this:

if(MSVC)
  # Force to always compile with W4
  if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
  else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
  endif()
elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
  # Update if necessary
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
endif()
27
votes

Some CMake modules I've written include experimental cross-platfrom warning suppression:

sugar_generate_warning_flags(
    target_compile_options
    target_properties
    ENABLE conversion
    TREAT_AS_ERRORS ALL
)

set_target_properties(
    foo
    PROPERTIES
    ${target_properties}
    COMPILE_OPTIONS
    "${target_compile_options}"
)

Result for Xcode:

  • Set CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION Xcode attribute (aka build settings -> warnings -> suspicious implicit conversions -> YES)
  • Add compiler flag: -Werror

Makefile gcc and clang:

  • Add compiler flags: -Wconversion, -Werror

Visual studio:

  • Add compiler flags: /WX, /w14244

Links

11
votes

As per Cmake 3.21.0 documentation:

if (MSVC)
    # warning level 4 and all warnings as errors
    add_compile_options(/W4 /WX)
else()
    # lots of warnings and all warnings as errors
    add_compile_options(-Wall -Wextra -pedantic -Werror)
endif()

GCC and Clang share these flags, so this should cover all 3.

8
votes

Here is the best solution I found so far (including a compiler check):

if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
    add_definitions(/W2)
endif()

This will set warning level 2 in Visual Studio. I suppose with a -W2 it would work in GCC too (untested).

Update from @Williams: It should be -Wall for GCC.

3
votes
if(MSVC)
    string(REGEX REPLACE "/W[1-3]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()

If you use target_compile_options - cmake will try to use double /W* flag, which will give warning by compiler.