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.
Observed behaviour
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:
-
DisableSpecificWarnings
accepting a list of compiler warning ids, to be translated into/wd<id>
-
TreatSpecificWarningsAsErrors
taking a list of ids, translated into/we<id>
-
AdditionalOptions
taking 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 /W[1-4]
sets.)
Finally all flags from AdditionalOptions
are applied.
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 /wd<id>
and /we<id>
and puts these in the aforementioned fields, the /w[1-4]<id>
flags end up in AdditionalOptions
.
And this is where things break.
The problem
The Visual Studio generators reorder the warning flags always as /wd<id> /we<id> /w[1-4]<id>
.
- Setting additional warnings (not present in
/W4
) with/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
-W*
and-Wno-*
flags. - 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 thetarget_compile_options()
function, or directly in theCOMPILE_OPTIONS
property, suggests behaviour similar to theAdditionalOptions
field.
- There is no benefit in using the specialized fields and their mechanics over leaving all
/w.*
flags in theAdditionalOptions
field, which offers conventional CMake behaviour.
Suggested Change
Drop the use of the separate MSBuild configuration fields: DisableSpecificWarnings
and TreatSpecificWarningsAsErrors
.
Leave all warning flags in the AdditionalOptions
field, which leaves control over the order and proper override behaviour with the implementers CMake configuration.
Backwards compatibility
For existing projects the observable change could be a /wd<id>
or /we<id>
option becoming active,
if it was shadowed by a /w[1-4]<id>
(or /we<id>
) flag, targeting the same compiler warning C<id>
.
This will only happen when the /wd<id>
or /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.