ExternalProject: Add support for Ninja Multi-Config cross-config mode
With the following project:
cmake_minimum_required(VERSION 3.21)
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Debug")
set(CMAKE_DEFAULT_BUILD_TYPE "RelWithDebInfo")
set(CMAKE_DEFAULT_CONFIGS "all")
set(CMAKE_CROSS_CONFIGS "all")
project(proj NONE)
include(ExternalProject)
set(cmakelists_contents [[
cmake_minimum_required(VERSION 3.21)
project(mysub LANGUAGES CXX)
add_executable(app main.cpp)
]])
set(main_contents [[
int main() {return 0;}
]])
set(base_dir "${CMAKE_CURRENT_BINARY_DIR}/subproj")
file(WRITE "${base_dir}/CMakeLists.txt" "${cmakelists_contents}")
file(WRITE "${base_dir}/main.cpp" "${main_contents}")
ExternalProject_Add(
subproj
SOURCE_DIR "${base_dir}"
INSTALL_COMMAND ""
)
Configuring with CMake 3.26 / 3.27
$ cmake .. -G"Ninja Multi-Config"
$ ninja
yields the following error during a parallel build:
$ ninja -v
[1/16] cd /proj_build/build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -Dcfgdir=/Debug -P /proj_build/build/subproj-prefix/tmp/subproj-mkdirs.cmake && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/Debug/subproj-mkdir
[2/16] cd /proj_build/build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -Dcfgdir=/RelWithDebInfo -P /proj_build/build/subproj-prefix/tmp/subproj-mkdirs.cmake && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/RelWithDebInfo/subproj-mkdir
[3/16] cd /proj_build/build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E echo_append && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/Debug/subproj-download
[4/16] cd /proj_build/build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E echo_append && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/RelWithDebInfo/subproj-download
[5/16] cd /proj_build/build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E echo_append && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/Debug/subproj-update
[6/16] cd /proj_build/build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E echo_append && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/RelWithDebInfo/subproj-update
[7/16] cd /proj_build/build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E echo_append && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/Debug/subproj-patch
[8/16] cd /proj_build/build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E echo_append && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/RelWithDebInfo/subproj-patch
[9/16] cd /proj_build/build/subproj-prefix/src/subproj-build && /usr/local/Cellar/cmake/3.26.4/bin/cmake "-GNinja Multi-Config" -S /proj_build/build/subproj -B /proj_build/build/subproj-prefix/src/subproj-build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/RelWithDebInfo/subproj-configure
FAILED: subproj-prefix/src/subproj-stamp/RelWithDebInfo/subproj-configure /proj_build/build/subproj-prefix/src/subproj-stamp/RelWithDebInfo/subproj-configure
cd /proj_build/build/subproj-prefix/src/subproj-build && /usr/local/Cellar/cmake/3.26.4/bin/cmake "-GNinja Multi-Config" -S /proj_build/build/subproj -B /proj_build/build/subproj-prefix/src/subproj-build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/RelWithDebInfo/subproj-configure
-- The CXX compiler identification is AppleClang 14.0.3.14030022
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/CMakeTestCXXCompiler.cmake:73 (configure_file):
No such file or directory
Call Stack (most recent call first):
CMakeLists.txt:2 (project)
-- Configuring incomplete, errors occurred!
[10/16] cd /proj_build/build/subproj-prefix/src/subproj-build && /usr/local/Cellar/cmake/3.26.4/bin/cmake "-GNinja Multi-Config" -S /proj_build/build/subproj -B /proj_build/build/subproj-prefix/src/subproj-build && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /proj_build/build/subproj-prefix/src/subproj-stamp/Debug/subproj-configure
-- The CXX compiler identification is AppleClang 14.0.3.14030022
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: /proj_build/build/subproj-prefix/src/subproj-build
ninja: build stopped: subcommand failed.
This happens because ninja tries to configure and build the external project twice, once for each config, in the same build directory, concurrently.
To avoid this, ExternalProject_Add
should likely learn to take a config-specific build directory (likely via a generator expression) for each configuration.
Edited by alcroito