# cmake 3.18: generator expressions with add\_subdirectory ?

**URL:** <https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801>\
**Category:** Code\
**Created:** [September 9, 2020, 1:53pm UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801 "2020-09-09T13:53:54Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 9, 2020, 1:53pm UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/1 "2020-09-09T13:53:54Z")

</div>

How could I define a binary\_dir dependent on generator expression.

The goal is to have a different build directory (_binary\_dir_) dependent on a configuration, when I call _add\_subdirectory_.

Currently with cmake v3.18 I have the following:

```
set(BINARY_PATH $<$<CONFIG:Debug>:${PATH_BASE}Debug>$<$<CONFIG:Release>:${PATH_BASE}Release>)

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../module/ ${BINARY_PATH})

```

and the _add\_subdirectory_ fails while generating with

> Generator expressions in custom command outputs are not implemented

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [September 9, 2020, 2:31pm UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/2 "2020-09-09T14:31:17Z")

</div>

What you’re asking for doesn’t really make sense. In a single-configuration generator, you can just use `CMAKE_BUILD_TYPE` to make decisions at configure time. In a multi-configuration generator, multiple configurations are managed by the same buildsystem (e.g. by one `.vcxproj` file in the binary directory), so having different binary directories for different configurations is impossible.

Are you perhaps looking for something like [`CMAKE_CFG_INTDIR`](https://cmake.org/cmake/help/latest/variable/CMAKE_CFG_INTDIR.html), which allows you to have per-configuration paths at build time with multi-config generators?

---

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 10, 2020, 6:34am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/3 "2020-09-10T06:34:37Z")

</div>

Wise words “doesnt really make sense” 🙂 but thanks, I needed really advises. As far as I understand from the link you gave, CMAKE\_CFG\_INTDIR expands to the ${OutDir} but I want to set it up manually. (Besides the help tells about problems with Ninja-Multiconfiguration and that is actually depreciated and add\_custom\_command should be used instead). So, it seems, this won’t help.

I want to be able with a multi-configuration generator to set up the build folder like  
build/Release\_x64, Release\_x86 etc.  
or  
build/Debug\_x64, Debug \_x64 etc.

I tried with add\_subdirectory and generator expressions (see the initial post) but cmake complains about this combination. (Which imho is a bug, and not a feature).

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [September 10, 2020, 8:23am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/4 "2020-09-10T08:23:27Z")

</div>

When you want certain setup for a multi-configuration project, you should always cross-check it by asking “how would this work with a multi-configuration generator like VS?” That will show you that having a per-configuration binary directory is impossible, because the binary directory is where the project file (`.vcxproj`) is stored. You cannot have one file in multiple directories.

Can you explain why you want such per-configuration directories? Perhaps it’s a bit of an X-Y problem and your goal could be better achieved by modifying `CMAKE_RUNTIME_OUTPUT_DIRECTORY` and similar?

---

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 10, 2020, 9:06am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/5 "2020-09-10T09:06:02Z")

</div>

I would really like to get an answer to the question, why `add_subdirectory` **doesn’t work with** `generator expressions` ?

In VS it is also possible to specify different `OutputDirectory` per Configuration, e.g.  
`$(ProjectDir)\windows_$(Platform)_$(Configuration)_$(PlatformToolset)\`

Why is it not possible to set it up with `cmake` like this? How could I achieve this with `cmake`?

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [September 10, 2020, 9:12am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/6 "2020-09-10T09:12:30Z")

</div>

You _can_ specify a different output directory for each configuration, even with generator expressions (see e.g. [`RUNTIME_OUTPUT_DIRECTORY`](https://cmake.org/cmake/help/latest/prop_tgt/RUNTIME_OUTPUT_DIRECTORY.html) property):

```
add_executable(foo ${sources})
set_property(
  TARGET foo 
  PROPERTY RUNTIME_OUTPUT_DIRECTORY
  windows_$<PLATFORM_ID>_$<CONFIG>
)

```

What you cannot do is specify a different _binary directory_ for each configuration, because the binary directory is the place where the _buildsystem files_ (e.g. project files, makefiles) go, and these are not necessarily per-configuration. The binary directory is _also_ the default output directory, but that can be changed.

---

<div class="post-metadata">

**Author:** ![fdk17](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/f/ea666f/32.png) [@fdk17](https://discourse.cmake.org/u/fdk17)\
**Post date:** [September 10, 2020, 12:57pm UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/7 "2020-09-10T12:57:15Z")

</div>

Many of the items that go into the `binary directory` specified in `add_subdirectory`, like .vcxproj or Makefiles and other build system files, are created when the project is generated. CMake isn’t going to make duplicate vcxproj for each of the proposed binary directories. That would like be having two top level binary directories and two solution files.

There are plenty of ways to control where the final build outputs goes per configuration. The concept doesn’t readily apply to where the build system files or intermediate objects go. You don’t get to decide total control of the entire build folder.

---

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 10, 2020, 1:43pm UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/8 "2020-09-10T13:43:35Z")

</div>

This would suffice, however after generating and opening the VS, the OutputDirectory is unaffected. It shows the predifined OutputDirectory, and I cannot find any place where the set property is considered when generating. So what is missing?

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [September 10, 2020, 2:19pm UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/9 "2020-09-10T14:19:12Z")

</div>

Strange, I’ve just tested that it works for me with this minimal example:

```
cmake_minimum_required(VERSION 3.14)
project(Test)

