Feature Request: Latest Language Standard Specification
Summary
The MSVC has a means to specify that the latest C++ standard should be used via the /std:c++latest
command line argument. It would be convenient if CMake provided a similar facility when generating build files so that users did not have to update their own CMake scripts to account for a new version of the language standard for their project.
(NOTE: Throughout this issue, I will be referring to the C++ standard in particular. However, this feature can and should be applied to all languages whose standards are recognized by CMake - namely, C, C++, CUDA/C++, and HIP.)
Use Cases
For many larger projects with a substantial list of dependencies and supported platforms, it can make sense to specify a hard limit on the language standard (e.g., C++17). However, for smaller projects or those which are built in a more controlled environment, being able to easily specify that the latest C++ standard be used can be convenient.
Anecdotally, I have written and used a CMake function similar to the following for defining the C++ language standard used in my own personal projects:
function(GetLatestCXXStandard OUT_CXX_STANDARD)
set(${OUT_CXX_STANDARD} cxx_std_23 PARENT_SCOPE)
endfunction()
# ...
add_library(SomeLibrary)
GetLatestCXXStandard(LATEST_CXX_STANDARD)
target_compile_features(SomeLibrary
PRIVATE
${LATEST_CXX_STANDARD}
)
This works, but it requires that the user manually update the implementation of the GetLatestCXXStandard()
function to account for an update in build environment or language standard (even if it only happens every, say, three years). It would be more convenient and future proof if CMake offered a standardized method for specifying that the latest supported C++ standard be used to compile a given target.
Feature Details
The proposed approach is for CMake to expose a CMAKE_CXX_STANDARD_LATEST
variable which is assigned an integer value representing the latest C++ standard supported by the current compiler (e.g., 23
for C++23). This can then be used to specify the C++ standard level for a target:
# Set the latest C++ standard as the default for created targets.
set(CMAKE_CXX_STANDARD ${CMAKE_CXX_STANDARD_LATEST})
# === OR ===
# Set the latest C++ standard for a specific target.
target_compile_features(SomeLibrary PRIVATE cxx_std_${CMAKE_CXX_STANDARD_LATEST})
It would also be possible for script developers to use the value of this variable to conditionally enable optional features for a distributed library. However, we should stress in the documentation that integer comparisons will not work between C++ standard versions. This is because some older standards have a greater numerical value than newer standards. The documentation can include a code sample like the following to demonstrate how one could correctly perform this check:
# Careful! We cannot do direct integer comparisons with CMAKE_CXX_STANDARD_LATEST
# because some earlier C++ standards (e.g., C++98) will have a higher numerical
# value than our requirement (C++17).
#
# Instead, we keep a list of unsupported C++ standards and check if
# CMAKE_CXX_STANDARD_LATEST appears in that list.
set(UNSUPPORTED_CXX_STANDARDS
98
11
14
)
list(FIND UNSUPPORTED_CXX_STANDARDS ${CMAKE_CXX_STANDARD_LATEST} UNSUPPORTED_CXX_STANDARDS_INDEX)
if(UNSUPPORTED_CXX_STANDARDS_INDEX EQUAL -1)
# Enabling some optional feature...
else()
message(STATUS
"Feature X is disabled because it requires C++17, but the current compiler "
"only supports C++${CMAKE_CXX_STANDARD_LATEST}."
)
endif()
Other Approaches
This section contains ideas which were at one point proposed, but have since been rejected for implementation. They are kept here for reference.
cxx_std_latest Compile Feature
One approach would be to add a new cxx_std_latest
(or similarly named) compile feature to the CMAKE_CXX_KNOWN_FEATURES
list. Then, users would be able to write CMake code like the following to automatically build their project with the latest supported standard:
add_library(SomeLibrary)
target_compile_features(SomeLibrary
PRIVATE
cxx_std_latest
)
This behavior has actually been implemented in this branch, and !9288 (closed) was submitted as a merge request. However, that request was closed for further discussion. Furthermore, @brad.king pointed out in this comment that this proposal is fundamentally flawed as a compile feature. Essentially, cxx_std_latest
cannot safely be in the INTERFACE_COMPILE_FEATURES
list of a distributed project because it would imply different requirements in different build environments.