0

I did read this question: How to detect C++11 support in CMake. It basically tells me that CMake's support for detecting C++ features is very sophisticated when you want to fail generation if a certain compiler does NOT support the feature you are using in your code but also extremely limited when you want to react on this at generation time without failing.

What I would like to be able to do is not to fail but e.g. to define a different set of source files if certain features are not available in order to allow compilation of old c++03 code if needed and use the newer c++11-... ones if possible. Something like this would be great:

set(TARGET MyTarget)
if(CPP_STANDARD_VERSION GREATER_EQUAL 11)
    set(SOURCE myModernFile.cpp)
else()
    set(SOURCE myLegacyFile.cpp)
endif()
add_executable(${TARGET} ${SOURCE })
if(CPP_STANDARD_VERSION GREATER_EQUAL 11)
    # Here failing would be fine if lambdas are not supported!
    target_compile_features(${TARGET} PRIVATE cxx_lambdas)
endif()

When following this approach as recommended in the linked question:

foreach(i ${CMAKE_CXX_COMPILE_FEATURES})
  message("${i}")
endforeach()

e.g. with Visual Studio 2013 with CMake 3.13.2 I am getting the following output:

cxx_std_98
cxx_std_11
cxx_std_14
cxx_std_17
cxx_std_20
cxx_alias_templates
cxx_auto_type
cxx_contextual_conversions
cxx_decltype
cxx_default_function_template_args
cxx_defaulted_functions
cxx_delegating_constructors
cxx_enum_forward_declarations
cxx_explicit_conversions
cxx_extended_friend_declarations
cxx_extern_templates
cxx_final
cxx_generalized_initializers
cxx_lambdas
cxx_local_type_template_args
cxx_long_long_type
cxx_nullptr
cxx_override
cxx_range_for
cxx_raw_string_literals
cxx_right_angle_brackets
cxx_rvalue_references
cxx_static_assert
cxx_strong_enums
cxx_template_template_parameters
cxx_trailing_return_types
cxx_uniform_initialization
cxx_variadic_macros
cxx_variadic_templates

To me the list makes sense for the specific features, but the general ones with the supported C++ standards apparently cannot be right as VS 2013 does not support C++20. Am I missing something?

Right now I ended up with more or less the same approach as described in the linked question: I check various compiler versions manually and then depending on that I set my CPP_STANDARD_VERSION property, but this seems very fragile to me. Is there really no other way?

StefanB
  • 21
  • 4
  • Is there something wrong with just checking if `CMAKE_CXX_COMPILE_FEATURES` contains `cxx_std_11` or higher? It was part of the accepted answer you linked to. – fdk1342 Feb 04 '19 at 12:15
  • Looking at the MSVC-CXX.cmake file it just adds all of the `cxx_std_XX` to the compiler features because older MSVC compiler didn't have a language standard flag (according to the comments). The logic doesn't seem quite correct because `cxx_std_20` shouldn't be in the list for this version of Visual Studio compilers but no issue report seems to have been made on the CMake website. You could just check to see if the feature you need is supported instead as this seems to be correct. – fdk1342 Feb 04 '19 at 17:37
  • Apparently looking for the features I need also doesn't really help as I would like to find out e.g. if I can use std::mutex or std::thread for a start. This unfortunately cannot be done using the supported features. And checking if e.g. 'nullptr' is supported and then assuming that I can safely use threads seems a bit like a hack.I also had a look at the CMake sources and it seems(as you pointed out) that VS 2010 - 2015 are not handled absolutely correct. I did create a ticket there(https://gitlab.kitware.com/cmake/cmake/issues/18874). Thanks! – StefanB Feb 05 '19 at 06:02

0 Answers0