Home > other >  How can cmake_minimum_required required version impact generated files?
How can cmake_minimum_required required version impact generated files?

Time:08-25

I'm experiencing a strange behaviour where changing cmake_minimum_required affects files generated by CMake targetting Visual Studio 2019. According to the doc of cmake_minimum_required:

If the running version of CMake is lower than the required version it will stop processing the project and report an error

So it's just supposed to interrupt project generation.

But, if I create:

main.cpp:

int main()
{
#ifndef _DEBUG
#error "DEBUG flag not set"
#endif

    return 0;
}

and CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.12)

project(hello_world)

set( CMAKE_CONFIGURATION_TYPES "Debug;Release;MyDebug" CACHE INTERNAL "" FORCE )
set( CMAKE_CXX_FLAGS_MYDEBUG "${CMAKE_CXX_FLAGS_DEBUG}" )
set( CMAKE_C_FLAGS_MYDEBUG "${CMAKE_C_FLAGS_DEBUG}" )
set( CMAKE_EXE_LINKER_FLAGS_MYDEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" )
set( CMAKE_SHARED_LINKER_FLAGS_MYDEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" )
set_property( GLOBAL PROPERTY DEBUG_CONFIGURATIONS "Debug;MyDebug" )

add_executable(app main.cpp)

If I generate this project with CMake 3.24.1 for Visual Studio 2019, then it builds correctly using MyDebug config as _DEBUG compilation flag is correctly set.

However, if I change cmake_minimum_required(VERSION 2.8.12) to cmake_minimum_required(VERSION 3.24.1), then it fails to build, reporting DEBUG flag not set, meaning _DEBUG compilation flag is not set anymore.

When I check vcproj file, I see that for MyDebug, <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> is changed to <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>.

Is this a CMake bug or am I doing something wrong?

CodePudding user response:

Of course cmake can change behaviour with its evolution.

As CMake evolves it is sometimes necessary to change existing behavior in order to fix bugs or improve implementations of existing features. *

If it just changes some behaviour in a new version, it introduces a policy, that can explicitly switch cmake to use an old behaviour. The OLD behavior of a policy becomes deprecated by definition and may be removed in a future version of CMake.

See what is changed in the list cmake-policies(7). Also you can set cmake_minimum_required incrementing the major version number by one at a time, run cmake and see what policies were introduced in cmake dump. One of them is changing the behaviour of RuntimeLibrary and _DEBUG.

CodePudding user response:

So it's just supposed to interrupt project generation.

That's not the case at all!

cmake_minimum_required puts your project into a backwards compatibility mode consistent with the version specified. The "Policy Settings" section of that doc talks about this. There are a set of now over one hundred CMake policies that enable breaking improvements to the system. You can see the full list here: https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html

The relevant policy here is CMP0091 which was introduced in CMake 3.15.

CMake 3.15 and above prefer to leave the MSVC runtime library selection flags out of the default CMAKE_<LANG>_FLAGS_<CONFIG> values and instead offer a first-class abstraction. The CMAKE_MSVC_RUNTIME_LIBRARY variable and MSVC_RUNTIME_LIBRARY target property may be set to select the MSVC runtime library. If they are not set then CMake uses the default value MultiThreaded$<$<CONFIG:Debug>:Debug>DLL which is equivalent to the original flags.

So to upgrade your project to a version of CMake newer than 3.15, you'll just need to override the default CMAKE_MSVC_RUNTIME_LIBRARY close to the top of your CMakeLists.txt file:

set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug,MyDebug>:Debug>DLL"
    CACHE STRING "Rule for selecting MSVC runtime")

This uses the $<CONFIG> generator expression to enable the debug runtime for your custom MyDebug config.

  • Related