How to set warning level correctly in modern CMake?

I believe this is a simple question about some of the most basic of requirements - setting a warning level. Yet I cannot find anything half sane about how to actually achieve this. The common suggestion is:

if (MSVC)
    add_compile_options(/W4 /WX)
else()
    add_compile_options(-Wall -Wextra -pedantic -Werror)
endif()

That sounds more or less fine except it is compiler specific (isn’t CMake supposed to abstract from that?) and produces tonnes of warnings with MSVC:

cl : Command line warning D9025 : overriding '/W3' with '/W4'

The reason is that CMake sets the /W3 flag for MSVC despite it being the default as observed for example in 2018 in this thread (https://cmake.org/pipermail/cmake/2018-December/068716.html). The change would be trivial - dropping the flag - but it was disagreed with right in that thread. The argument was pretty weak though IMO as Microsoft will never change that default and as was pointed out it is not CMake’s job to maintain this anyway (or does CMake guarantee my warnings stay the same across all versions and all compilers? Hardly.).

So we are left with this:

if(MSVC)
    string(REGEX REPLACE "/W[1-3]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
    add_compile_options(-Wall -Wextra -pedantic -Werror)
endif()

So is this how it is done in “modern” CMake? Or is there another way? Or can we perhaps drop that flag from CMake (since it is the default)?

2 Likes

It has already been fixed, but to preserve backward compatibility there is a policy for it (CMP0092). If your project sets its minimum version to 3.15 or later, then /W3 won’t be added to the default set of compiler flags. You can find the change here:

https://gitlab.kitware.com/cmake/cmake/-/merge_requests/3250

1 Like

It works. :slight_smile: Hopefully this gets indexed by Google and others can find about it more easily. Thanks!