Merge topic 'cpack-innosetup-linux'
[kiteware-cmake.git] / Modules / FindOpenMP.cmake
blob077a2398abfc8c57b6fd9609b5cc2f527ef0787e
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:
5 FindOpenMP
6 ----------
8 Finds Open Multi-Processing (OpenMP) support.
10 This module can be used to detect OpenMP support in a compiler.  If
11 the compiler supports OpenMP, the flags required to compile with
12 OpenMP support are returned in variables for the different languages.
13 The variables may be empty if the compiler does not need a special
14 flag to support OpenMP.
16 .. versionadded:: 3.5
17   Clang support.
19 Variables
20 ^^^^^^^^^
22 .. versionadded:: 3.10
23   The module exposes the components ``C``, ``CXX``, and ``Fortran``.
24   Each of these controls the various languages to search OpenMP support for.
26 Depending on the enabled components the following variables will be set:
28 ``OpenMP_FOUND``
29   Variable indicating that OpenMP flags for all requested languages have been found.
30   If no components are specified, this is true if OpenMP settings for all enabled languages
31   were detected.
32 ``OpenMP_VERSION``
33   Minimal version of the OpenMP standard detected among the requested languages,
34   or all enabled languages if no components were specified.
36 This module will set the following variables per language in your
37 project, where ``<lang>`` is one of C, CXX, or Fortran:
39 ``OpenMP_<lang>_FOUND``
40   Variable indicating if OpenMP support for ``<lang>`` was detected.
41 ``OpenMP_<lang>_FLAGS``
42   OpenMP compiler flags for ``<lang>``, separated by spaces.
43 ``OpenMP_<lang>_INCLUDE_DIRS``
44   Directories that must be added to the header search path for ``<lang>``
45   when using OpenMP.
47 For linking with OpenMP code written in ``<lang>``, the following
48 variables are provided:
50 ``OpenMP_<lang>_LIB_NAMES``
51   :ref:`;-list <CMake Language Lists>` of libraries for OpenMP programs for ``<lang>``.
52 ``OpenMP_<libname>_LIBRARY``
53   Location of the individual libraries needed for OpenMP support in ``<lang>``.
54 ``OpenMP_<lang>_LIBRARIES``
55   A list of libraries needed to link with OpenMP code written in ``<lang>``.
57 Additionally, the module provides :prop_tgt:`IMPORTED` targets:
59 ``OpenMP::OpenMP_<lang>``
60   Target for using OpenMP from ``<lang>``.
62 Specifically for Fortran, the module sets the following variables:
64 ``OpenMP_Fortran_HAVE_OMPLIB_HEADER``
65   Boolean indicating if OpenMP is accessible through ``omp_lib.h``.
66 ``OpenMP_Fortran_HAVE_OMPLIB_MODULE``
67   Boolean indicating if OpenMP is accessible through the ``omp_lib`` Fortran module.
69 The module will also try to provide the OpenMP version variables:
71 ``OpenMP_<lang>_SPEC_DATE``
72   .. versionadded:: 3.7
74   Date of the OpenMP specification implemented by the ``<lang>`` compiler.
75 ``OpenMP_<lang>_VERSION_MAJOR``
76   Major version of OpenMP implemented by the ``<lang>`` compiler.
77 ``OpenMP_<lang>_VERSION_MINOR``
78   Minor version of OpenMP implemented by the ``<lang>`` compiler.
79 ``OpenMP_<lang>_VERSION``
80   OpenMP version implemented by the ``<lang>`` compiler.
82 The specification date is formatted as given in the OpenMP standard:
83 ``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of
84 the OpenMP specification implemented by the ``<lang>`` compiler.
86 For some compilers, it may be necessary to add a header search path to find
87 the relevant OpenMP headers.  This location may be language-specific.  Where
88 this is needed, the module may attempt to find the location, but it can be
89 provided directly by setting the ``OpenMP_<lang>_INCLUDE_DIR`` cache variable.
90 Note that this variable is an _input_ control to the module.  Project code
91 should use the ``OpenMP_<lang>_INCLUDE_DIRS`` _output_ variable if it needs
92 to know what include directories are needed.
93 #]=======================================================================]
95 cmake_policy(PUSH)
96 cmake_policy(SET CMP0012 NEW) # if() recognizes numbers and booleans
97 cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
98 cmake_policy(SET CMP0057 NEW) # if IN_LIST
99 cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
101 function(_OPENMP_FLAG_CANDIDATES LANG)
102   if(NOT OpenMP_${LANG}_FLAG)
103     unset(OpenMP_FLAG_CANDIDATES)
105     set(OMP_FLAG_GNU "-fopenmp")
106     set(OMP_FLAG_LCC "-fopenmp")
107     set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp" "-Xclang -fopenmp")
108     set(OMP_FLAG_AppleClang "-Xclang -fopenmp")
109     set(OMP_FLAG_HP "+Oopenmp")
110     if(WIN32)
111       set(OMP_FLAG_Intel "-Qopenmp")
112     elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND
113            "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528")
114       set(OMP_FLAG_Intel "-openmp")
115     else()
116       set(OMP_FLAG_Intel "-qopenmp")
117     endif()
118     if(CMAKE_${LANG}_COMPILER_ID STREQUAL "IntelLLVM" AND
119       "x${CMAKE_${LANG}_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
120       set(OMP_FLAG_IntelLLVM "-Qiopenmp")
121     else()
122       set(OMP_FLAG_IntelLLVM "-fiopenmp")
123     endif()
124     set(OMP_FLAG_MSVC "-openmp")
125     set(OMP_FLAG_PathScale "-openmp")
126     set(OMP_FLAG_NAG "-openmp")
127     set(OMP_FLAG_Absoft "-openmp")
128     set(OMP_FLAG_NVHPC "-mp")
129     set(OMP_FLAG_PGI "-mp")
130     set(OMP_FLAG_Flang "-fopenmp")
131     set(OMP_FLAG_SunPro "-xopenmp")
132     set(OMP_FLAG_XL "-qsmp=omp")
133     # Cray compiler activate OpenMP with -h omp, which is enabled by default.
134     set(OMP_FLAG_Cray " " "-h omp")
135     set(OMP_FLAG_Fujitsu "-Kopenmp" "-KOMP")
136     set(OMP_FLAG_FujitsuClang "-fopenmp" "-Kopenmp")
138     # If we know the correct flags, use those
139     if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID})
140       set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}")
141     # Fall back to reasonable default tries otherwise
142     else()
143       set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ")
144     endif()
145     set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE)
146   else()
147     set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE)
148   endif()
149 endfunction()
151 # sample openmp source code to test
152 set(OpenMP_C_CXX_TEST_SOURCE
154 #include <omp.h>
155 int main(void) {
156 #ifdef _OPENMP
157   omp_get_max_threads();
158   return 0;
159 #elif defined(__HIP_DEVICE_COMPILE__)
160   return 0;
161 #else
162   breaks_on_purpose
163 #endif
167 # in Fortran, an implementation may provide an omp_lib.h header
168 # or omp_lib module, or both (OpenMP standard, section 3.1)
169 # Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2)
170 # Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code
171 # while not actually enabling OpenMP, building code sequentially
172 set(OpenMP_Fortran_TEST_SOURCE
173   "
174       program test
175       @OpenMP_Fortran_INCLUDE_LINE@
176   !$  integer :: n
177       n = omp_get_num_threads()
178       end program test
179   "
182 macro(_OPENMP_PREPARE_SOURCE LANG CONTENT_ID NAME_PREFIX FULLNAME_VAR CONTENT_VAR)
183   if("${LANG}" STREQUAL "C")
184     set(${FULLNAME_VAR} "${NAME_PREFIX}.c")
185     set(${CONTENT_VAR} "${OpenMP_C_CXX_${CONTENT_ID}}")
186   elseif("${LANG}" STREQUAL "CXX")
187     set(${FULLNAME_VAR} "${NAME_PREFIX}.cpp")
188     set(${CONTENT_VAR} "${OpenMP_C_CXX_${CONTENT_ID}}")
189   elseif("${LANG}" STREQUAL "Fortran")
190     set(${FULLNAME_VAR} "${NAME_PREFIX}.F90")
191     string(CONFIGURE "${OpenMP_Fortran_${CONTENT_ID}}" ${CONTENT_VAR} @ONLY)
192   endif()
193 endmacro()
195 include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseImplicitLinkInfo.cmake)
197 function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
198   _OPENMP_FLAG_CANDIDATES("${LANG}")
199   _OPENMP_PREPARE_SOURCE("${LANG}" TEST_SOURCE OpenMPTryFlag
200     _OPENMP_TEST_SRC_NAME _OPENMP_TEST_SRC_CONTENT)
202   unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
203   separate_arguments(OpenMP_VERBOSE_OPTIONS NATIVE_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}")
204   foreach(_VERBOSE_OPTION IN LISTS OpenMP_VERBOSE_OPTIONS)
205     if(NOT _VERBOSE_OPTION MATCHES "^-Wl,")
206       list(APPEND OpenMP_VERBOSE_COMPILE_OPTIONS ${_VERBOSE_OPTION})
207     endif()
208   endforeach()
210   foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES)
211     set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}")
212     if(OpenMP_VERBOSE_COMPILE_OPTIONS)
213       string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}")
214     endif()
215     string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
216     unset(_includeDirFlags)
217     if(OpenMP_${LANG}_INCLUDE_DIR)
218       set(_includeDirFlags "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}")
219     endif()
220     try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}
221       SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
222       LOG_DESCRIPTION "Detecting ${LANG} OpenMP compiler info"
223       CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" ${_includeDirFlags}
224       LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG}
225       OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
226     )
228     if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} AND
229        NOT "${CMAKE_${LANG}_COMPILER_ID};${CMAKE_${LANG}_SIMULATE_ID}" STREQUAL "Clang;MSVC")
230       set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
232       if(CMAKE_${LANG}_VERBOSE_FLAG)
233         unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES)
234         unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS)
235         unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS)
236         unset(OpenMP_${LANG}_LOG_VAR)
238         cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}"
239           OpenMP_${LANG}_IMPLICIT_LIBRARIES
240           OpenMP_${LANG}_IMPLICIT_LINK_DIRS
241           OpenMP_${LANG}_IMPLICIT_FWK_DIRS
242           OpenMP_${LANG}_LOG_VAR
243           "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}"
244           LANGUAGE ${LANG}
245         )
247         # For LCC we should additionally alanyze -print-search-dirs output
248         # to check for additional implicit_dirs.
249         # Note: This won't work if CMP0129 policy is set to OLD!
250         if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "LCC")
251           execute_process(
252             COMMAND ${CMAKE_${LANG}_COMPILER} -print-search-dirs
253             OUTPUT_VARIABLE output_lines
254             COMMAND_ERROR_IS_FATAL ANY
255             ERROR_QUIET)
256           if("${output_lines}" MATCHES ".*\nlibraries:[ \t]+(.*:)\n.*")
257             string(REPLACE ":" ";" implicit_dirs_addon "${CMAKE_MATCH_1}")
258             list(PREPEND OpenMP_${LANG}_IMPLICIT_LINK_DIRS ${implicit_dirs_addon})
259             string(APPEND OpenMP_${LANG}_LOG_VAR
260               "  Extended OpenMP library search paths: [${implicit_dirs}]\n")
261           endif()
262         endif()
264         message(CONFIGURE_LOG
265           "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n")
267         unset(_OPENMP_LIB_NAMES)
268         foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES)
269           get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY)
270           get_filename_component(_OPENMP_IMPLICIT_LIB_NAME "${_OPENMP_IMPLICIT_LIB}" NAME)
271           get_filename_component(_OPENMP_IMPLICIT_LIB_PLAIN "${_OPENMP_IMPLICIT_LIB}" NAME_WE)
272           string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PLAIN_ESC "${_OPENMP_IMPLICIT_LIB_PLAIN}")
273           string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PATH_ESC "${_OPENMP_IMPLICIT_LIB}")
274           if(NOT ( "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES
275             OR "${CMAKE_${LANG}_STANDARD_LIBRARIES}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)"
276             OR "${CMAKE_${LANG}_LINK_EXECUTABLE}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" ) )
277             if(_OPENMP_IMPLICIT_LIB_DIR)
278               set(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY "${_OPENMP_IMPLICIT_LIB}" CACHE FILEPATH
279                 "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP")
280             else()
281               find_library(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY
282                 NAMES "${_OPENMP_IMPLICIT_LIB_NAME}"
283                 DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP"
284                 HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
285                 CMAKE_FIND_ROOT_PATH_BOTH
286                 NO_PACKAGE_ROOT_PATH
287                 NO_CMAKE_PATH
288                 NO_CMAKE_ENVIRONMENT_PATH
289               )
290             endif()
291             mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY)
292             list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB_PLAIN})
293           endif()
294         endforeach()
295         set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE)
296       else()
297         # We do not know how to extract implicit OpenMP libraries for this compiler.
298         # Assume that it handles them automatically, e.g. the Intel Compiler on
299         # Windows should put the dependency in its object files.
300         set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
301       endif()
302       break()
303     elseif((CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang"
304       AND CMAKE_${LANG}_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0") OR
305       (CMAKE_${LANG}_COMPILER_ID STREQUAL "Clang" AND APPLE))
307       # Check for separate OpenMP library on AppleClang 7+
308       find_library(OpenMP_libomp_LIBRARY
309         NAMES omp gomp iomp5
310         HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
311       )
312       mark_as_advanced(OpenMP_libomp_LIBRARY)
314       if(OpenMP_libomp_LIBRARY)
315         # Try without specifying include directory first. We only want to
316         # explicitly add a search path if the header can't be found on the
317         # default header search path already.
318         try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}
319           SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
320           LOG_DESCRIPTION "Trying ${LANG} OpenMP compiler with '${OpenMP_libomp_LIBRARY}'"
321           CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
322           LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
323         )
324         if(NOT OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
325           find_path(OpenMP_${LANG}_INCLUDE_DIR omp.h)
326           mark_as_advanced(OpenMP_${LANG}_INCLUDE_DIR)
327           set(OpenMP_${LANG}_INCLUDE_DIR "${OpenMP_${LANG}_INCLUDE_DIR}" PARENT_SCOPE)
328           if(OpenMP_${LANG}_INCLUDE_DIR)
329             try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}
330               SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
331               LOG_DESCRIPTION "Trying ${LANG} OpenMP compiler with '${OpenMP_libomp_LIBRARY}' and '${OpenMP_${LANG}_INCLUDE_DIR}'"
332               CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
333                           "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}"
334               LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
335             )
336           endif()
337         endif()
338         if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
339           set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
340           set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
341           break()
342         endif()
343       endif()
344     elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Clang" AND WIN32)
345       # Check for separate OpenMP library for Clang on Windows
346       find_library(OpenMP_libomp_LIBRARY
347         NAMES libomp libgomp libiomp5
348         HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
349       )
350       mark_as_advanced(OpenMP_libomp_LIBRARY)
351       if(OpenMP_libomp_LIBRARY)
352         try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}
353           SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
354           LOG_DESCRIPTION "Trying ${LANG} OpenMP compiler with '${OpenMP_libomp_LIBRARY}'"
355           CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
356           LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
357         )
358         if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
359           set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
360           set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
361           break()
362         endif()
363       endif()
364     endif()
365     set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
366     set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
367   endforeach()
369   unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
370 endfunction()
372 set(OpenMP_C_CXX_CHECK_VERSION_SOURCE
374 #include <stdio.h>
375 #include <omp.h>
376 const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M',
377                             'P', '-', 'd', 'a', 't', 'e', '[',
378                             ('0' + ((_OPENMP/100000)%10)),
379                             ('0' + ((_OPENMP/10000)%10)),
380                             ('0' + ((_OPENMP/1000)%10)),
381                             ('0' + ((_OPENMP/100)%10)),
382                             ('0' + ((_OPENMP/10)%10)),
383                             ('0' + ((_OPENMP/1)%10)),
384                             ']', '\\0' };
385 int main(void)
387   puts(ompver_str);
388   return 0;
392 set(OpenMP_Fortran_CHECK_VERSION_SOURCE
394       program omp_ver
395       @OpenMP_Fortran_INCLUDE_LINE@
396       integer, parameter :: zero = ichar('0')
397       integer, parameter :: ompv = openmp_version
398       character, dimension(24), parameter :: ompver_str =&
399       (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 'P', '-',&
400          'd', 'a', 't', 'e', '[',&
401          char(zero + mod(ompv/100000, 10)),&
402          char(zero + mod(ompv/10000, 10)),&
403          char(zero + mod(ompv/1000, 10)),&
404          char(zero + mod(ompv/100, 10)),&
405          char(zero + mod(ompv/10, 10)),&
406          char(zero + mod(ompv/1, 10)), ']' /)
407       print *, ompver_str
408       end program omp_ver
411 function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
412   _OPENMP_PREPARE_SOURCE("${LANG}" CHECK_VERSION_SOURCE OpenMPCheckVersion
413     _OPENMP_TEST_SRC_NAME _OPENMP_TEST_SRC_CONTENT)
415   unset(_includeDirFlags)
416   if(OpenMP_${LANG}_INCLUDE_DIR)
417     set(_includeDirFlags "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}")
418   endif()
420   set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin")
421   string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
422   try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}
423     SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
424     LOG_DESCRIPTION "Detecting ${LANG} OpenMP version"
425     CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}" ${_includeDirFlags}
426     COPY_FILE "${BIN_FILE}"
427     )
429   if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}})
430     file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
431     set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*")
432     if("${specstr}" MATCHES "${regex_spec_date}")
433       set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
434     endif()
435   endif()
436 endfunction()
438 macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG)
439   set(OpenMP_SPEC_DATE_MAP
440     "202111=5.2"
441     "202011=5.1"
442     # Preview versions
443     "201611=5.0" # OpenMP 5.0 preview 1
444     # Combined versions, 2.5 onwards
445     "201811=5.0"
446     "201511=4.5"
447     "201307=4.0"
448     "201107=3.1"
449     "200805=3.0"
450     "200505=2.5"
451     # C/C++ version 2.0
452     "200203=2.0"
453     # Fortran version 2.0
454     "200011=2.0"
455     # Fortran version 1.1
456     "199911=1.1"
457     # C/C++ version 1.0 (there's no 1.1 for C/C++)
458     "199810=1.0"
459     # Fortran version 1.0
460     "199710=1.0"
461   )
462   if(MSVC)
463     list(APPEND OpenMP_SPEC_DATE_MAP "2019=2.0")
464   endif()
466   if(OpenMP_${LANG}_SPEC_DATE)
467     string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}")
468   else()
469     set(_version_match "")
470   endif()
471   if(NOT _version_match STREQUAL "")
472     set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1})
473     set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2})
474     set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}")
475   else()
476     unset(OpenMP_${LANG}_VERSION_MAJOR)
477     unset(OpenMP_${LANG}_VERSION_MINOR)
478     unset(OpenMP_${LANG}_VERSION)
479   endif()
480   unset(_version_match)
481   unset(OpenMP_SPEC_DATE_MAP)
482 endmacro()
484 foreach(LANG IN ITEMS C CXX)
485   if(CMAKE_${LANG}_COMPILER_LOADED)
486     if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND"
487       OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
488       _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK)
489       if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND")
490         set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
491           CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE)
492       endif()
493       if(NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
494         set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
495           CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE)
496       endif()
497       mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES)
498     endif()
499   endif()
500 endforeach()
502 if(CMAKE_Fortran_COMPILER_LOADED)
503   if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
504     OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
505     OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
506     set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n      implicit none")
507     _OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
508     if(OpenMP_Fortran_FLAGS_WORK)
509       set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "")
510     endif()
512     if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND")
513       set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
514         CACHE STRING "Fortran compiler flags for OpenMP parallelization" FORCE)
515     endif()
516     if(NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND")
517       set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
518         CACHE STRING "Fortran compiler libraries for OpenMP parallelization" FORCE)
519     endif()
520     mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES)
521   endif()
523   if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
524     OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
525     OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
526     set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n      include 'omp_lib.h'")
527     _OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
528     if(OpenMP_Fortran_FLAGS_WORK)
529       set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "")
530     endif()
532     if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND")
533       set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
534         CACHE STRING "Fortran compiler flags for OpenMP parallelization" FORCE)
535     endif()
536     if(NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND")
537       set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
538         CACHE STRING "Fortran compiler libraries for OpenMP parallelization" FORCE)
539     endif()
540   endif()
542   if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
543     set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n      implicit none")
544   else()
545     set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n      include 'omp_lib.h'")
546   endif()
547 endif()
549 if(NOT OpenMP_FIND_COMPONENTS)
550   set(OpenMP_FINDLIST C CXX Fortran)
551 else()
552   set(OpenMP_FINDLIST ${OpenMP_FIND_COMPONENTS})
553 endif()
555 unset(_OpenMP_MIN_VERSION)
557 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
559 foreach(LANG IN LISTS OpenMP_FINDLIST)
560   if(CMAKE_${LANG}_COMPILER_LOADED)
561     if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS)
562       _OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL)
563       set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE
564         INTERNAL "${LANG} compiler's OpenMP specification date")
565     endif()
566     _OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}")
568     set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY})
569     set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED})
570     set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION})
571     set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT})
573     set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS)
574     if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
575       set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES)
576     else()
577       foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
578         list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY)
579       endforeach()
580     endif()
582     find_package_handle_standard_args(OpenMP_${LANG}
583       NAME_MISMATCHED
584       REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS}
585       VERSION_VAR OpenMP_${LANG}_VERSION
586     )
588     if(OpenMP_${LANG}_FOUND)
589       if(DEFINED OpenMP_${LANG}_VERSION)
590         if(NOT _OpenMP_MIN_VERSION OR _OpenMP_MIN_VERSION VERSION_GREATER OpenMP_${LANG}_VERSION)
591           set(_OpenMP_MIN_VERSION OpenMP_${LANG}_VERSION)
592         endif()
593       endif()
594       set(OpenMP_${LANG}_LIBRARIES "")
595       foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
596         list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}")
597       endforeach()
598       if(OpenMP_${LANG}_INCLUDE_DIR)
599         set(OpenMP_${LANG}_INCLUDE_DIRS ${OpenMP_${LANG}_INCLUDE_DIR})
600       else()
601         set(OpenMP_${LANG}_INCLUDE_DIRS "")
602       endif()
604       if(NOT TARGET OpenMP::OpenMP_${LANG})
605         add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED)
606       endif()
607       if(OpenMP_${LANG}_FLAGS)
608         set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
609           INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:SHELL:${OpenMP_${LANG}_FLAGS}>")
610         if(CMAKE_${LANG}_COMPILER_ID STREQUAL "Fujitsu"
611           OR ${CMAKE_${LANG}_COMPILER_ID} STREQUAL "IntelLLVM")
612           set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
613             INTERFACE_LINK_OPTIONS "SHELL:${OpenMP_${LANG}_FLAGS}")
614         endif()
615       endif()
616       if(OpenMP_${LANG}_INCLUDE_DIRS)
617         set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
618           INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${OpenMP_${LANG}_INCLUDE_DIRS}>")
619       endif()
620       if(OpenMP_${LANG}_LIBRARIES)
621         set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
622           INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}")
623       endif()
624     endif()
625   endif()
626 endforeach()
628 unset(_OpenMP_REQ_VARS)
629 foreach(LANG IN ITEMS C CXX Fortran)
630   if((NOT OpenMP_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST OpenMP_FIND_COMPONENTS)
631     list(APPEND _OpenMP_REQ_VARS "OpenMP_${LANG}_FOUND")
632   endif()
633 endforeach()
635 find_package_handle_standard_args(OpenMP
636     REQUIRED_VARS ${_OpenMP_REQ_VARS}
637     VERSION_VAR ${_OpenMP_MIN_VERSION}
638     HANDLE_COMPONENTS)
640 set(OPENMP_FOUND ${OpenMP_FOUND})
642 if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND)
643   if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
644     set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "")
645   endif()
646   if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
647     set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "")
648   endif()
649 endif()
651 if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED ))
652   message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled")
653 endif()
655 unset(OpenMP_C_CXX_TEST_SOURCE)
656 unset(OpenMP_Fortran_TEST_SOURCE)
657 unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE)
658 unset(OpenMP_Fortran_CHECK_VERSION_SOURCE)
659 unset(OpenMP_Fortran_INCLUDE_LINE)
661 cmake_policy(POP)