How to know the generator previously used ?

CMake version: 3.29.3

Hello,

I develop on Windows, and use a batch file to tun the build. This script calls the CMake command :

REM positionning in the CMake bin directory
cd "%BIN_DIR%"

REM remove the previous CMake items (platform/mode may have changed)
if exist CMakeFiles rmdir /s /q CMakeFiles
if exist CMakeCache.txt del CMakeCache.txt

cmake^
 -S "<current_directory"^
 -B .^
 -D ...
 -D PLATFORM=%PLATFORM%^
 -D MODE=%MODE%
 -D VS_GENERATOR=%VS_GENERATOR%^
 -D ...

Note I gave to the batch script an argument about the generator (VS2017, VS2019, VS2022).

In the current directory, there is a CMakeLists.txt which calls ExternalProject_Add() :

ExternalProject_Add(...
      SOURCE_DIR ...
      BINARY_DIR ...
      DOWNLOAD_COMMAND ""
      CMAKE_GENERATOR ${cmake_generator_param}
      CMAKE_GENERATOR_PLATFORM ${cmake_generator_platform_param}
      CMAKE_ARGS
          -D...
          -D...
          -D...

cmake_generator_param is a correct value deduced from the argument given to the batch.

All the code is used to build several projects, with potentially differents versions of Visual Studio and architecture. That’s why I delete the cache at the beginning of the batch. But maybe I’m wrong.

With CMake 3.29.3, when I switch among Visual Studio generators, I get the message :

Does not match the generator used previously: Visual Studio 17 2022
Either remove the CMakeCache.txt file and CMakeFiles directory or choose a different binary directory.

I so should add the --fresh option when I switch version. But my script has to know when it needs to apply this option (I need some automatization for continuous integration).

I think I have two solutions :

  • Saving a cache value in the upper CMake execution, but so I can’t delete the cache at the beginning of the batch script. What could the side effects. The cache deletion instructions are legacy, but I guess the comment is obsolete, because we hard set the platform and mode in the CMake command.
  • Request a cache value for the lower CMake execution. But how to do that ?

Can you parse CMakeCache.txt for CMAKE_GENERATOR:INTERNAL=Ninja and similar? This is how I’ve done things like this from Python say.

I thought it would be possible to do cmake -Bbuild -LA | grep CMAKE_GENERATOR but that one variable is omitted from the output…

No, I can’t use Ninja.

cmake -L is only for variables set with the option -D (from what I understand from the documentation).

Looks like parsing the CMakeCache.txt to extract CMAKE_GENERATOR value is the only way, as it was mentioned in the first reply. Don’t get me wrong, your question seems to be valid to me, but I can’t think of any other way.

What you could also do is set CMAKE_GENERATOR environment variable - that way all the projects in the system will have that generator as the default one, unless a different generator is provided with -G or with this ${cmake_generator_param} thing from your example.

1 Like

Actually, I am working on this solution.
I coded in a new .cmake file a function to retrieve the value, but I can’t manage to include it: it can’t be found, although it is in caller’s directory! Note the caller is also an included .cmake…
I don’t know if it possible to get the path of an included cmake file from inside this file, without relying to waht was given as path to include it. It seems that CMAKE_CURRENT_LIST_DIR is supposed to return this value, but i doesn’t. I’m going to ask an other question…

Try making a script “detect_gen.cmake”:

cmake_minimum_required(VERSION 3.21)

file(REAL_PATH ${bindir} bindir EXPAND_TILDE)

file(READ "${bindir}/CMakeCache.txt" _cache)

if(_cache MATCHES "CMAKE_GENERATOR:INTERNAL=([^ \n]+)")
  set(CMAKE_GENERATOR ${CMAKE_MATCH_1})
  message(STATUS "Detected CMake generator: ${CMAKE_GENERATOR}")
else()
  message(FATAL_ERROR "Failed to detect CMake generator")
endif()

This script is used like:

cmake -Dbindir=/path/to/build -P detect_gen.cmake

reference

I made a similar function, but as I didn’t find the optimal regular expression, my function is longer !
I’ll try yours.

Thanks!