Investigating on the question of the actual C++ dialect used when requesting on with target_compile_features I discovered that my CMake version set 2 variables:
They actually seemed to correspond to the requested compiler default standard and CMake behavior seems to replace my target_compile_features request by the compiler default if this one is higher than my demand.
The reason why has been discussed in the provided link but now I’m wondering if these variable can be safely used to deduce and report the actual version used (which does not appear in any other variable). AFAIK, they are not cached variables, and no cached variable contains the desired information either.
As I said there, it’s a generator-time determination of what the actual standard in use is. The only 100% reliable way to detect any of this is with the __cplusplus preprocessor symbol.
I’d like to be sure to understand. CMAKE_CXX_STANDARD_DEFAULT is set at configuration time but actual standard used (for instance through an added -std option) is determined at generation time?
Is there a rule that, if user is requesting some standard, the chosen option at generation time is the greater of the user-requested and the CMAKE_CXX_STANDARD_DEFAULT?
Is it a behavior that can change in time or that depends on the generator?
IMHO, it’s a “bug” that this behavior is not explicitly documented (but, as discussed in another thread, maybe I’m over-zealous and the only thing that matters for coder is to have, at least, the requested standard).
Regards
PS though C++ tries to be legacy-compliant it’s not always the case. I’ve got code that broke because some functions became constexpr and it changed some specialization choices in library using metaprogramming, leading to wrong behavior.
It took me time to track down the issue and, in the meantime, it was a real issue to have my builds updated to C++17, while only C++14 was working.
There was yet another thread where enforcing a C++ maximum version within the ,cpp source files was discussed.
#if __cplusplus >
#error
#endif
Another way to do this might be to check each target property cxx_standard If the source C++ files cannot be modified due to management decision.
Another way would be to have cmake generate and then a separate checker script parse compile_commands.json. although that does not account for the default C++ standard of particular compiler versions.
Hmm, I could not find where the merge logic of “use newest compile feature” is documented. @brad.king? We could use a few extra cross-references to where it does (will?) live from COMPILE_FEATURES, target_compile_features, and the <LANG>_STANDARD variable docs.
CMAKE_CXX_STANDARD[_COMPUTED]_DEFAULT are implementation details that are not documented or meant for public use.
where the merge logic of “use newest compile feature” is documented
I don’t think we document any specific algorithm for selecting a standard level. The documentation of each cxx_std_## feature says it means only that the “Compiler mode is at least C++##”. That document also says “If the compiler’s default standard level is at least that of the requested feature, CMake may omit the -std= flag.”
I note also that I should not use CMAKE_CXX_STANDARD[_COMPUTED]_DEFAULT.
Thus it leaves me with my issue where I needed (at least temporarily) an exact C++ dialect. Do you feel it can be a motivation for opening an issue (feature request)?
I thought even CXX_STANDARD still ended up being part of the same logic that ensured that at least that version was used, not that it should use that exact version. In other words, I don’t think CXX_STANDARD guarantees you’ll get that exact standard either, even if there are no target_compile_features() that ask for something higher. But I haven’t checked the code lately to reconfirm my understanding (it’s been a while since I’ve looked at that logic).
The cxx_std_## features are for minimum standard levels. CXX_STANDARD will be honored even if it is lower than the compiler’s default, and an explicit -std= flag will be used to achieve it if necessary.
Is CMAKE_CXX_STANDARD forcing flag a policy-enabled behavior? I can’t make it work when building protobuf. I don’t have minimal reproducer yet, but here are pieces I have found so far:
I have a problem with third-party vendor toolchain where CMake incorrectly detects (probably self-reported by toolchain/compiler) C+14 as default standard and as a result some code can’t be compiled: it would if -std=C+14 was passed, but it didn’t get passed.
I started to experiment with CMAKE_CXX_STANDARD on MSVC as it is something I can potentially build reproducer with to report here.
Reading this thread, I had an impression that CMAKE_CXX_STANDARD=14 property should force adding std=c++14 flag even if compiler’s default standard is C++14, but it seems I misunderstood.
Looks like my only option is to either force C++17 or fix compiler detection.
I did try cmake -DCMAKE_CXX_STANDARD=14 which adds CXX_STANDARD property to all non-imported targets. Do you have reason to believe that explicit property will have different effect?