add_executable(foo main.cpp)
set_property(TARGET foo PROPERTY RUNTIME_OUTPUT_DIRECTORY win_$<PLATFORM_ID>_$<CONFIG>)

```

Can you post the relevant part of your CMakeList to see if everything’s ok there?

---

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 11, 2020, 4:32am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/10 "2020-09-11T04:32:40Z")

</div>

I tested it with your example in my project. It wont change the Output Directory either

 ![Windows_OutputDir_Unchanged](https://discourse.cmake.org/uploads/default/original/1X/19f4837d10e63f5e3a296103b3cf57772737b651.png)

Here my modified cmake extracts, I always see in visual studio the unwanted/predefined Output Directory

```
cmake_minimum_required (VERSION 3.14)

project(myTarget C CXX)
add_library(myTarget ${SRCS} ${HDRS})

include(cmakeSetUpSomeVars.cmake)

# variant 1
set_property(TARGET myTarget PROPERTY RUNTIME_OUTPUT_DIRECTORY win_$<PLATFORM_ID>_$<CONFIG>)
# 1.2
#set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/win_$<PLATFORM_ID>_$<CONFIG> )

# variant 2
set_property(TARGET myTarget PROPERTY LIBRARY_OUTPUT_DIRECTORY win_$<PLATFORM_ID>_$<CONFIG>)
#2.2 
# set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/win_$<PLATFORM_ID>_$<CONFIG> )
```

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [September 11, 2020, 7:22am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/11 "2020-09-11T07:22:30Z")

</div>

The correct property for specifying output location depends on the type of target. For executables, it’s `RUNTIME_OUTPUT_DIRECTORY`. For static libraries, it’s `ARCHIVE_OUTPUT_DIRECTORY`. For shared libraries on DLL platforms (Windows), it’s `RUNTIME_OUTPUT_DIRECTORY` for the `.dll` and `ARCHIVE_OUTPUT_DIRECTORY` for the import `.lib`. For shared libraries on non-DLL platforms (Linux), it’s `LIBRARY_OUTPUT_DIRECTORY`. See the discussion of Output artifacts for details: [https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#output-artifacts](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#output-artifacts) . (Note that this is also linked from the documentation of `RUNTIME_OUTPUT_DIRECTORY` to which I pointed you earlier).

Regarding the variables `CMAKE_[XYZ]_OUTPUT_DIRECTORY`, these follow the standard CMake approach of initialising the corresponding target property at the moment the target is created. So if you want to use these (i.e. `CMAKE_ARCHIVE_OUTPUT_DIRECTORY` in your case), it must be set _before_ the `add_library()` command.

---

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 11, 2020, 8:31am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/12 "2020-09-11T08:31:14Z")

</div>

I see. I hadnt dived into details of the output variants… Thanks about it.

What is the way to change the VS Intermediate Directory in the same way? Otherwise it would be not a complete solution.

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [September 11, 2020, 8:56am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/13 "2020-09-11T08:56:42Z")

</div>

> [@ProTur1](#):
>
> What is the way to change the VS Intermediate Directory in the same way?

AFAIK, there is none. Location of object files is an implementation detail of CMake, something you should never need to be concerned about. CMake will make sure everything works as it should, and we don’t really need to know or care how. CMake reserves this to be free to evolve object file layout and handling across versions.

---

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 11, 2020, 9:24am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/14 "2020-09-11T09:24:04Z")

</div>

The problem with VS Intermediate Directory is, that when you clean one project which has the same intermediate directory with another project, you force rebuild of the other project.

In VS there is a possibility to change the Intermediate Directory (see above screenshot), why is not possible with cmake (it is just one json entry in the vs project configuration)?

My workflow is: cmake config & generate and VS build. Do you know of a better/another one?

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [September 11, 2020, 9:49am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/15 "2020-09-11T09:49:49Z")

</div>

How did you get CMake to generate two projects with the same Intermediate directory? Normally CMake generates `.vcxproj` files such that each project has its own (effectively `TargetName.dir`).

---

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 11, 2020, 10:23am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/16 "2020-09-11T10:23:26Z")

</div>

This would be the case when you choose a different architecture type (_x64/x86_) for the same project differently configured.

Btw, why (with deleted cache) when set with the `cmake-gui` (the 2nd line of the gui - Optional platform for generator), the variable `CMAKE_GENERATOR_PLATFORM` is not affected, or at least cmake doesnt know it at configuration start? Or do I check for a wrong variable again?

---

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 14, 2020, 3:19pm UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/17 "2020-09-14T15:19:56Z")

</div>

1. Do you know, when setting of the `CMAKE_ARCHIVE_OUTPUT_DIRECTORY` has no effect, is it an IDE (in this case Qt Creator) issue, or this property works only for VS ?

2. If I want to build the above static lib, triggered by a module which uses it, how is this done in a clean way? My consideration is:  
In the static lib, I have `set_property(TARGET myLib PROPERTY ARCHIVE_OUTPUT_DIRECTORY ${MYLIB_OUTPUT_PATH})`  
and in the module, depending on this static, I have to include  
`add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../mylib binary_dir)`  
But I was hoping, that specifying the `ARCHIVE_OUTPUT_DIRECTORY`, would release the requirement of specifying the `binary_dir.`  
For me two contradictory points.

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [September 15, 2020, 8:22am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/18 "2020-09-15T08:22:07Z")

</div>

> [@ProTur1](#):
>
> Do you know, when setting of the `CMAKE_ARCHIVE_OUTPUT_DIRECTORY` has no effect, is it an IDE (in this case Qt Creator) issue, or this property works only for VS ?

It’s supposed to work for all generators. If it doesn’t work for you, it’s either a Qt Creator issue, or you’re using it incorrectly (such as only setting it after the static library target has already been created).

> [@ProTur1](#):
>
> If I want to build the above static lib, triggered by a module which uses it, how is this done in a clean way? My consideration is:  
> In the static lib, I have `set_property(TARGET myLib PROPERTY ARCHIVE_OUTPUT_DIRECTORY ${MYLIB_OUTPUT_PATH})`  
> and in the module, depending on this static, I have to include  
> `add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../mylib binary_dir)`  
> But I was hoping, that specifying the `ARCHIVE_OUTPUT_DIRECTORY` , would release the requirement of specifying the `binary_dir.`  
> For me two contradictory points.

Please try to understand this: the `binary_dir` is where the **buildsystem files** (Makefiles, `.vcxproj` files etc.) go; it is also used by CMake to store the intermediate build artifacts (`.o`, `.obj`). Finally, it’s also the default location where final build artifacts (`.lib`, `.dll`, `.a`, `.exe`, `.so` etc.) go, but that location can be changed.

Therefore, setting the `*_OUTPUT_DIRECTORY` properties and/or variables cannot possibly remove the need for specifying the location of buildsystem files (= the binary directory), since it doesn’t affect them at all.

Note that you only need to specify the binary directory explicitly if you’re using an absolute path as the source directory argument. Quoting [`add_subdirectory()` docs](https://cmake.org/cmake/help/latest/command/add_subdirectory.html):

> If `binary_dir` is not specified, the value of `source_dir`, before expanding any relative path, will be used (the typical usage).

So in your case, you could just do this:

```
add_subdirectory(../mylib)

