How to set standard C++ 2003 in CMake - cmake

I'm looking for solution how to set standard of C++ to 2003 in cmake. I can find a lot of information how to do it on later versions like 11, 17 and so on. But for 2003 version I couldn't find it. Does someone knows how to set it? I found also how to do it by adding flag to every cmake list that project contains. The problem is that I have a lot of cmake lists in my project and I want to add it once in main cmake lists.
Thanks in advance for help.

See the docs for CMAKE_CXX_STANDARD
Supported values are: [98, 11, 14, 17, 20, 23].
03 is not supported.
Notes:
Note that while gcc supports -std=c++03 as a flag, it is just an alias for -std=c++98. So the two flags have the same effect and it doesn't make a difference which of the two you use:
The original ISO C++ standard was published as the ISO standard (ISO/IEC 14882:1998) and amended by a Technical Corrigenda published in 2003 (ISO/IEC 14882:2003). These standards are referred to as C++98 and C++03, respectively. GCC implements the majority of C++98 (export is a notable exception) and most of the changes in C++03. To select this standard in GCC, use one of the options -ansi, -std=c++98, or -std=c++03; to obtain all the diagnostics required by the standard, you should also specify -pedantic (or -pedantic-errors if you want them to be errors rather than warnings).
MSVC does not provide flags for selecting standards older than C++14 (ctrl+F for "/std").

Related

How to error out cleanly in CMake if CMAKE_CXX_STANDARD cannot be met?

