# Setting a default \`CMAKE\_BUILD\_TYPE\` per project

**URL:** https://discourse.cmake.org/t/setting-a-default-cmake-build-type-per-project/10195
**Category:** Development
**Created:** [February 26, 2024, 5:53pm UTC](https://discourse.cmake.org/t/setting-a-default-cmake-build-type-per-project/10195 "2024-02-26T17:53:45Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [February 26, 2024, 5:53pm UTC](https://discourse.cmake.org/t/setting-a-default-cmake-build-type-per-project/10195/1 "2024-02-26T17:53:45Z")

</div>

Splitting this discussion from [this issue comment](https://gitlab.kitware.com/cmake/cmake/-/issues/25715#note_1486615).

Basically I am considering how to allow a project to set its default custom build type without affecting other project’s build type.

### Setup:

- Project A: fetches Project B
- Project A: sets default `CMAKE_BUILD_TYPE` to `CustomReleaseA` as local variable (maybe with an `if`-guard before/after `project`)
- Project B: sets default `CMAKE_BUILD_TYPE` to `CustomReleaseB` as local variable (maybe with and `if`-guard before/after `project`)

### Case1: user does not set `CMAKE_BUILD_TYPE` as `-D` option

- **Expectation** : Project A and B are built against a default that they wish to implement
- **Users** : Default behavior for (end-)users
- `CustomReleaseA` and `CustomReleaseB` are expected to be used, but probably that would not happen because `CMAKE_BUILD_TYPE` is set as a local variable by Project A and propagated to Project B. I don’t think there is a clean way to get such an outcome right now.
- The above behavior could be fixed if within `project` the cache variable is always set to `set(CMAKE_BUILD_TYPE "" CACHE STRING ...)` by `project()`, the local variable is reset to the cache variable, and the projects use:

```cmake
project(...)
if (NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE CustomReleaseA)
endif()

```

### Case2: user provides `CMAKE_BUILD_TYPE` as `-D` option

- **Expectation** : Both project A and B are built against a configuration that they both recognize `RelWithDebInfo/Debug`
- **Users** : Packagers where typically `RelWithDebInfo` is set, or developers who would require `Debug`
- Would always work as intended if the project use an `if`-guard as above

### Why have such a design?

This allows the project to define their own default configuration that builds on top of `Release` which they would want the typical user to use as a default, e.g. adding native build flags, compiler specific fixes or optimizations, etc. But if the packager like spack always uses `Release` as their `CMAKE_BUILD_TYPE`, this will ensure that the packager can overwrite those defaults and use the CMake specific defaults to build on top of.

I think I came up to thinking about this issue when seeing a project (ab)use `CMAKE_<LANG>_FLAGS_<CONFIG>` and appending flags manually to those. For the most cases that project can change to using target-scoped compile flags, but there could be some merit of putting the project’s default flags into `CMAKE_<LANG>_FLAGS_<CustomRelease>` so that they can be overwritten individually for each project.
