1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4# This module is shared by multiple languages and compilers; use include guard
5if (__COMPILER_CMAKE_COMMON_COMPILER_MACROS)
6  return()
7endif ()
8set(__COMPILER_CMAKE_COMMON_COMPILER_MACROS 1)
9
10
11# Check that a compiler's language standard is properly detected
12# Parameters:
13#   lang   - Language to check
14#   stdver1 - Minimum version to set a given default for
15#   std1    - Default to use for compiler ver >= stdver1
16#   stdverN - Minimum version to set a given default for
17#   stdN    - Default to use for compiler ver >= stdverN
18#
19#   The order of stdverN stdN pairs passed as arguments is expected to be in
20#   monotonically increasing version order.
21#
22# Note:
23#   This macro can be called with multiple version / std pairs to convey that
24#   newer compiler versions may use a newer standard default.
25#
26# Example:
27#   To specify that compiler version 6.1 and newer defaults to C++11 while
28#   4.8 <= ver < 6.1 default to C++98, you would call:
29#
30# __compiler_check_default_language_standard(CXX 4.8 98 6.1 11)
31#
32macro(__compiler_check_default_language_standard lang stdver1 std1)
33  set(__std_ver_pairs "${stdver1};${std1};${ARGN}")
34  string(REGEX REPLACE " *; *" " " __std_ver_pairs "${__std_ver_pairs}")
35  string(REGEX MATCHALL "[^ ]+ [^ ]+" __std_ver_pairs "${__std_ver_pairs}")
36
37  # If the compiler version is below the threshold of even having CMake
38  # support for language standards, then don't bother.
39  if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL "${stdver1}")
40    if (NOT CMAKE_${lang}_COMPILER_FORCED)
41      if (NOT CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT OR NOT DEFINED CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT)
42        message(FATAL_ERROR "CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT and CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT should be set for ${CMAKE_${lang}_COMPILER_ID} (${CMAKE_${lang}_COMPILER}) version ${CMAKE_${lang}_COMPILER_VERSION}")
43      endif ()
44      set(CMAKE_${lang}_STANDARD_DEFAULT ${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT})
45      set(CMAKE_${lang}_EXTENSIONS_DEFAULT ${CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT})
46    else ()
47      list(REVERSE __std_ver_pairs)
48      foreach (__std_ver_pair IN LISTS __std_ver_pairs)
49        string(REGEX MATCH "([^ ]+) (.+)" __std_ver_pair "${__std_ver_pair}")
50        set(__stdver ${CMAKE_MATCH_1})
51        set(__std ${CMAKE_MATCH_2})
52        # Compiler id was forced so just guess the defaults.
53        if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL __stdver)
54          if(NOT DEFINED CMAKE_${lang}_EXTENSIONS_DEFAULT)
55            # Currently known compilers default to enabling extensions.
56            set(CMAKE_${lang}_EXTENSIONS_DEFAULT ON)
57          endif()
58          if(NOT DEFINED CMAKE_${lang}_STANDARD_DEFAULT)
59            set(CMAKE_${lang}_STANDARD_DEFAULT ${__std})
60          endif()
61        endif ()
62        unset(__std)
63        unset(__stdver)
64      endforeach ()
65    endif ()
66  endif ()
67  unset(__std_ver_pairs)
68endmacro()
69
70# Define to allow compile features to be automatically determined
71macro(cmake_record_c_compile_features)
72  set(_result 0)
73  if(_result EQUAL 0 AND DEFINED CMAKE_C23_STANDARD_COMPILE_OPTION)
74    _has_compiler_features_c(23)
75  endif()
76  if(_result EQUAL 0 AND DEFINED CMAKE_C17_STANDARD_COMPILE_OPTION)
77    _has_compiler_features_c(17)
78  endif()
79  if(_result EQUAL 0 AND DEFINED CMAKE_C11_STANDARD_COMPILE_OPTION)
80    if(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT)
81      _has_compiler_features_c(11)
82    else()
83      _record_compiler_features_c(11)
84    endif()
85    unset(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT)
86  endif()
87  if(_result EQUAL 0 AND DEFINED CMAKE_C99_STANDARD_COMPILE_OPTION)
88    if(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT)
89      _has_compiler_features_c(99)
90    else()
91      _record_compiler_features_c(99)
92    endif()
93    unset(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT)
94  endif()
95  if(_result EQUAL 0 AND DEFINED CMAKE_C90_STANDARD_COMPILE_OPTION)
96    if(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT)
97      _has_compiler_features_c(90)
98    else()
99      _record_compiler_features_c(90)
100    endif()
101    unset(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT)
102  endif()
103endmacro()
104
105# Define to allow compile features to be automatically determined
106macro(cmake_record_cxx_compile_features)
107  set(_result 0)
108  if(_result EQUAL 0 AND DEFINED CMAKE_CXX23_STANDARD_COMPILE_OPTION)
109    _has_compiler_features_cxx(23)
110  endif()
111  if(_result EQUAL 0 AND DEFINED CMAKE_CXX20_STANDARD_COMPILE_OPTION)
112    _has_compiler_features_cxx(20)
113  endif()
114  if(_result EQUAL 0 AND DEFINED CMAKE_CXX17_STANDARD_COMPILE_OPTION)
115    _has_compiler_features_cxx(17)
116  endif()
117  if(_result EQUAL 0 AND DEFINED CMAKE_CXX14_STANDARD_COMPILE_OPTION)
118    if(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT)
119      _has_compiler_features_cxx(14)
120    else()
121      _record_compiler_features_cxx(14)
122    endif()
123    unset(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT)
124  endif()
125  if(_result EQUAL 0 AND DEFINED CMAKE_CXX11_STANDARD_COMPILE_OPTION)
126    if(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT)
127      _has_compiler_features_cxx(11)
128    else()
129      _record_compiler_features_cxx(11)
130    endif()
131    unset(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT)
132  endif()
133  if(_result EQUAL 0 AND DEFINED CMAKE_CXX98_STANDARD_COMPILE_OPTION)
134    if(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT)
135      _has_compiler_features_cxx(98)
136    else()
137      _record_compiler_features_cxx(98)
138    endif()
139    unset(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT)
140  endif()
141endmacro()
142
143macro(cmake_record_cuda_compile_features)
144  set(_result 0)
145  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA23_STANDARD_COMPILE_OPTION)
146    _has_compiler_features_cuda(23)
147  endif()
148  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA20_STANDARD_COMPILE_OPTION)
149    _has_compiler_features_cuda(20)
150  endif()
151  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA17_STANDARD_COMPILE_OPTION)
152    _has_compiler_features_cuda(17)
153  endif()
154  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA14_STANDARD_COMPILE_OPTION)
155    if(CMAKE_CUDA14_STANDARD__HAS_FULL_SUPPORT)
156      _has_compiler_features_cuda(14)
157    else()
158      _record_compiler_features_cuda(14)
159    endif()
160    unset(CMAKE_CUDA14_STANDARD__HAS_FULL_SUPPORT)
161  endif()
162  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA11_STANDARD_COMPILE_OPTION)
163    if(CMAKE_CUDA11_STANDARD__HAS_FULL_SUPPORT)
164      _has_compiler_features_cuda(11)
165    else()
166      _record_compiler_features_cuda(11)
167    endif()
168    unset(CMAKE_CUDA11_STANDARD__HAS_FULL_SUPPORT)
169  endif()
170  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA03_STANDARD_COMPILE_OPTION)
171    if(CMAKE_CUDA03_STANDARD__HAS_FULL_SUPPORT)
172      _has_compiler_features_cuda(03)
173    else()
174      _record_compiler_features_cuda(03)
175    endif()
176    unset(CMAKE_CUDA03_STANDARD__HAS_FULL_SUPPORT)
177  endif()
178endmacro()
179
180macro(cmake_record_hip_compile_features)
181  set(_result 0)
182  if(_result EQUAL 0 AND DEFINED CMAKE_HIP23_STANDARD_COMPILE_OPTION)
183    _has_compiler_features_hip(23)
184  endif()
185  if(_result EQUAL 0 AND DEFINED CMAKE_HIP20_STANDARD_COMPILE_OPTION)
186    _has_compiler_features_hip(20)
187  endif()
188  if(_result EQUAL 0 AND DEFINED CMAKE_HIP17_STANDARD_COMPILE_OPTION)
189    _has_compiler_features_hip(17)
190  endif()
191  _has_compiler_features_hip(14)
192  _has_compiler_features_hip(11)
193  _has_compiler_features_hip(98)
194endmacro()
195