CMake provides CMAKE_CXX_STANDARD for specifying the required C++ Standard.
set (CMAKE_CXX_STANDARD 17)
However, if your compiler is old... say gcc4... it will still attempt to compile the sources, and it will of course fail with bizarre error messages, due to missing compiler features.
Is there a clean way to make CMake detect this missing support, and fail in a more obvious way?
From https://cmake.org/cmake/help/latest/variable/CMAKE_CXX_STANDARD.html :
See the cmake-compile-features(7) manual for information on compile features and a list of supported compilers.
From https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html#manual:cmake-compile-features(7) :
The CMAKE_C_KNOWN_FEATURES, CMAKE_CUDA_KNOWN_FEATURES, and CMAKE_CXX_KNOWN_FEATURES global properties contain all the features known to CMake, regardless of compiler support for the feature. The CMAKE_C_COMPILE_FEATURES, CMAKE_CUDA_COMPILE_FEATURES , and CMAKE_CXX_COMPILE_FEATURES variables contain all features CMake knows are known to the compiler, regardless of language standard or compile flags needed to use them.
From https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#prop_gbl:CMAKE_CXX_KNOWN_FEATURES :
cxx_std_17
Compiler mode is at least C++ 17.
Check:
if ("cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
Using target_compile_features for more control
As KamilCuk mentioned in their answer, you can check for cxx_std_17.
Additionally, you can set the requirement on a target with:
target_compile_features(my_example_library PUBLIC cxx_std_17)
Source https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html#requiring-language-standards
This is more verbose, but it allows you to specify that only some targets need certain standards. The same syntax can also be used to require only specific features, full list found in CMAKE_CXX_KNOWN_FEATURES.
Simpler option for CMAKE_CXX_STANDARD, set CXX_STANDARD_REQUIRED
However, if you're using CMAKE_CXX_STANDARD, it's much easier to just set CMAKE_CXX_STANDARD_REQUIRED, e.g.:
# will affect any library/target defined after this
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
# also recommended, uses -std=c++17 instead of -std=gnu++17
# if you code is compatible with non-GCC compilers too
# set(CMAKE_CXX_EXTENSIONS OFF)
You'll get an error that looks something like:
CMake Error in CMakeLists.txt:
Target "my_example_library" requires the language dialect "C17" (with
compiler extensions). But the current compiler "GNU" does not support
this, or CMake does not know the flags to enable it.

Cmake - Documentation

I use clang, gcc (and also their arm version).
is there somewhere a documentation, where i can see which values the following 2 arguments take:
set(CMAKE_SYSTEM_NAME <value>)
set(CMAKE_SYSTEM_PROCESSOR <value>)
i cannot find any doc, where cmake lists every possible input.
i just see that you have to assign a value to those, but what options do i have?
like system name: Linux is one, how about Windows?
And then what about processors, arm, x86, x86_64 (amd64)...
would be cool if someone knows a good source of documentation.
thanks
From the CMake wiki about cross compiling:
Once the system and the compiler are determined by CMake, it loads the
corresponding files in the following order:
Platform/${CMAKE_SYSTEM_NAME}.cmake (optional, but issues a stern
warning)
Platform/${CMAKE_SYSTEM_NAME}-<compiler>.cmake
(optional)
Platform/${CMAKE_SYSTEM_NAME}-<compiler>-${CMAKE_SYSTEM_PROCESSOR}.cmake
(optional)
So, for find out all possible values for variable CMAKE_SYSTEM_NAME you could check filenames under Modules/Platform and extract the first part of every filename.
As for CMAKE_SYSTEM_PROCESSOR variable, its only purpose is to include the latter file (of 3 components in the filename). From the same wiki:
This variable is not used very much except for one purpose,
it is used to load a CMAKE_SYSTEM_NAME-compiler-CMAKE_SYSTEM_PROCESSOR.cmake file,
which can be used to modify settings like compiler flags etc. for the target.
You probably only have to set this one if you are using a cross compiler
where every target hardware needs special build settings.

How to detect C++11-... support of a compiler with CMake and react without failing generation

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?

Specifying a minimum required C++ standard

According to the documentation, setting CXX_STANDARD_REQUIRED to ON prohibits the build system from using older C++ standards then the one requested by CXX_STANDARD.
But this leads to "interesting" problems when combined with the WriteCompilerDetectionHeader module. e.g. when offering some form of "forward compatibility":
set(CMAKE_CXX_STANDARD 11) and testing for cxx_relaxed_constexpr, then conditionally defining a macro that expands to constexpr leads to compilation errors on GCC 6.3.0 as the requirements of CXX_STANDARD and the usage of the macro are conflicting (the feature header using the actual feature set of the compiler, not the one offered by the compiler when requiring C++11).
Is there any way to specifying a required minimum C++ standard, without prohibiting more recent standards (e.g. C++ 11 or later)? The only workaround I can currently think about would be to not set CXX_STANDARD and CXX_STANDARD_REQUIRED at all and just "informally" require a minimum version of C++...
No, there is no way to do this easily. While you could extend CMake to continuously compile objects up-to (or down-to) a specific standard, this would take quite a lot of effort. There ways to possibly do what you want depending on your circumstances.
Use non-conflicting macros. Using your example, use #define MYCONSTEXPR ... instead of #define constexpr ...
Use larger conditional blocks based on the standard
Is your project mostly one standard, but have a few files that need a different one? use CMake's set_source_files_properties() to set a new CXX_STANDARD or COMPILE_FLAGS.

Should I always use -Wall and -pedantic switches with g++ while learning C++?

Being a --novice, I am wondering is it beneficial to always use these flags (with g++) while learning C++ ?
Thanks
As long as you understand that code samples written by others will likely result in warnings with -Wall, then yes, it's a good flag to use because it gets you in the habit of writing code that is free of any potential gray areas the compiler may be able to identify.
-pedantic, on the other hand, is a trickier case. Here's what the GCC 4.4.4 manpage has to say about it:
Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not
follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.
Valid ISO C and ISO C++ programs should compile properly with or without this option (though a rare few will require -ansi or a -std option specifying
the required version of ISO C). However, without this option, certain GNU extensions and traditional C and C++ features are supported as well. With
this option, they are rejected.
-pedantic does not cause warning messages for use of the alternate keywords whose names begin and end with __. Pedantic warnings are also disabled in
the expression that follows "__extension__". However, only system header files should use these escape routes; application programs should avoid
them.
Some users try to use -pedantic to check programs for strict ISO C conformance. They soon find that it does not do quite what they want: it finds
some non-ISO practices, but not all---only those for which ISO C requires a diagnostic, and some others for which diagnostics have been added.
A feature to report any failure to conform to ISO C might be useful in some instances, but would require considerable additional work and would be
quite different from -pedantic. We don't have plans to support such a feature in the near future.
Not exactly an answer but there's the -Weffc++ flag which emits warnings for constructs that violate guidelines in Effective C++ (the book by Scott Meyer).
While these guidelines are good they can also be too strict eg. the STL headers will issue warnings.