# Inquiring C++ standard from build target for analyzer config - possible regression, bug or missing documentation?

**URL:** https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584
**Category:** Usage
**Created:** [March 2, 2023, 7:12am UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584 "2023-03-02T07:12:15Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![benedikt](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/51bf81/32.png) [@benedikt](https://discourse.cmake.org/u/benedikt)
#### Post date: [March 2, 2023, 7:12am UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584/1 "2023-03-02T07:12:15Z")

</div>

## Context

We have some convenience functions to configure the code analyzers (cppcheck and clang-tidy) via the builtin cmake mechanisms (Properties CXX\_CLANG\_TIDY and CXX\_CPPCHECK). As we use this in multiple projects and with multiple compilers and operating systems these functions get a cmake target and a “level” and should the automatically configure the analyzers. For the respective tool command line we need to specify the C+±Standard (e.g. --std=c++17) as we use different Standards in different projects. For that we use `get_target_property()` on the target, whicht got its c++ standard via `target_compile_fatures()`

## Problem

This used to work flawlessly with ubuntu 20.04 (cmake 3.16), but after upgrading to Ubuntu 22.04 (cmake 3.22) that mechanism is broken. `target_compile_features()` does not seem to set the property `CXX_STANDARD` any more.

## Questions

- Is this a bug or a regression?
- If not, this intended behaviour - so what’s the rationale behind that? Should it be documented somewhere?

## Minimal example to reproduce

CMakeLists.txt:

```auto
cmake_minimum_required(VERSION 3.16)

project(minimal_example
        LANGUAGES CXX)

add_executable(minexample)

set(CMAKE_MAKE_PROGRAM ninja)

target_compile_features(minexample
    PRIVATE
        cxx_std_17
)

get_target_property(TGT_CXX_STANDARD minexample CXX_STANDARD)

message(STATUS "Got CXX_STANDARD=${TGT_CXX_STANDARD}")

```

Output on Ubuntu 20.04:

```auto
[proc] Executing command: /usr/bin/cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++ -S/workspaces/miDAS -B/workspaces/miDAS/build -G Ninja
[cmake] Not searching for unused variables given on the command line.
[cmake] -- The CXX compiler identification is GNU 9.4.0
[cmake] -- Check for working CXX compiler: /usr/bin/g++
[cmake] -- Check for working CXX compiler: /usr/bin/g++ -- works
[cmake] -- Detecting CXX compiler ABI info
[cmake] -- Detecting CXX compiler ABI info - done
[cmake] -- Detecting CXX compile features
[cmake] -- Detecting CXX compile features - done
[cmake] -- Got CXX_STANDARD=17
[cmake] -- Configuring done

```

Output on Ubuntu 22.04:

```auto
[proc] Executing command: /usr/bin/cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++ -S/workspaces/miDAS -B/workspaces/miDAS/build -G Ninja
[cmake] Not searching for unused variables given on the command line.
[cmake] -- The CXX compiler identification is GNU 11.3.0
[cmake] -- Detecting CXX compiler ABI info
[cmake] -- Detecting CXX compiler ABI info - done
[cmake] -- Check for working CXX compiler: /usr/bin/g++ - skipped
[cmake] -- Detecting CXX compile features
[cmake] -- Detecting CXX compile features - done
[cmake] -- Got CXX_STANDARD=TGT_CXX_STANDARD-NOTFOUND
[cmake] -- Configuring done

```

---

<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: [March 2, 2023, 9:03pm UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584/2 "2023-03-02T21:03:38Z")

</div>

This may have appeared to do what you want in the past, but it isn’t robust. There are a number of things that can affect the language standard that ultimately gets used in the compiler command for a target:

- The target’s own compile feature settings.
- Transitive compile features of targets it links to.
- The target’s own `<LANG>_STANDARD` property (`<LANG>_STANDARD_REQUIRED` is also relevant).

CMake looks at all of those and works out the highest language standard required across the whole set. It then ensures that the language standard used during compilation is _at least_ that. There’s nothing to guarantee that CMake won’t select something _higher_ than any of those. The reason for this relates to some toolchains not offering older language standards, or having a higher standard with its default settings. There was some work related to this across the CMake versions you’ve mentioned which made things more rigorous and more accurate, but I don’t know the exact details. @tambre should be able to provide more details if required.

> [@benedikt](#):
>
> `target_compile_features()` does not seem to set the property `CXX_STANDARD` any more.

To my knowledge, it never did that before, but maybe @tambre can confirm. The two mechanisms are separate, but as explained above, CMake enforces the higher constraint of these. I can’t explain how you got the result with Ubuntu 20.04 though, that is suspicious.

---

<div class="post-metadata">

### Author: ![tambre](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tambre/32/5127_2.png) [@tambre](https://discourse.cmake.org/u/tambre)
#### Post date: [March 3, 2023, 5:04pm UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584/3 "2023-03-03T17:04:07Z")

</div>

> [@craig.scott](#):
>
> > [@benedikt](#):
> >
> > `target_compile_features()` does not seem to set the property `CXX_STANDARD` any more.
> 
> To my knowledge, it never did that before, but maybe @tambre can confirm. The two mechanisms are separate, but as explained above, CMake enforces the higher constraint of these. I can’t explain how you got the result with Ubuntu 20.04 though, that is suspicious.

There’s [a FIXME in `cmStandardLevelResolver.cxx`](https://gitlab.kitware.com/cmake/cmake/-/blob/0a9945cb8d6c1568d7a120eaaf0b02b8d078ecbf/Source/cmStandardLevelResolver.cxx#L438-442) that seems related. Essentially `target_compile_features()` effects are observable in some cases during the configuration stage. They aren’t intended to be and we need a policy eventually to fix this.

I teste various versions between 3.16 and 3.26-rc5 on Windows with MSVC and I’m unable to reproduce the issue. It functions like “Ubuntu 20.04” for all of them.

---

<div class="post-metadata">

### Author: ![benedikt](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/51bf81/32.png) [@benedikt](https://discourse.cmake.org/u/benedikt)
#### Post date: [March 6, 2023, 6:41am UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584/4 "2023-03-06T06:41:48Z")

</div>

Thank you very much @craig.scott and @tambre for sharing these insights!

I’m happy to learn that this was not the best and most robust approach - which for me immediately sparks the question: what would be the right and robust approach? Is there a way to interrogate CMake, which language standard it selected for a given target while configuring it?

---

<div class="post-metadata">

### Author: ![tambre](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tambre/32/5127_2.png) [@tambre](https://discourse.cmake.org/u/tambre)
#### Post date: [March 6, 2023, 10:30am UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584/5 "2023-03-06T10:30:56Z")

</div>

You should be able to use the [`$<COMPILE_FEATURES:features>`](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:COMPILE_FEATURES) to get the final value during the generation phase when. Should presumably work with `add_custom_command()`/`add_custom_target()`.

[`$<TARGET_PROPERTY:prop>`](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_PROPERTY) might work as well.

---

<div class="post-metadata">

### Author: ![benedikt](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/51bf81/32.png) [@benedikt](https://discourse.cmake.org/u/benedikt)
#### Post date: [March 6, 2023, 12:57pm UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584/6 "2023-03-06T12:57:17Z")

</div>

Unfortunately this is “to late” - the analyzers are configured via calls to `set_target_properties(tgt PROPERTIES CXX_CPPCHECK cmdline)` where I can not use generator expressions. But I understand that information might not be available at the time I call that function.

Any help to break this circular reasoning is welcome…

---

<div class="post-metadata">

### Author: ![tambre](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tambre/32/5127_2.png) [@tambre](https://discourse.cmake.org/u/tambre)
#### Post date: [March 6, 2023, 1:07pm UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584/7 "2023-03-06T13:07:52Z")

</div>

It seems the fix would be to support generator expressions for `<LANG>_CPPCHECK` like we do already for `LINK_LIBRARIES`, `INCLUDE_DIRECTORIES`, `COMPILE_DEFINITIONS`. Seems like it should be just a few lines of code.

@craig.scott Agreed on this approach?

---

<div class="post-metadata">

### Author: ![benedikt](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/51bf81/32.png) [@benedikt](https://discourse.cmake.org/u/benedikt)
#### Post date: [March 6, 2023, 1:17pm UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584/8 "2023-03-06T13:17:39Z")

</div>

If that is possible that should be supported for CXX\_CLANG\_TIDY as well (and maybe there are even more tools I’m not aware of…)

---

<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: [March 6, 2023, 8:32pm UTC](https://discourse.cmake.org/t/inquiring-c-standard-from-build-target-for-analyzer-config-possible-regression-bug-or-missing-documentation/7584/9 "2023-03-06T20:32:14Z")

</div>

Adding support for generator expressions to `<LANG>_CPPCHECK` seems reasonable. You could mount a similar argument for `<LANG>_CPPLINT`, `<LANG>_INCLUDE_WHAT_YOU_USE` and `<LANG>_CLANG_TIDY` as well. CMake 3.25 did that for `<LANG>_COMPILER_LAUNCHER`.
