VS: [suggestion] change how the Visual Studio generator handles compiler-warning flags
The strategy used to configure the MSVC compiler-warning flags in the VS generator is unnecessarily complex, severely limits control over warning flags, and incompatible with configurations for other generators.
The MSVC compiler (cl.exe) processes the compiler-warning-flags in order of occurrence, subsequent flags for the same warning override earlier settings.
I.e. Manually calling cl.exe with:
/w34619 /we4619 /wd4619,
sets warning C4619 to warning-level 3, promotes it to an error (always on) and disables it.
The result is the warning being disabled.
MSBuild .vcproj-files have the following fields to configure individual compiler warnings:
DisableSpecificWarningsaccepting a list of compiler warning ids, to be translated into
TreatSpecificWarningsAsErrorstaking a list of ids, translated into
AdditionalOptionstaking any flag, as-is.
These fields are supplied to the compiler in the following order:
First warnings are disabled. Then warnings are enabled as errors.
(This works fine for warnings that are part of the default
Finally all flags from
This field allows for adding additional warnings and overriding of inherited warning flags behaviour.
CMake's Visual Studio generator transforms the supplied warning flags to match the .vcproj-file implementation. It collects all applicable compiler warning flags matching
/we<id> and puts these in the aforementioned fields, the
/w[1-4]<id> flags end up in
And this is where things break.
The Visual Studio generators reorder the warning flags always as
/wd<id> /we<id> /w[1-4]<id>.
- Setting additional warnings (not present in
/w[1-4]<id>causes difficulties when inherited. These cannot be disabled by setting
/wd<id>but require removal of the added flag. And potentially re-adding flags down the inheritance tree.
- This behaviour is unique for the combination: CMake + Visual Studio generator + MSVC
- When using the Visual Studio generator with LLVM/clang-cl, there is no separate behaviour for
- With the Ninja-build generator:
all flags are applied in the order specified with
target_compile_options(). Both with MSVC and Clang-cl.
- This behaviour is unexpected (even for MSVC project users).
- Calling cl.exe manually respects the order of declaration.
- The CMake documentation for
target_compiler_options()explicitly states it "append[s] items in the order called".
- The CMake interface does not correspond with the use of those custom fields.
There is no way to explicitly request the different fields and their mechanics.
The use of the full
/w.*flags in the
target_compile_options()function, or directly in the
COMPILE_OPTIONSproperty, suggests behaviour similar to the
- There is no benefit in using the specialized fields and their mechanics over leaving all
/w.*flags in the
AdditionalOptionsfield, which offers conventional CMake behaviour.
Drop the use of the separate MSBuild configuration fields:
Leave all warning flags in the
AdditionalOptions field, which leaves control over the order and proper override behaviour with the implementers CMake configuration.
For existing projects the observable change could be a
/we<id> option becoming active,
if it was shadowed by a
/we<id>) flag, targeting the same compiler warning
This will only happen when the
/we<id> flag is the latest added.
One would assume this to be the intended behaviour.
And this is the behaviour when the same CMake configuration is used with the Ninja generator.
Any project functioning with more than just the VS generators might see the MSBuild configurations behaving like the others. Workarounds using custom functions to remove flags should still function, albeit becoming unnecessary.