# How is ExternalProject\_Add's BINARY\_DIR meant to be set with CMAKE\_CROSS\_CONFIGS + CMAKE\_DEFAULT\_CONFIGS == all

**URL:** https://discourse.cmake.org/t/how-is-externalproject-adds-binary-dir-meant-to-be-set-with-cmake-cross-configs-cmake-default-configs-all/8648
**Category:** Usage
**Tags:** gen:ninja
**Created:** [July 31, 2023, 4:16pm UTC](https://discourse.cmake.org/t/how-is-externalproject-adds-binary-dir-meant-to-be-set-with-cmake-cross-configs-cmake-default-configs-all/8648 "2023-07-31T16:16:02Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![alcroito](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alcroito/32/186_2.png) [@alcroito](https://discourse.cmake.org/u/alcroito)
#### Post date: [July 31, 2023, 4:16pm UTC](https://discourse.cmake.org/t/how-is-externalproject-adds-binary-dir-meant-to-be-set-with-cmake-cross-configs-cmake-default-configs-all/8648/1 "2023-07-31T16:16:02Z")

</div>

Consider the following short project:

```cmake
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Debug")
set(CMAKE_DEFAULT_BUILD_TYPE "RelWithDebInfo")
set(CMAKE_DEFAULT_CONFIGS "all")
set(CMAKE_CROSS_CONFIGS "all")

project(ExternalProjectExample NONE)
include(ExternalProject)

# Assignment of config specific binary dir that causes build failure
set(ep_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/mysub")

ExternalProject_Add(
  mysub
  #BINARY_DIR "${ep_binary_dir}"
  SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mysub
  INSTALL_COMMAND ""
)
ExternalProject_Get_Property(mysub BINARY_DIR)
message(">> BINARY_DIR ${BINARY_DIR}")

# Workaround
#set_property(
    #TARGET "mysub"
    #PROPERTY EXCLUDE_FROM_ALL "$<NOT:$<CONFIG:RelWithDebInfo>>")

```

So it’s a multi-config cross-config project building one EP. Running ninja will configure and build the EP in both configurations, `RelWithDebInfo` and `Debug`.

The external project it configures

```auto
# $ cat mysub/CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(mysub LANGUAGES CXX)
add_executable(app main.cpp)

```

```auto
// $ cat main.cpp
int main() {return 0;}

```

If you run `ninja` after configuring with `cmake .. -G"Ninja Multi-Config"`  
then CMake will configure the external project twice in the exact same build directory, overriding `CMakeCache.txt` and other files.

```auto
...
cd /Volumes/T3/Dev/projects/cmake/general/external_project_multi_config/build/special/RelWithDebInfo && /usr/local/Cellar/cmake/3.26.4/bin/cmake "-GNinja Multi-Config" -S /Volumes/T3/Dev/projects/cmake/general/external_project_multi_config/mysub -B /Volumes/T3/Dev/projects/cmake/general/external_project_multi_config/build/special/RelWithDebInfo && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /Volumes/T3/Dev/projects/cmake/general/external_project_multi_config/build/mysub-prefix/src/mysub-stamp/RelWithDebInfo/mysub-configure
...
cd /Volumes/T3/Dev/projects/cmake/general/external_project_multi_config/build/special/Debug && /usr/local/Cellar/cmake/3.26.4/bin/cmake "-GNinja Multi-Config" -S /Volumes/T3/Dev/projects/cmake/general/external_project_multi_config/mysub -B /Volumes/T3/Dev/projects/cmake/general/external_project_multi_config/build/special/Debug && /usr/local/Cellar/cmake/3.26.4/bin/cmake -E touch /Volumes/T3/Dev/projects/cmake/general/external_project_multi_config/build/mysub-prefix/src/mysub-stamp/Debug/mysub-configure

```

This is because `BINARY_DIR` does not contain any config-specific subdirectory, despite other metadata files (timestamp files) being config-specific.  
This happens starting with CMake 3.24.0 up to 3.27.1.

If I change the `BINARY_DIR` to contain a `$<CONFIG>` subdirectory, then at build time ninja fails with

```auto
/bin/sh: line 0: cd: external_project_multi_config/build/RelWithDebInfo/mysub: No such file or directory

```

I can work around the issue of the overridden `CMakeCache.txt` by explicitly excluding the Debug configuration from `ALL`, but that is not entirely safe, because one could still run `ninja mysub:Debug` explicitly and override the files.

I can also manually pre-create the subdirectories with something like:

```cmake
set(ep_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/mysub/$<CONFIG>")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mysub/RelWithDebInfo")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mysub/Debug")

```

And the build appears to work, but i also end up with an actuall directory called `\$\<CONFIG\>` on the file system.

So what’s the intended way to assign unique `BINARY_DIR`s for each config in such a case? Is it just not possible with the current release CMake versions?

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [July 31, 2023, 10:26pm UTC](https://discourse.cmake.org/t/how-is-externalproject-adds-binary-dir-meant-to-be-set-with-cmake-cross-configs-cmake-default-configs-all/8648/2 "2023-07-31T22:26:22Z")

</div>

For multi-config generators, I’ve always just assumed there is still only a single configure step, and that there is a single `<BINARY_DIR>`. The build step is the part that would pass through the chosen build configuration, and the config-specific build artifacts would be in some config-specific location under the common `<BINARY_DIR>` (or have different config-specific names). I don’t think there’s separate time stamps for each config for the configure step, but I’m going from memory and haven’t checked what the code actually does. I don’t know if there’s config-specific time stamps for the build step, but it’s hard to imagine how it could work if it didn’t.

Your observation that CMake configures the external project twice is surprising (to me, at least). There may be something about the way the Ninja Multi-Config generator handles things that I’m not considering here. @kyle.edwards might have some thoughts on that.

> [@alcroito](#):
>
> So what’s the intended way to assign unique `BINARY_DIR`s for each config in such a case? Is it just not possible with the current release CMake versions?

My thinking is that this is not a supported use case. But again, I’m just going from memory here.

---

<div class="post-metadata">

### Author: ![alcroito](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alcroito/32/186_2.png) [@alcroito](https://discourse.cmake.org/u/alcroito)
#### Post date: [August 4, 2023, 2:05pm UTC](https://discourse.cmake.org/t/how-is-externalproject-adds-binary-dir-meant-to-be-set-with-cmake-cross-configs-cmake-default-configs-all/8648/3 "2023-08-04T14:05:04Z")

</div>

Filed [https://gitlab.kitware.com/cmake/cmake/-/issues/25160](https://gitlab.kitware.com/cmake/cmake/-/issues/25160)
