_MBCS in 4.2, and policy CMP0204

I recently updated one of my projects to use cmake_minimum_required(VERSION 4.2).

My project sets the defines UNICODE and _UNICODE globally, so I assumed that the new policy CMP0204 should work without problem for me. It says:

CMake 4.2 and above, when targeting the MSVC ABI, prefer to compile sources with _MBCS defined by all generators unless another charset preprocessor definition is found (_UNICODE or _SBCS).

But it seems like _UNICODE is not “found” in my project, even though it is set. After some experimentation I have concluded that:

  • if _UNICODE is set via add_compile_definitions() it is found
  • if _UNICODE is set via target_compile_definitions() it is found
  • if _UNICODE is set via CMAKE_CXX_FLAGS_DEBUG and CMAKE_CXX_FLAGS_RELEASE, or CMAKE_CXX_FLAGS, then it is NOT found

I know that using variables like CMAKE_CXX_FLAGS_DEBUG for “permanent” settings is not good style. But my current project happened to use it.

The effect on the project was to get all of _MBCS, _UNICODE, and UNICODE set when building with Visual C++, and the same with Ninja.

Is this difference in behavior, depending on which method is used, intentional?

I’m thinking about switching to setting _UNICODE and UNICODE via add_compile_definitions(), to get past this problem. I guess that way would be equally “global” for my project, and will work right away with 4.2 behaviour.

CMake only checks a target’s evaluated compile definitions for the preprocessor defines, not the complete flag line. Generally CMake tries to avoid parsing arbitrary flag fragments like CMAKE_<LANG>_FLAGS for infomation, only relying on flag entries in dedicated properties. That means it only sees definitions supplied via the various COMPILE_DEFINITIONS properties.

This is maybe a bug, you can open one describing your use case on the tracker. I think it’s a little strange CMake has no abstraction for describing compile definitions from cache variables other than CMAKE_<LANG>_FLAGS, but then ignores the *_FLAGS variables of this policy.

CMake either needs a dedicated cache variable for compile definitions, or needs to consider the language-specific flags in its calculation for MSVC encoding.

Thanks for the explanation. I hadn’t thought about that, but it seems reasonable.

I have now moved away from setting the defines via those variables, so I’m avoiding the problem described in my original post.