Add support for setting arbitrary c++ standards for a project
I am using:
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:
-
- 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 specifytarget_compile_feature
for every single target.
- if
-
- 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.
- if I pass it
-
- if I pass it
cxx_std_2a
orcxx_std_20
then CMake errors because it doesn't know those flags
- if I pass it
-
- since this is the second time this breaks in less than a year, maybe a different, more future-proof solution should be considered (e.g. pass a
cxx_std_xy
string, parse it, requirexy
to be a number, and ifxy
is not known by cmake, try-std=c++xy
, assume that ifxy > wz
then thexy
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).
- since this is the second time this breaks in less than a year, maybe a different, more future-proof solution should be considered (e.g. pass a
-
- 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 viaadd_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.
- even if
-
- 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=...
.
- if
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.