FindOpenMP.cmake 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file Copyright.txt or https://cmake.org/licensing for details.
  3. #.rst:
  4. # FindOpenMP
  5. # ----------
  6. #
  7. # Finds OpenMP support
  8. #
  9. # This module can be used to detect OpenMP support in a compiler. If
  10. # the compiler supports OpenMP, the flags required to compile with
  11. # OpenMP support are returned in variables for the different languages.
  12. # The variables may be empty if the compiler does not need a special
  13. # flag to support OpenMP.
  14. #
  15. # Variables
  16. # ^^^^^^^^^
  17. #
  18. # The module exposes the components ``C``, ``CXX``, and ``Fortran``.
  19. # Each of these controls the various languages to search OpenMP support for.
  20. #
  21. # Depending on the enabled components the following variables will be set:
  22. #
  23. # ``OpenMP_FOUND``
  24. # Variable indicating that OpenMP flags for all requested languages have been found.
  25. # If no components are specified, this is true if OpenMP settings for all enabled languages
  26. # were detected.
  27. # ``OpenMP_VERSION``
  28. # Minimal version of the OpenMP standard detected among the requested languages,
  29. # or all enabled languages if no components were specified.
  30. #
  31. # This module will set the following variables per language in your
  32. # project, where ``<lang>`` is one of C, CXX, or Fortran:
  33. #
  34. # ``OpenMP_<lang>_FOUND``
  35. # Variable indicating if OpenMP support for ``<lang>`` was detected.
  36. # ``OpenMP_<lang>_FLAGS``
  37. # OpenMP compiler flags for ``<lang>``, separated by spaces.
  38. #
  39. # For linking with OpenMP code written in ``<lang>``, the following
  40. # variables are provided:
  41. #
  42. # ``OpenMP_<lang>_LIB_NAMES``
  43. # :ref:`;-list <CMake Language Lists>` of libraries for OpenMP programs for ``<lang>``.
  44. # ``OpenMP_<libname>_LIBRARY``
  45. # Location of the individual libraries needed for OpenMP support in ``<lang>``.
  46. # ``OpenMP_<lang>_LIBRARIES``
  47. # A list of libraries needed to link with OpenMP code written in ``<lang>``.
  48. #
  49. # Additionally, the module provides :prop_tgt:`IMPORTED` targets:
  50. #
  51. # ``OpenMP::OpenMP_<lang>``
  52. # Target for using OpenMP from ``<lang>``.
  53. #
  54. # Specifically for Fortran, the module sets the following variables:
  55. #
  56. # ``OpenMP_Fortran_HAVE_OMPLIB_HEADER``
  57. # Boolean indicating if OpenMP is accessible through ``omp_lib.h``.
  58. # ``OpenMP_Fortran_HAVE_OMPLIB_MODULE``
  59. # Boolean indicating if OpenMP is accessible through the ``omp_lib`` Fortran module.
  60. #
  61. # The module will also try to provide the OpenMP version variables:
  62. #
  63. # ``OpenMP_<lang>_SPEC_DATE``
  64. # Date of the OpenMP specification implemented by the ``<lang>`` compiler.
  65. # ``OpenMP_<lang>_VERSION_MAJOR``
  66. # Major version of OpenMP implemented by the ``<lang>`` compiler.
  67. # ``OpenMP_<lang>_VERSION_MINOR``
  68. # Minor version of OpenMP implemented by the ``<lang>`` compiler.
  69. # ``OpenMP_<lang>_VERSION``
  70. # OpenMP version implemented by the ``<lang>`` compiler.
  71. #
  72. # The specification date is formatted as given in the OpenMP standard:
  73. # ``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of
  74. # the OpenMP specification implemented by the ``<lang>`` compiler.
  75. cmake_policy(PUSH)
  76. cmake_policy(SET CMP0012 NEW) # if() recognizes numbers and booleans
  77. cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
  78. cmake_policy(SET CMP0057 NEW) # if IN_LIST
  79. function(_OPENMP_FLAG_CANDIDATES LANG)
  80. if(NOT OpenMP_${LANG}_FLAG)
  81. unset(OpenMP_FLAG_CANDIDATES)
  82. set(OMP_FLAG_GNU "-fopenmp")
  83. set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp")
  84. set(OMP_FLAG_AppleClang "-Xclang -fopenmp")
  85. set(OMP_FLAG_HP "+Oopenmp")
  86. if(WIN32)
  87. set(OMP_FLAG_Intel "-Qopenmp")
  88. elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND
  89. "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528")
  90. set(OMP_FLAG_Intel "-openmp")
  91. else()
  92. set(OMP_FLAG_Intel "-qopenmp")
  93. endif()
  94. set(OMP_FLAG_MIPSpro "-mp")
  95. set(OMP_FLAG_MSVC "-openmp")
  96. set(OMP_FLAG_PathScale "-openmp")
  97. set(OMP_FLAG_NAG "-openmp")
  98. set(OMP_FLAG_Absoft "-openmp")
  99. set(OMP_FLAG_PGI "-mp")
  100. set(OMP_FLAG_Flang "-fopenmp")
  101. set(OMP_FLAG_SunPro "-xopenmp")
  102. set(OMP_FLAG_XL "-qsmp=omp")
  103. # Cray compiler activate OpenMP with -h omp, which is enabled by default.
  104. set(OMP_FLAG_Cray " " "-h omp")
  105. # If we know the correct flags, use those
  106. if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID})
  107. set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}")
  108. # Fall back to reasonable default tries otherwise
  109. else()
  110. set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ")
  111. endif()
  112. set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE)
  113. else()
  114. set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE)
  115. endif()
  116. endfunction()
  117. # sample openmp source code to test
  118. set(OpenMP_C_CXX_TEST_SOURCE
  119. "
  120. #include <omp.h>
  121. int main(void) {
  122. #ifdef _OPENMP
  123. omp_get_max_threads();
  124. return 0;
  125. #else
  126. breaks_on_purpose
  127. #endif
  128. }
  129. ")
  130. # in Fortran, an implementation may provide an omp_lib.h header
  131. # or omp_lib module, or both (OpenMP standard, section 3.1)
  132. # Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2)
  133. # Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code
  134. # while not actually enabling OpenMP, building code sequentially
  135. set(OpenMP_Fortran_TEST_SOURCE
  136. "
  137. program test
  138. @OpenMP_Fortran_INCLUDE_LINE@
  139. !$ integer :: n
  140. n = omp_get_num_threads()
  141. end program test
  142. "
  143. )
  144. function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH)
  145. set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP)
  146. if("${LANG}" STREQUAL "C")
  147. set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c")
  148. file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
  149. elseif("${LANG}" STREQUAL "CXX")
  150. set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp")
  151. file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
  152. elseif("${LANG}" STREQUAL "Fortran")
  153. set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90")
  154. file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}")
  155. configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY)
  156. endif()
  157. set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
  158. endfunction()
  159. include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseImplicitLinkInfo.cmake)
  160. function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
  161. _OPENMP_FLAG_CANDIDATES("${LANG}")
  162. _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC)
  163. unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
  164. separate_arguments(OpenMP_VERBOSE_OPTIONS NATIVE_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}")
  165. foreach(_VERBOSE_OPTION IN LISTS OpenMP_VERBOSE_OPTIONS)
  166. if(NOT _VERBOSE_OPTION MATCHES "^-Wl,")
  167. list(APPEND OpenMP_VERBOSE_COMPILE_OPTIONS ${_VERBOSE_OPTION})
  168. endif()
  169. endforeach()
  170. foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES)
  171. set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}")
  172. if(OpenMP_VERBOSE_COMPILE_OPTIONS)
  173. string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}")
  174. endif()
  175. string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
  176. try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
  177. CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
  178. LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG}
  179. OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
  180. )
  181. if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
  182. set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
  183. if(CMAKE_${LANG}_VERBOSE_FLAG)
  184. unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES)
  185. unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS)
  186. unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS)
  187. unset(OpenMP_${LANG}_LOG_VAR)
  188. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  189. "Detecting ${LANG} OpenMP compiler ABI info compiled with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
  190. cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}"
  191. OpenMP_${LANG}_IMPLICIT_LIBRARIES
  192. OpenMP_${LANG}_IMPLICIT_LINK_DIRS
  193. OpenMP_${LANG}_IMPLICIT_FWK_DIRS
  194. OpenMP_${LANG}_LOG_VAR
  195. "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}"
  196. )
  197. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  198. "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n")
  199. unset(_OPENMP_LIB_NAMES)
  200. foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES)
  201. get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY)
  202. get_filename_component(_OPENMP_IMPLICIT_LIB_NAME "${_OPENMP_IMPLICIT_LIB}" NAME)
  203. get_filename_component(_OPENMP_IMPLICIT_LIB_PLAIN "${_OPENMP_IMPLICIT_LIB}" NAME_WE)
  204. string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PLAIN_ESC "${_OPENMP_IMPLICIT_LIB_PLAIN}")
  205. string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PATH_ESC "${_OPENMP_IMPLICIT_LIB}")
  206. if(NOT ( "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES
  207. OR "${CMAKE_${LANG}_STANDARD_LIBRARIES}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)"
  208. OR "${CMAKE_${LANG}_LINK_EXECUTABLE}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" ) )
  209. if(_OPENMP_IMPLICIT_LIB_DIR)
  210. set(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY "${_OPENMP_IMPLICIT_LIB}" CACHE FILEPATH
  211. "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP")
  212. else()
  213. find_library(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY
  214. NAMES "${_OPENMP_IMPLICIT_LIB_NAME}"
  215. DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP"
  216. HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
  217. CMAKE_FIND_ROOT_PATH_BOTH
  218. NO_DEFAULT_PATH
  219. )
  220. endif()
  221. mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY)
  222. list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB_PLAIN})
  223. endif()
  224. endforeach()
  225. set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE)
  226. else()
  227. # We do not know how to extract implicit OpenMP libraries for this compiler.
  228. # Assume that it handles them automatically, e.g. the Intel Compiler on
  229. # Windows should put the dependency in its object files.
  230. set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
  231. endif()
  232. break()
  233. elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang"
  234. AND CMAKE_${LANG}_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0")
  235. # Check for separate OpenMP library on AppleClang 7+
  236. find_library(OpenMP_libomp_LIBRARY
  237. NAMES omp gomp iomp5
  238. HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
  239. )
  240. mark_as_advanced(OpenMP_libomp_LIBRARY)
  241. if(OpenMP_libomp_LIBRARY)
  242. try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
  243. CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
  244. LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
  245. OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
  246. )
  247. if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
  248. set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
  249. set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
  250. break()
  251. endif()
  252. endif()
  253. else()
  254. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  255. "Detecting ${LANG} OpenMP failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
  256. endif()
  257. set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
  258. set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
  259. endforeach()
  260. unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
  261. endfunction()
  262. set(OpenMP_C_CXX_CHECK_VERSION_SOURCE
  263. "
  264. #include <stdio.h>
  265. #include <omp.h>
  266. const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M',
  267. 'P', '-', 'd', 'a', 't', 'e', '[',
  268. ('0' + ((_OPENMP/100000)%10)),
  269. ('0' + ((_OPENMP/10000)%10)),
  270. ('0' + ((_OPENMP/1000)%10)),
  271. ('0' + ((_OPENMP/100)%10)),
  272. ('0' + ((_OPENMP/10)%10)),
  273. ('0' + ((_OPENMP/1)%10)),
  274. ']', '\\0' };
  275. int main(void)
  276. {
  277. puts(ompver_str);
  278. return 0;
  279. }
  280. ")
  281. set(OpenMP_Fortran_CHECK_VERSION_SOURCE
  282. "
  283. program omp_ver
  284. @OpenMP_Fortran_INCLUDE_LINE@
  285. integer, parameter :: zero = ichar('0')
  286. integer, parameter :: ompv = openmp_version
  287. character, dimension(24), parameter :: ompver_str =&
  288. (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 'P', '-',&
  289. 'd', 'a', 't', 'e', '[',&
  290. char(zero + mod(ompv/100000, 10)),&
  291. char(zero + mod(ompv/10000, 10)),&
  292. char(zero + mod(ompv/1000, 10)),&
  293. char(zero + mod(ompv/100, 10)),&
  294. char(zero + mod(ompv/10, 10)),&
  295. char(zero + mod(ompv/1, 10)), ']' /)
  296. print *, ompver_str
  297. end program omp_ver
  298. ")
  299. function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
  300. _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC)
  301. set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin")
  302. string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
  303. try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}"
  304. CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}"
  305. COPY_FILE ${BIN_FILE}
  306. OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT)
  307. if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}})
  308. file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
  309. set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*")
  310. if("${specstr}" MATCHES "${regex_spec_date}")
  311. set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
  312. endif()
  313. else()
  314. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  315. "Detecting ${LANG} OpenMP version failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
  316. endif()
  317. endfunction()
  318. macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG)
  319. set(OpenMP_SPEC_DATE_MAP
  320. # Preview versions
  321. "201611=5.0" # OpenMP 5.0 preview 1
  322. # Combined versions, 2.5 onwards
  323. "201511=4.5"
  324. "201307=4.0"
  325. "201107=3.1"
  326. "200805=3.0"
  327. "200505=2.5"
  328. # C/C++ version 2.0
  329. "200203=2.0"
  330. # Fortran version 2.0
  331. "200011=2.0"
  332. # Fortran version 1.1
  333. "199911=1.1"
  334. # C/C++ version 1.0 (there's no 1.1 for C/C++)
  335. "199810=1.0"
  336. # Fortran version 1.0
  337. "199710=1.0"
  338. )
  339. if(OpenMP_${LANG}_SPEC_DATE)
  340. string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}")
  341. else()
  342. set(_version_match "")
  343. endif()
  344. if(NOT _version_match STREQUAL "")
  345. set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1})
  346. set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2})
  347. set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}")
  348. else()
  349. unset(OpenMP_${LANG}_VERSION_MAJOR)
  350. unset(OpenMP_${LANG}_VERSION_MINOR)
  351. unset(OpenMP_${LANG}_VERSION)
  352. endif()
  353. unset(_version_match)
  354. unset(OpenMP_SPEC_DATE_MAP)
  355. endmacro()
  356. foreach(LANG IN ITEMS C CXX)
  357. if(CMAKE_${LANG}_COMPILER_LOADED)
  358. if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND"
  359. OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
  360. _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK)
  361. endif()
  362. set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
  363. CACHE STRING "${LANG} compiler flags for OpenMP parallelization")
  364. set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
  365. CACHE STRING "${LANG} compiler libraries for OpenMP parallelization")
  366. mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES)
  367. endif()
  368. endforeach()
  369. if(CMAKE_Fortran_COMPILER_LOADED)
  370. if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
  371. OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
  372. OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
  373. set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
  374. _OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
  375. if(OpenMP_Fortran_FLAGS_WORK)
  376. set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "")
  377. endif()
  378. set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
  379. CACHE STRING "Fortran compiler flags for OpenMP parallelization")
  380. set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
  381. CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
  382. mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES)
  383. endif()
  384. if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
  385. OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
  386. OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
  387. set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
  388. _OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
  389. if(OpenMP_Fortran_FLAGS_WORK)
  390. set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "")
  391. endif()
  392. set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
  393. CACHE STRING "Fortran compiler flags for OpenMP parallelization")
  394. set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}"
  395. CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
  396. endif()
  397. if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
  398. set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
  399. else()
  400. set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
  401. endif()
  402. endif()
  403. if(NOT OpenMP_FIND_COMPONENTS)
  404. set(OpenMP_FINDLIST C CXX Fortran)
  405. else()
  406. set(OpenMP_FINDLIST ${OpenMP_FIND_COMPONENTS})
  407. endif()
  408. unset(_OpenMP_MIN_VERSION)
  409. include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
  410. foreach(LANG IN LISTS OpenMP_FINDLIST)
  411. if(CMAKE_${LANG}_COMPILER_LOADED)
  412. if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS)
  413. _OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL)
  414. set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE
  415. INTERNAL "${LANG} compiler's OpenMP specification date")
  416. _OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}")
  417. endif()
  418. set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY})
  419. set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED})
  420. set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION})
  421. set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT})
  422. set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS)
  423. if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
  424. set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES)
  425. else()
  426. foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
  427. list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY)
  428. endforeach()
  429. endif()
  430. find_package_handle_standard_args(OpenMP_${LANG}
  431. REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS}
  432. VERSION_VAR OpenMP_${LANG}_VERSION
  433. )
  434. if(OpenMP_${LANG}_FOUND)
  435. if(DEFINED OpenMP_${LANG}_VERSION)
  436. if(NOT _OpenMP_MIN_VERSION OR _OpenMP_MIN_VERSION VERSION_GREATER OpenMP_${LANG}_VERSION)
  437. set(_OpenMP_MIN_VERSION OpenMP_${LANG}_VERSION)
  438. endif()
  439. endif()
  440. set(OpenMP_${LANG}_LIBRARIES "")
  441. foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
  442. list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}")
  443. endforeach()
  444. if(NOT TARGET OpenMP::OpenMP_${LANG})
  445. add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED)
  446. endif()
  447. if(OpenMP_${LANG}_FLAGS)
  448. separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}")
  449. set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
  450. INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${_OpenMP_${LANG}_OPTIONS}>")
  451. unset(_OpenMP_${LANG}_OPTIONS)
  452. endif()
  453. if(OpenMP_${LANG}_LIBRARIES)
  454. set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
  455. INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}")
  456. endif()
  457. endif()
  458. endif()
  459. endforeach()
  460. unset(_OpenMP_REQ_VARS)
  461. foreach(LANG IN ITEMS C CXX Fortran)
  462. if((NOT OpenMP_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST OpenMP_FIND_COMPONENTS)
  463. list(APPEND _OpenMP_REQ_VARS "OpenMP_${LANG}_FOUND")
  464. endif()
  465. endforeach()
  466. find_package_handle_standard_args(OpenMP
  467. REQUIRED_VARS ${_OpenMP_REQ_VARS}
  468. VERSION_VAR ${_OpenMP_MIN_VERSION}
  469. HANDLE_COMPONENTS)
  470. set(OPENMP_FOUND ${OpenMP_FOUND})
  471. if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND)
  472. if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
  473. set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "")
  474. endif()
  475. if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
  476. set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "")
  477. endif()
  478. endif()
  479. if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED ))
  480. message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled")
  481. endif()
  482. unset(OpenMP_C_CXX_TEST_SOURCE)
  483. unset(OpenMP_Fortran_TEST_SOURCE)
  484. unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE)
  485. unset(OpenMP_Fortran_CHECK_VERSION_SOURCE)
  486. unset(OpenMP_Fortran_INCLUDE_LINE)
  487. cmake_policy(POP)