1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
4 #[=======================================================================[.rst:
10 Check whether the compiler supports an interprocedural optimization (IPO/LTO).
11 Use this before enabling the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target
14 .. command:: check_ipo_supported
18 check_ipo_supported([RESULT <result>] [OUTPUT <output>]
19 [LANGUAGES <lang>...])
24 Set ``<result>`` variable to ``YES`` if IPO is supported by the
25 compiler and ``NO`` otherwise. If this option is not given then
26 the command will issue a fatal error if IPO is not supported.
28 Set ``<output>`` variable with details about any error.
29 ``LANGUAGES <lang>...``
30 Specify languages whose compilers to check.
31 Languages ``C``, ``CXX``, and ``Fortran`` are supported.
33 It makes no sense to use this module when :policy:`CMP0069` is set to ``OLD`` so
34 module will return error in this case. See policy :policy:`CMP0069` for details.
36 .. versionadded:: 3.13
37 Add support for Visual Studio generators.
39 .. versionadded:: 3.24
40 The check uses the caller's :variable:`CMAKE_<LANG>_FLAGS`
41 and :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` values.
42 See policy :policy:`CMP0138`.
49 check_ipo_supported() # fatal error if IPO is not supported
50 set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
54 # Optional IPO. Do not use IPO if it's not supported by compiler.
55 check_ipo_supported(RESULT result OUTPUT output)
57 set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
59 message(WARNING "IPO is not supported: ${output}")
62 #]=======================================================================]
64 # X_RESULT - name of the final result variable
65 # X_OUTPUT - name of the variable with information about error
66 macro(_ipo_not_supported output)
68 message(FATAL_ERROR "IPO is not supported (${output}).")
71 set("${X_RESULT}" NO PARENT_SCOPE)
73 set("${X_OUTPUT}" "${output}" PARENT_SCOPE)
78 macro(_ipo_run_language_check language)
82 string(COMPARE EQUAL "${language}" "CUDA" is_cuda)
84 set(ext ${_${language}_ext})
85 if(NOT "${ext}" STREQUAL "")
86 set(copy_sources foo.${ext} main.${ext})
88 if(_CMAKE_CUDA_IPO_SUPPORTED_BY_CMAKE)
89 set("${X_RESULT}" YES PARENT_SCOPE)
93 message(FATAL_ERROR "Language not supported")
96 set(testdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/_CMakeLTOTest-${language}")
98 file(REMOVE_RECURSE "${testdir}")
99 file(MAKE_DIRECTORY "${testdir}")
101 set(bindir "${testdir}/bin")
102 set(srcdir "${testdir}/src")
104 file(MAKE_DIRECTORY "${bindir}")
105 file(MAKE_DIRECTORY "${srcdir}")
107 set(TRY_COMPILE_PROJECT_NAME "lto-test")
109 set(try_compile_src "${CMAKE_ROOT}/Modules/CheckIPOSupported")
112 # * TRY_COMPILE_PROJECT_NAME
115 "${try_compile_src}/CMakeLists-${language}.txt.in"
116 "${srcdir}/CMakeLists.txt"
120 foreach(x ${copy_sources})
122 "${try_compile_src}/${x}"
128 if(ipo_CMP0138 STREQUAL "NEW")
129 set(CMAKE_TRY_COMPILE_CONFIGURATION Debug)
130 set(_CMAKE_LANG_FLAGS
131 "-DCMAKE_${language}_FLAGS:STRING=${CMAKE_${language}_FLAGS}"
132 "-DCMAKE_${language}_FLAGS_DEBUG:STRING=${CMAKE_${language}_FLAGS_DEBUG}"
135 set(_CMAKE_LANG_FLAGS "")
139 _IPO_LANGUAGE_CHECK_RESULT
140 PROJECT "${TRY_COMPILE_PROJECT_NAME}"
141 SOURCE_DIR "${srcdir}"
142 BINARY_DIR "${bindir}"
144 "-DCMAKE_VERBOSE_MAKEFILE=ON"
145 "-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON"
147 OUTPUT_VARIABLE output
149 set(_IPO_LANGUAGE_CHECK_RESULT "${_IPO_LANGUAGE_CHECK_RESULT}")
150 unset(_IPO_LANGUAGE_CHECK_RESULT CACHE)
152 if(NOT _IPO_LANGUAGE_CHECK_RESULT)
153 _ipo_not_supported("check failed to compile")
155 set("${X_OUTPUT}" "${output}" PARENT_SCOPE)
161 function(check_ipo_supported)
162 cmake_policy(GET CMP0069 x)
164 string(COMPARE EQUAL "${x}" "" not_set)
166 message(FATAL_ERROR "Policy CMP0069 is not set")
169 string(COMPARE EQUAL "${x}" "OLD" is_old)
171 message(FATAL_ERROR "Policy CMP0069 set to OLD")
174 # Save policy setting for condition in _ipo_run_language_check.
175 cmake_policy(GET CMP0138 ipo_CMP0138
176 PARENT_SCOPE # undocumented, do not use outside of CMake
180 set(one RESULT OUTPUT)
181 set(multiple LANGUAGES)
187 cmake_parse_arguments(X "${optional}" "${one}" "${multiple}" "${ARGV}")
189 string(COMPARE NOTEQUAL "${X_UNPARSED_ARGUMENTS}" "" has_unparsed)
191 message(FATAL_ERROR "Unparsed arguments: ${X_UNPARSED_ARGUMENTS}")
194 string(COMPARE EQUAL "${X_LANGUAGES}" "" no_languages)
196 # User did not set any languages, use defaults
197 get_property(enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
198 string(COMPARE EQUAL "${enabled_languages}" "" no_languages)
201 "no languages found in ENABLED_LANGUAGES global property"
207 list(FIND enabled_languages "CXX" result)
208 if(NOT result EQUAL -1)
209 list(APPEND languages "CXX")
212 list(FIND enabled_languages "C" result)
213 if(NOT result EQUAL -1)
214 list(APPEND languages "C")
217 list(FIND enabled_languages "CUDA" result)
218 if(NOT result EQUAL -1)
219 list(APPEND languages "CUDA")
222 list(FIND enabled_languages "Fortran" result)
223 if(NOT result EQUAL -1)
224 list(APPEND languages "Fortran")
227 string(COMPARE EQUAL "${languages}" "" no_languages)
230 "no C/CXX/CUDA/Fortran languages found in ENABLED_LANGUAGES global property"
235 set(languages "${X_LANGUAGES}")
237 set(unsupported_languages "${languages}")
238 list(REMOVE_ITEM unsupported_languages "C" "CXX" "CUDA" "Fortran")
239 string(COMPARE NOTEQUAL "${unsupported_languages}" "" has_unsupported)
242 "language(s) '${unsupported_languages}' not supported"
248 foreach(lang ${languages})
249 if(NOT _CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE)
250 _ipo_not_supported("CMake doesn't support IPO for current ${lang} compiler")
254 if(NOT _CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER)
255 _ipo_not_supported("${lang} compiler doesn't support IPO")
260 if(CMAKE_GENERATOR MATCHES "^Visual Studio 9 ")
261 _ipo_not_supported("CMake doesn't support IPO for current generator")
265 foreach(x ${languages})
266 _ipo_run_language_check(${x})
269 set("${X_RESULT}" YES PARENT_SCOPE)