Understanding CMP0092: MSVC Warning Flag Handling in CMake
What is CMP0092?
CMP0092 is a CMake policy introduced in version 3.15 that controls how warning flags are handled for MSVC-like compilers. It addresses a behavior change that occurred between CMake versions 3.14 and 3.15.
What's the Issue?
New Behavior (CMake >= 3.15)
- To provide more control, MSVC warning flags are no longer included in the default
CMAKE_<LANG>_FLAGS
values. - This allows projects to explicitly set the desired warning level.
- To provide more control, MSVC warning flags are no longer included in the default
- By default, MSVC warning flags (like
/W3
) were automatically added to theCMAKE_<LANG>_FLAGS
variable for C and C++ languages. - This could be problematic if a project wanted to set a different warning level programmatically. It necessitated manual manipulation of the
CMAKE_<LANG>_FLAGS
variable, requiring knowledge of CMake's default flags.
- By default, MSVC warning flags (like
Why Use CMP0092?
- Compatibility with Older Projects
- CMP0092 offers compatibility with projects that haven't been updated to expect the absence of warning flags in
CMAKE_<LANG>_FLAGS
. - By setting this policy to
OLD
, projects can maintain the pre-3.15 behavior if necessary.
- CMP0092 offers compatibility with projects that haven't been updated to expect the absence of warning flags in
How to Use CMP0092
Set the Policy
- Use the
cmake_policy
command to explicitly set CMP0092 to eitherOLD
orNEW
.
cmake_policy(CMP0092 NEW) # Enable new behavior (warning flags not in default) # OR cmake_policy(CMP0092 OLD) # Maintain old behavior (warning flags in default)
- Use the
Placement of the Policy Command
- The policy setting takes effect at the first
project
orenable_language
command that initializes theCMAKE_<LANG>_FLAGS
variable for a given language. - For consistency across a project, ensure the policy is set at the top level or before any language-specific configuration.
- The policy setting takes effect at the first
Important Considerations
- Default Behavior (No Policy Set)
- Unlike many policies, CMake doesn't warn if CMP0092 isn't explicitly set. It defaults to the OLD behavior (warning flags in
CMAKE_<LANG>_FLAGS
).
- Unlike many policies, CMake doesn't warn if CMP0092 isn't explicitly set. It defaults to the OLD behavior (warning flags in
- Nested Projects
- If your project has nested subdirectories, make sure to convert all projects consistently (either to OLD or NEW behavior) to avoid potential issues.
Example 1: Setting CMP0092 to NEW (Modern Behavior)
This example sets the policy to NEW
, ensuring MSVC warning flags are not included in the default compiler flags:
cmake_policy(CMP0092 NEW) # Enable new behavior (warning flags not in default)
project(MyProject)
# Language-specific configuration (warning flags can be set explicitly here)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3") # Example: Set warning level for C
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") # Example: Treat warnings as errors for C++
add_executable(my_executable source1.cpp source2.c)
Example 2: Maintaining Old Behavior (Compatibility)
This example shows how to maintain the pre-3.15 behavior by setting CMP0092 to OLD
:
cmake_policy(CMP0092 OLD) # Maintain old behavior (warning flags in default)
project(MyOldProject)
# No need to set warning flags explicitly (uses CMake's default behavior)
add_executable(my_old_executable source_old.cpp)
Explicitly Setting Warning Flags
- Regardless of the CMP0092 policy setting, you can always explicitly set the desired warning flags for each language using
target_compile_options
:
project(MyProject)
# Set warning flags explicitly (works with any CMP0092 setting)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3") # Example: Set warning level for C
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") # Example: Treat warnings as errors for C++
add_executable(my_executable source1.cpp source2.c)
Treat Warnings as Errors
- If you want warnings to be treated as errors during compilation, use the
COMPILE_WARNING_AS_ERROR
target property:
project(MyProject)
# Treat warnings as errors (works with any CMP0092 setting)
set_property(TARGET my_executable PROPERTY COMPILE_WARNING_AS_ERROR ON)
add_executable(my_executable source1.cpp source2.c)
- For more complex scenarios, you could create custom CMake modules to manage warning flags based on specific logic or project requirements.