# Building multiple configurations of a project at the same time with Ninja

**URL:** https://discourse.cmake.org/t/building-multiple-configurations-of-a-project-at-the-same-time-with-ninja/10709
**Category:** Development
**Tags:** gen:ninja
**Created:** [April 21, 2024, 7:04pm UTC](https://discourse.cmake.org/t/building-multiple-configurations-of-a-project-at-the-same-time-with-ninja/10709 "2024-04-21T19:04:22Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![Tachyon](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tachyon/32/4520_2.png) [@Tachyon](https://discourse.cmake.org/u/Tachyon)
#### Post date: [April 21, 2024, 7:04pm UTC](https://discourse.cmake.org/t/building-multiple-configurations-of-a-project-at-the-same-time-with-ninja/10709/1 "2024-04-21T19:04:22Z")

</div>

## Introduction

I’ve been interested for a while on how to optimize builds, and one thing that I thought about is to have a central ninja `build.ninja` that can drive the build for everything. It seems like the topic has been discussed before, both on the Ninja’s GitHub Issues page and on the maillist here, and the conclusion was that it’s not possible.

However, I still wanted to try it. This is the top ninja file that I was playing it:

```ninja
subninja release_32/build.ninja
subninja release_64/build.ninja

build all: phony release_32/all release_64/all

default all

```

## The problems

The first big problem I faced was that the files are relative to the top ninja file. This was solved by setting `CMAKE_NINJA_OUTPUT_PATH_PREFIX`. The next problem problem was that I had duplicated rule names (like `cmake_object_order_depends_target_libninja-re2c`).

At this point I tried different combinations of regex and simple replace scripts to try and patch the ninja files, but I couldn’t get anything working. So as any person with too much enthusiasm would do, I figured it’s time to make a project that could parse and edit in place ninja files.

[Here](https://github.com/xTachyon/ninja_editor) it is for anyone interested (disclaimer: very early and untested, made the minimum necessary work to get something working). In the end, I managed to make something that looks like it works, but I wouldn’t trust it to use it on a real build.

What I’m hoping is that CMake could be changed so it would generate files that would solve (some of) the following problems that I found:

### 1. Duplicated rules names

Like I’ve mentioned before, CMake generated rules named like `cmake_..`. What I did is to add a prefix to each rule, much more like `CMAKE_NINJA_OUTPUT_PATH_PREFIX`. I think this could be solved pretty easily with something like `CMAKE_NINJA_OUTPUT_RULE_PREFIX` with the same logic.

### 2. Rule that builds CMakeLists.txt

Right now there’s a rule that looks like this

```cmake
build /home/tachyon/repos/ninja/build-cmake/src_32/CMakeLists.txt /usr/share/cmake-3.27/Modules/BasicConfigVersion-AnyNewerVersion.cmake.in ..... : phony

```

This is a problem because more than one configuration will try to “generate” those files. To be honest I don’t understand why this exists in the first place, but it’s probably important.

One thing I did to “solve” a part of the problem is to make symlinks of the source directory (`ln -s $PWD/.. src_32`) and pass it to CMake (`-S src_32`) for each configuration, but I can’t tell if this is actually an okay thing to do. This still didn’t solve it building files in `/usr/share/cmake..`, so I just mangled the path to those with a prefix that “soft” broke it.

### 3. Files that are generated in source

This will result in multiple rules generating the same files, which is fair enough. I have no solution for this other than not doing that. While not ideal, I could absolutely live with this in my projects. Generating the file in the build directory sounds already like a good idea for me.

## Conclusion

The final questions would be:

1. Do you see better solutions for these problems?
2. Do you see any other problem that might arise?
3. Could CMake implement changes that would make this easier and less error prone?

Edit: I used “rule” when I actually meant edge.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 27, 2024, 3:44pm UTC](https://discourse.cmake.org/t/building-multiple-configurations-of-a-project-at-the-same-time-with-ninja/10709/2 "2024-04-27T15:44:30Z")

</div>

Have you looked at the [Ninja Multi-Config generator](https://cmake.org/cmake/help/latest/generator/Ninja%20Multi-Config.html)?

---

<div class="post-metadata">

### Author: ![Tachyon](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tachyon/32/4520_2.png) [@Tachyon](https://discourse.cmake.org/u/Tachyon)
#### Post date: [April 27, 2024, 3:47pm UTC](https://discourse.cmake.org/t/building-multiple-configurations-of-a-project-at-the-same-time-with-ninja/10709/3 "2024-04-27T15:47:31Z")

</div>

I have, but as far as I can tell, it can only do different build types. I’m also interested in building different architectures (i686, amd64, arm64, etc.) with different toolchain files and so on at the same time.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 27, 2024, 3:56pm UTC](https://discourse.cmake.org/t/building-multiple-configurations-of-a-project-at-the-same-time-with-ninja/10709/4 "2024-04-27T15:56:57Z")

</div>

You’ll need separate build trees for that kind of thing. I would suggest something like a “superbuild” that uses `ExternalProject` to build each configuration you want.

---

<div class="post-metadata">

### Author: ![Tachyon](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tachyon/32/4520_2.png) [@Tachyon](https://discourse.cmake.org/u/Tachyon)
#### Post date: [April 27, 2024, 4:44pm UTC](https://discourse.cmake.org/t/building-multiple-configurations-of-a-project-at-the-same-time-with-ninja/10709/5 "2024-04-27T16:44:29Z")

</div>

Is there information somewhere on how to setup such a superbuild? Or I should try to figure it out from the docs.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 27, 2024, 9:40pm UTC](https://discourse.cmake.org/t/building-multiple-configurations-of-a-project-at-the-same-time-with-ninja/10709/6 "2024-04-27T21:40:01Z")

</div>

You might try to extract it from the (slightly abstract) [`common-superbuild`](https://gitlab.kitware.com/paraview/common-superbuild/).

The core of it is:

- use `ExternalProject` for _all_ builds within the project
- use `DEPENDS` to make sure things build in the right order
- use install trees rather than build trees of dependencies

Of course, one may stretch things a _bit_ for each line, but I’d recommend not straying too far off the path until it is understood why each rule might be bent (it’s “gut feeling” for me; I don’t think I can explain it).
