# Strictly appending to CMAKE\_\<LANG\>\_FLAGS

**URL:** https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478
**Category:** Usage
**Created:** [September 13, 2022, 9:54pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478 "2022-09-13T21:54:52Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![mrjoel](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mrjoel/32/2770_2.png) [@mrjoel](https://discourse.cmake.org/u/mrjoel)
#### Post date: [September 13, 2022, 9:54pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/1 "2022-09-13T21:54:52Z")

</div>

I haven’t been able to identify any mechanism to specify strictly additional compiler flags from a commandline `cmake` execution. I usually just use `-D CMAKE_CXX_FLAGS=foo` which in practice works in most cases. However, I have recently encountered an issue using Visual Studio generators where doing so results in the exclusion of CMake-internal default definitions, in particular `WIN32`.

This is a follow-up to what was originally [filed as a GitLab issue](https://gitlab.kitware.com/cmake/cmake/-/issues/23956). The message closing the issue mentions that the resulting `CMAKE_CXX_FLAGS` can be “interactively edited after-the-fact in `ccmake` or `cmake-gui`” which while true, doesn’t cover our usage of successive executions of a CI job in a non-interactive environment.

Depending on per-execution external criteria (i.e., not encapsulable in `CMakeLists.txt`) I’m seeking to provide or inhibit compiler flags such as warning-as-error (`/WX`). This seems to be a case of wanting an “append to default flags” option (without requiring knowledge of what the default flags are), but I haven’t been able to locate such a thing.

Explored alternatives:

- `CXXFLAGS` environment variable does yield the desired behavior. This seems to me like inconsistent behavior (possible bug?) for `CMAKE_CXX_FLAGS` and `CXXFLAGS`. As I understand the documentation, the environment variable is used to initialize the CMake variable, so using either should yield the same result.

- `CMAKE_<LANG>_FLAGS_INIT` gives the desired behavior, but since I’m not using it from a toolchain file, I’m reluctant to rely on it. It is also relevant for the first configuration and so is similarly insufficient as the environment variable alternative.

I’d certainly argue that the best solution is to ensure that needed definitions are added within the project `CMakeLists.txt`. Unfortunately, that isn’t reasonable when using with 3rd party libraries. In particular many have a habit of assuming `WIN32` (as opposed to `_WIN32`) since it’s added by default by Visual Studio (and the CMake Visual Studio generators) which leads to sloppy authoring of `CMakeLists.txt`.

---

<div class="post-metadata">

### Author: ![mrjoel](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mrjoel/32/2770_2.png) [@mrjoel](https://discourse.cmake.org/u/mrjoel)
#### Post date: [September 20, 2022, 2:34pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/2 "2022-09-20T14:34:50Z")

</div>

Bump, in particular for feedback on the behavior difference between `CXXFLAGS` and `-D CMAKE_CXX_FLAGS`. Based on my understanding this would appear to be a bug (either functionality and/or documentation).

---

<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: [October 17, 2022, 8:57pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/3 "2022-10-17T20:57:28Z")

</div>

I don’t think there’s a mechanism to give extra flags from the command line here. A new feature might be required. @brad.king?

---

<div class="post-metadata">

### Author: ![mrjoel](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mrjoel/32/2770_2.png) [@mrjoel](https://discourse.cmake.org/u/mrjoel)
#### Post date: [October 17, 2022, 9:17pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/4 "2022-10-17T21:17:44Z")

</div>

I’d argue against a general-purpose feature addition here, but since `WIN32` has special handling, perhaps a targeted special case for just that entry? It’s a slippery slope though going down that path.

As I originally caveated, “I’d certainly argue that the best solution is to ensure that needed definitions are added within the project `CMakeLists.txt`.” For the particular project which drove and surfaced this issue we’ve since done this more proper thing of using `target_compile_definitions()` for focused setting of the variable. I’d suggest two separate potential tasks here:

- Use consistent behavior between specifying `CXXFLAGS` via environment variable vs. `-D CMAKE_CXX_FLAGS` for a clean build area. The fact that the environment variable path gave the desired (but arguably incorrect) behavior was misleading.

- Consider maybe, possibly, , providing special cases handling for `WIN32` in this situation as well? I only raise this as being possibly beneficial since it’s already a special case, so being consistent and pervasive with that special case would be nice.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [October 17, 2022, 9:56pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/5 "2022-10-17T21:56:08Z")

</div>

As I explained in the linked [CMake Issue 23956](https://gitlab.kitware.com/cmake/cmake/-/issues/23956#note_1244270), the difference between `CMAKE_CXX_FLAGS` and `CXXFLAGS` is intentional. The flags are stored in the `CMAKE_CXX_FLAGS` cache entry, and the default value for that is taken from a combination of builtin flags and the `CXXFLAGS` environment variable. By specifying `-DCMAKE_CXX_FLAGS=...` one says “use my flags instead of the defaults”.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [October 17, 2022, 10:17pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/6 "2022-10-17T22:17:30Z")

</div>

`CXXFLAGS` is the official way to say “use default flags plus these”.

> our particular CI jobs in some cases use incremental build areas, which makes the environment variable approach insufficient (since it’s only used during the first configuration).

Please explain that use case in more detail. Are you trying to append to the current `CMAKE_CXX_FLAGS` value in an existing `CMakeCache.txt`, reconfigure, and build again?

---

<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: [October 18, 2022, 12:28am UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/7 "2022-10-18T00:28:48Z")

</div>

> [@mrjoel](#):
>
> I’d argue against a general-purpose feature addition here, but since `WIN32` has special handling, perhaps a targeted special case for just that entry?

Note that anything depending on the `WIN32` symbol can just use the actually-provided-by-Windows `_WIN32` spelling. The `WIN32` spelling was added in the _old_ days of CMake and hasn’t been able to be removed because of compatibility concerns. I’d love a policy to remove it though 🙂 .

---

<div class="post-metadata">

### Author: ![mrjoel](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mrjoel/32/2770_2.png) [@mrjoel](https://discourse.cmake.org/u/mrjoel)
#### Post date: [October 18, 2022, 2:16pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/8 "2022-10-18T14:16:16Z")

</div>

> [@brad.king](#):
>
> > our particular CI jobs in some cases use incremental build areas, which makes the environment variable approach insufficient (since it’s only used during the first configuration).
> 
> Please explain that use case in more detail. Are you trying to append to the current `CMAKE_CXX_FLAGS` value in an existing `CMakeCache.txt`, reconfigure, and build again?

Precisely - we have jobs in CI (Jenkins in this particular case, but also GitLab CI) for quick-turn checks of multiple branches which use `ccache`, incremental builds, and provide user-facing options/parameters which internally result in changing effective C++ compiler options (e.g. warning-as-error, optimization level, etc.). A single job builds with all of MSVC, gcc, and clang, so we convert the single job parameter into the compiler-specific options. There is obviously a separate build area for each compiler, but multiple build areas are driven by a single job with distinct parallel stages.

We want to be able to switch branches and compilation options, then on a subsequent incremental build minimize needed rebuilds as well as use applicable results from `ccache`’s cache (typically only branch churn in subsets of the overall codebase). This works fine now that we’ve added the tailored application of `WIN32` on targets where needed. However due to the `WIN32` default vs. non-default special casing it seemed excessively complicated or at least non-intuitive. In particular, using `CXXFLAGS` was insufficient since it is only considered on initial build area creation, and not subsequent reexecutions of `cmake` with different options for our incremental builds.

> [@brad.king](#):
>
> `CXXFLAGS` is the official way to say “use default flags plus these”.
> 
> As I explained in the linked [CMake Issue 23956](https://gitlab.kitware.com/cmake/cmake/-/issues/23956#note_1244270), the difference between `CMAKE_CXX_FLAGS` and `CXXFLAGS` is intentional.

Fair point, and I’d even mentioned (somewhere?) that it may be a documentation clarification. The usage of `CMAKE_CXX_FLAGS` overriding the env var is completely sensical.

> [@brad.king](#):
>
> the default value for [`CMAKE_CXX_FLAGS`] is taken from a combination of builtin flags and the `CXXFLAGS` environment variable.

This is the crux of what I didn’t find clear in the documentation and may perhaps be worth a tweak. [The docs](https://cmake.org/cmake/help/latest/envvar/CXXFLAGS.html) simply indicate that `CXXFLAGS` is used “to determine `CXX` default compilation flags, after which the value for `CXXFLAGS` is stored in the cache as `CMAKE_CXX_FLAGS`”. To my reading:

- there isn’t a clear distinction that the behavior is different. The implications behind “to determine `CXX` flags” are at best subtle. I read “to determine” (now knowing incorrectly) as “determines” or “specifies”, rather than “merged with/appended to possibly other internal flags” indicating it’s only part of the resultant whole.
- This is further emphasized and seemingly reinforced by “the value for `CXXFLAGS` is stored in the cache as `CMAKE_CXX_FLAGS`” rather then something like “the resultant determined value (including `CXXFLAGS`) is store in the cache…”
- The combination of the above points seemed to falsely reinforce my understanding that the usage of `CXXFLAGS` and `CMAKE_CXX_FLAGS` were equivalent, with the former only serving as an alternate environment-based mechanism to seed the latter.

Hopefully this helps clarify and make sense of my perspective when working through it. If it’d be useful I’d be happy to draft a doc patch.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [October 18, 2022, 5:31pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/9 "2022-10-18T17:31:54Z")

</div>

I opened [CMake MR 7804](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7804) to clarify the documentation.

You should be able to achieve your use case with:

```nohighlight
$ env CXXFLAGS='-new -flags' cmake -U CMAKE_CXX_FLAGS ...

```

The `-U CMAKE_CXX_FLAGS` flag will undefine the cache entry so that it will be re-initialized using the new `CXXFLAGS` environment variable value in combination with the builtin defaults.

---

<div class="post-metadata">

### Author: ![mrjoel](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mrjoel/32/2770_2.png) [@mrjoel](https://discourse.cmake.org/u/mrjoel)
#### Post date: [October 18, 2022, 6:11pm UTC](https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478/10 "2022-10-18T18:11:29Z")

</div>

> [@brad.king](#):
>
> I opened [CMake MR 7804](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7804) to clarify the documentation.

Looks great, thanks!

> [@brad.king](#):
>
> You should be able to achieve your use case with:
> 
> ```auto
> $ env CXXFLAGS='-new -flags' cmake -U CMAKE_CXX_FLAGS ...
> 
> ```
> 
> The `-U CMAKE_CXX_FLAGS` flag will undefine the cache entry so that it will be re-initialized using the new `CXXFLAGS` environment variable value in combination with the builtin defaults.

Yep, indeed I had that used internally for a brief bit but it felt like cheating or subverting the intended system. The doc updates I think will help clarify and endorse that as valid to others in the future, thanks!