```

and the binary directory for `mylib` would evaluate to `${CMAKE_CURRENT_BINARY_DIR}/../mylib`, i.e. the hierarchy of binary directories will mirror your source directory hierarchy.

* * *

Perhaps you should think of these as two separate issues: one is the organisation of the buildsystem files, and one is the organisation of final build artifacts (executables, libraries).

If you really care about the former, you can control it by specifying binary directory arguments to `add_subdirectory()` calls, but you may find you don’t actually need control of that at all.

For the latter (build artifact locations), you can use the `*_OUTPUT_DIRECTORY` variables/properties, and if you want total manual control, you can root these in `CMAKE_BINARY_DIRECTORY` (the binary dir of the top-level project) instead of in `CMAKE_CURRENT_BINARY_DIRECTORY`. That way, you can lay out the binary artifacts however you like, regardless of the binary directory hierarchy.

---

<div class="post-metadata">

**Author:** ![ProTur1](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/34f0e0/32.png) [@ProTur1](https://discourse.cmake.org/u/ProTur1)\
**Post date:** [September 17, 2020, 10:09am UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/19 "2020-09-17T10:09:25Z")

</div>

10x a lot. Just some final remarks:

> [@Angew](#):
>
> `add_subdirectory(../mylib)`

This alone didnt work. Setting the binary explicitly was required.

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [September 17, 2020, 12:05pm UTC](https://discourse.cmake.org/t/cmake-3-18-generator-expressions-with-add-subdirectory/1801/20 "2020-09-17T12:05:11Z")

</div>

> [@ProTur1](#):
>
> > [@Angew](#):
> >
> > `add_subdirectory(../mylib)`
> 
> This alone didnt work. Setting the binary explicitly was required.

OK; I was writing from memory and docs, didn’t test it. Perhaps it doesn’t like the fact that the path goes outside the current directory subtree, so it doesn’t want to mess up directories outside the normally corresponding binary tree without explicit instruction.
