ExternalProject_Add and CMAKE_CONFIGURATION_TYPES

I added an external project to my CMake file, and I wanted it to have the same set of configurations as the parent project. However, the generated project seems to have only one configuration - the default RelWithDebInfo. Here’s the code:

include(ExternalProject)
ExternalProject_Add(allegro_monolith_ext 
    SOURCE_DIR ${ALLEGRO_DIR} 
    CMAKE_GENERATOR ${CMAKE_GENERATOR}
    CMAKE_GENERATOR_PLATFORM ${CMAKE_GENERATOR_PLATFORM}
    CMAKE_CACHE_ARGS 
        -DWANT_MONOLITH:BOOL=ON
        -DWANT_DEMO:BOOL=OFF
        -DWANT_DOCS:BOOL=OFF
        -DWANT_VIDEO:BOOL=OFF
        -DWANT_EXAMPLES:BOOL=OFF
        -DFREETYPE_ZLIB:BOOL=ON
        -DFREETYPE_BZIP2:BOOL=OFF
        -DSHARED:BOOL=ON
        -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
        -DCMAKE_CONFIGURATION_TYPES:STRING=${CMAKE_CONFIGURATION_TYPES}
        -DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_BINARY_DIR}/allegro
    LOG_CONFIGURE 1
)

In the generated CMakeCache:

CMAKE_CONFIGURATION_TYPES:INTERNAL=RelWithDebInfo

But the rest of options are set, so I’m sure that they are not entirely ignored. I assumed that external project should be built with the same set of configurations and currently selected configuration as the main project, but it’s not happening: if I change build type to Debug in Visual Studio, I get error error MSB8013: This project doesn't contain the Configuration and Platform combination of Debug|x64.

CMAKE_CONFIGURATION_TYPES is a ;-separated list. So this ends up with cache args of (in some order):

-DCMAKE_CONFIGURATION_TYPES:STRING=RelWithDebInfo
Debug
Release
MinSizeRel

You need to replace the ; and let EP know with the LIST_SEPARATOR argument.

Quoting may also help to some extent; I’d try that with your minimum CMake and bump if that is more palatable to you (and it works on newer CMake versions).

string(REPLACE ";" "|" CONFIGS "${CMAKE_CONFIGURATION_TYPES}")
message(STATUS "=====> ${CONFIGS}")

ExternalProject_Add(allegro_monolith_ext 
LIST_SEPARATOR "|"
    ...
CMAKE_CACHE_ARGS 
    -DCMAKE_CONFIGURATION_TYPES:STRING=${CONFIGS}

prints =====> Debug|Release|MinSizeRel|RelWithDebInfo, so CONFIGS is now a corrected value, but ExternalProject is still generated with only RelWithDebInfo. Interestingly, the list of configurations ends up with “;” in “allegro_monolith_ext-cache-Debug.cmake” (the file used to populate CMake cache with CMAKE_CACHE_ARGS). And CMakeCache.txt still ends up with a single config.

I’m not sure LIST_SEPARATOR makes sense in context of CMAKE_CACHE_ARGS - it documented to work on command line arguments mostly. If I move DCMAKE_CONFIGURATION_TYPES to CMAKE_ARGS, it gets passed to CMake with escaped ‘;’ between configs, but they’re still ignored silently.

OK, it seems that the external project was overwriting
CMAKE_CONFIGURATION_TYPES. Who knew…