Add support for setting arbitrary c++ standards for a project
I am using:
```cmake
check_cxx_compiler_flag("-std=c++2a" HAS_STDCXX_2a)
if (HAS_STDCXX_2a)
add_compile_options("-std=c++2a")
else()
check_cxx_compiler_flag("/std:c++2a" HAS_STDCXX_2a_MSVC)
if (HAS_STDCXX_2a_MSVC)
add_compile_options("/std:c++2a")
else()
message("The compiler doesn't support the 2a C++ standard")
exit()
endif()
endif()
```
to set the C++ standard of my project, but if I include Qt then CMake adds as the last flag to the C++ compiler `-std=gnu++11`.
It seems that Qt does something like this: `set_property(TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_FEATURES cxx_decltype)`
and that for "reasons" this means "force the C++11 standard with GNU extensions on all targets that depend on this target" independently of the compile options of the target.
I was told that I could pass to cmake `-DCMAKE_CXX_FLAGS="-std=c++2a"` on the command line to override all the C++ standard detection features. This feels wrong, those configuring my project shouldn't need to pass this kind of information through the command line.
I was also told that the best way to set this is via: `target_compile_features(my_custom_target PUBLIC cxx_std_xxx)` but:
- 1. if `my_custom_target` is not compilable, this errors (e.g. a dummy target that all other my compilable targets depend on), this means that right now I need to manually specify `target_compile_feature` for every single target.
- 2. if I pass it `cxx_std_17` then CMake adds the `-std=c++1z` flag instead of the `-std=c++17` flag. This is broken. CMake should check if the C++ compiler supports the `-std=c++17` flag, and only if this isn't the case try the `-std=c++1z` flag.
- 3. if I pass it `cxx_std_2a` or `cxx_std_20` then CMake errors because it doesn't know those flags
- 4. since this is the second time this breaks [in less than a year](https://gitlab.kitware.com/cmake/cmake/issues/16468), maybe a different, more future-proof solution should be considered (e.g. pass a `cxx_std_xy` string, parse it, require `xy` to be a number, and if `xy` is not known by cmake, try `-std=c++xy`, assume that if `xy > wz` then the `xy` standard is more recent, if `-std=c++xy` does not work, try `-std=c++xc/b/a/z/y/x`, and only if none of those work then error; also keep a list of known versions, but not be too "hard" if the user passes it a "custom" standard version).
- 5. even if `set_property`/`set_compile_features` is the "modern" way of setting the C++ standard of CMake targets, doing so while ignoring features specified via `add_compile_options` seems a recipe for disaster: basically Qt is now causing me pain,
and the only way that I have to override this is to `-DCMAKE_CXX_FLAGS="-std=c++2a"` which is something that my clients should not have to deal with.
- 6. if `check_cxx_compiler_flag`/`add_compile_options` shouldn't be used to set the C++ standard, they should warn when a user tries to use them to set `-std=...`.
I don't know whether the things in this list are "bugs" or "features", so first I would like to clear up if I just took the very wrong approach to setting the language standard, and if that is the case, maybe fill some issues about improving diagnostics to help others running into the same pitfals.
issue