FindOpenMP.cmake 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  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 CMP0054 NEW) # if() quoted variables not dereferenced
  77. cmake_policy(SET CMP0057 NEW) # if IN_LIST
  78. function(_OPENMP_FLAG_CANDIDATES LANG)
  79. if(NOT OpenMP_${LANG}_FLAG)
  80. unset(OpenMP_FLAG_CANDIDATES)
  81. set(OMP_FLAG_GNU "-fopenmp")
  82. set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp")
  83. set(OMP_FLAG_HP "+Oopenmp")
  84. if(WIN32)
  85. set(OMP_FLAG_Intel "-Qopenmp")
  86. elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND
  87. "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528")
  88. set(OMP_FLAG_Intel "-openmp")
  89. else()
  90. set(OMP_FLAG_Intel "-qopenmp")
  91. endif()
  92. set(OMP_FLAG_MIPSpro "-mp")
  93. set(OMP_FLAG_MSVC "-openmp")
  94. set(OMP_FLAG_PathScale "-openmp")
  95. set(OMP_FLAG_NAG "-openmp")
  96. set(OMP_FLAG_Absoft "-openmp")
  97. set(OMP_FLAG_PGI "-mp")
  98. set(OMP_FLAG_Flang "-fopenmp")
  99. set(OMP_FLAG_SunPro "-xopenmp")
  100. set(OMP_FLAG_XL "-qsmp=omp")
  101. # Cray compiler activate OpenMP with -h omp, which is enabled by default.
  102. set(OMP_FLAG_Cray " " "-h omp")
  103. # If we know the correct flags, use those
  104. if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID})
  105. set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}")
  106. # Fall back to reasonable default tries otherwise
  107. else()
  108. set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ")
  109. endif()
  110. set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE)
  111. else()
  112. set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE)
  113. endif()
  114. endfunction()
  115. # sample openmp source code to test
  116. set(OpenMP_C_CXX_TEST_SOURCE
  117. "
  118. #include <omp.h>
  119. int main() {
  120. #ifndef _OPENMP
  121. breaks_on_purpose
  122. #endif
  123. }
  124. ")
  125. # in Fortran, an implementation may provide an omp_lib.h header
  126. # or omp_lib module, or both (OpenMP standard, section 3.1)
  127. # Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2)
  128. # Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code
  129. # while not actually enabling OpenMP, building code sequentially
  130. set(OpenMP_Fortran_TEST_SOURCE
  131. "
  132. program test
  133. @OpenMP_Fortran_INCLUDE_LINE@
  134. !$ integer :: n
  135. n = omp_get_num_threads()
  136. end program test
  137. "
  138. )
  139. function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH)
  140. set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP)
  141. if("${LANG}" STREQUAL "C")
  142. set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c")
  143. file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
  144. elseif("${LANG}" STREQUAL "CXX")
  145. set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp")
  146. file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
  147. elseif("${LANG}" STREQUAL "Fortran")
  148. set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90")
  149. file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}")
  150. configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY)
  151. endif()
  152. set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
  153. endfunction()
  154. include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
  155. function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
  156. _OPENMP_FLAG_CANDIDATES("${LANG}")
  157. _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC)
  158. unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
  159. separate_arguments(OpenMP_VERBOSE_OPTIONS NATIVE_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}")
  160. foreach(_VERBOSE_OPTION IN LISTS OpenMP_VERBOSE_OPTIONS)
  161. if(NOT _VERBOSE_OPTION MATCHES "^-Wl,")
  162. list(APPEND OpenMP_VERBOSE_COMPILE_OPTIONS ${_VERBOSE_OPTION})
  163. endif()
  164. endforeach()
  165. foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES)
  166. set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}")
  167. if(OpenMP_VERBOSE_COMPILE_OPTIONS)
  168. string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}")
  169. endif()
  170. string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
  171. try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
  172. CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
  173. LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG}
  174. OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
  175. )
  176. if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
  177. set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
  178. if(CMAKE_${LANG}_VERBOSE_FLAG)
  179. unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES)
  180. unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS)
  181. unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS)
  182. unset(OpenMP_${LANG}_LOG_VAR)
  183. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  184. "Detecting ${LANG} OpenMP compiler ABI info compiled with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
  185. cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}"
  186. OpenMP_${LANG}_IMPLICIT_LIBRARIES
  187. OpenMP_${LANG}_IMPLICIT_LINK_DIRS
  188. OpenMP_${LANG}_IMPLICIT_FWK_DIRS
  189. OpenMP_${LANG}_LOG_VAR
  190. "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}"
  191. )
  192. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  193. "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n")
  194. unset(_OPENMP_LIB_NAMES)
  195. foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES)
  196. if(NOT "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES)
  197. find_library(OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY
  198. NAMES "${_OPENMP_IMPLICIT_LIB}"
  199. HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
  200. )
  201. mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY)
  202. list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB})
  203. endif()
  204. endforeach()
  205. set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE)
  206. else()
  207. # The Intel compiler on windows has no verbose mode, so we need to treat it explicitly
  208. if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Intel" AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
  209. set("${OPENMP_LIB_NAMES_VAR}" "libiomp5md" PARENT_SCOPE)
  210. find_library(OpenMP_libiomp5md_LIBRARY
  211. NAMES "libiomp5md"
  212. HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
  213. )
  214. mark_as_advanced(OpenMP_libiomp5md_LIBRARY)
  215. else()
  216. set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
  217. endif()
  218. endif()
  219. break()
  220. endif()
  221. set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
  222. set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
  223. endforeach()
  224. unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
  225. endfunction()
  226. set(OpenMP_C_CXX_CHECK_VERSION_SOURCE
  227. "
  228. #include <stdio.h>
  229. #include <omp.h>
  230. const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M',
  231. 'P', '-', 'd', 'a', 't', 'e', '[',
  232. ('0' + ((_OPENMP/100000)%10)),
  233. ('0' + ((_OPENMP/10000)%10)),
  234. ('0' + ((_OPENMP/1000)%10)),
  235. ('0' + ((_OPENMP/100)%10)),
  236. ('0' + ((_OPENMP/10)%10)),
  237. ('0' + ((_OPENMP/1)%10)),
  238. ']', '\\0' };
  239. int main()
  240. {
  241. puts(ompver_str);
  242. }
  243. ")
  244. set(OpenMP_Fortran_CHECK_VERSION_SOURCE
  245. "
  246. program omp_ver
  247. @OpenMP_Fortran_INCLUDE_LINE@
  248. integer, parameter :: zero = ichar('0')
  249. integer, parameter :: ompv = openmp_version
  250. character, dimension(24), parameter :: ompver_str =&
  251. (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 'P', '-',&
  252. 'd', 'a', 't', 'e', '[',&
  253. char(zero + mod(ompv/100000, 10)),&
  254. char(zero + mod(ompv/10000, 10)),&
  255. char(zero + mod(ompv/1000, 10)),&
  256. char(zero + mod(ompv/100, 10)),&
  257. char(zero + mod(ompv/10, 10)),&
  258. char(zero + mod(ompv/1, 10)), ']' /)
  259. print *, ompver_str
  260. end program omp_ver
  261. ")
  262. function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
  263. _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC)
  264. set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin")
  265. string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
  266. try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}"
  267. CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}"
  268. COPY_FILE ${BIN_FILE})
  269. if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}})
  270. file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
  271. set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*")
  272. if("${specstr}" MATCHES "${regex_spec_date}")
  273. set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
  274. endif()
  275. endif()
  276. endfunction()
  277. macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG)
  278. set(OpenMP_SPEC_DATE_MAP
  279. # Preview versions
  280. "201611=5.0" # OpenMP 5.0 preview 1
  281. # Combined versions, 2.5 onwards
  282. "201511=4.5"
  283. "201307=4.0"
  284. "201107=3.1"
  285. "200805=3.0"
  286. "200505=2.5"
  287. # C/C++ version 2.0
  288. "200203=2.0"
  289. # Fortran version 2.0
  290. "200011=2.0"
  291. # Fortran version 1.1
  292. "199911=1.1"
  293. # C/C++ version 1.0 (there's no 1.1 for C/C++)
  294. "199810=1.0"
  295. # Fortran version 1.0
  296. "199710=1.0"
  297. )
  298. if(OpenMP_${LANG}_SPEC_DATE)
  299. string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}")
  300. else()
  301. set(_version_match "")
  302. endif()
  303. if(NOT _version_match STREQUAL "")
  304. set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1})
  305. set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2})
  306. set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}")
  307. else()
  308. unset(OpenMP_${LANG}_VERSION_MAJOR)
  309. unset(OpenMP_${LANG}_VERSION_MINOR)
  310. unset(OpenMP_${LANG}_VERSION)
  311. endif()
  312. unset(_version_match)
  313. unset(OpenMP_SPEC_DATE_MAP)
  314. endmacro()
  315. foreach(LANG IN ITEMS C CXX)
  316. if(CMAKE_${LANG}_COMPILER_LOADED)
  317. if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND"
  318. OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
  319. _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK)
  320. endif()
  321. set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
  322. CACHE STRING "${LANG} compiler flags for OpenMP parallelization")
  323. set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
  324. CACHE STRING "${LANG} compiler libraries for OpenMP parallelization")
  325. mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES)
  326. endif()
  327. endforeach()
  328. if(CMAKE_Fortran_COMPILER_LOADED)
  329. if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
  330. OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
  331. OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
  332. set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
  333. _OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
  334. if(OpenMP_Fortran_FLAGS_WORK)
  335. set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "")
  336. endif()
  337. set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
  338. CACHE STRING "Fortran compiler flags for OpenMP parallelization")
  339. set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
  340. CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
  341. mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES)
  342. endif()
  343. if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
  344. OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
  345. OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
  346. set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
  347. _OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
  348. if(OpenMP_Fortran_FLAGS_WORK)
  349. set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "")
  350. endif()
  351. set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
  352. CACHE STRING "Fortran compiler flags for OpenMP parallelization")
  353. set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}"
  354. CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
  355. endif()
  356. if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
  357. set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
  358. else()
  359. set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
  360. endif()
  361. endif()
  362. if(NOT OpenMP_FIND_COMPONENTS)
  363. set(OpenMP_FINDLIST C CXX Fortran)
  364. else()
  365. set(OpenMP_FINDLIST ${OpenMP_FIND_COMPONENTS})
  366. endif()
  367. unset(_OpenMP_MIN_VERSION)
  368. foreach(LANG IN LISTS OpenMP_FINDLIST)
  369. if(CMAKE_${LANG}_COMPILER_LOADED)
  370. if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS)
  371. _OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL)
  372. set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE
  373. INTERNAL "${LANG} compiler's OpenMP specification date")
  374. _OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}")
  375. endif()
  376. include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
  377. set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY})
  378. set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED})
  379. set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION})
  380. set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT})
  381. set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS)
  382. if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
  383. set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES)
  384. else()
  385. foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
  386. list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY)
  387. endforeach()
  388. endif()
  389. find_package_handle_standard_args(OpenMP_${LANG}
  390. REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS}
  391. VERSION_VAR OpenMP_${LANG}_VERSION
  392. )
  393. if(OpenMP_${LANG}_FOUND)
  394. if(DEFINED OpenMP_${LANG}_VERSION)
  395. if(NOT _OpenMP_MIN_VERSION OR _OpenMP_MIN_VERSION VERSION_GREATER OpenMP_${LANG}_VERSION)
  396. set(_OpenMP_MIN_VERSION OpenMP_${LANG}_VERSION)
  397. endif()
  398. endif()
  399. set(OpenMP_${LANG}_LIBRARIES "")
  400. foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
  401. list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}")
  402. endforeach()
  403. if(NOT TARGET OpenMP::OpenMP_${LANG})
  404. add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED)
  405. endif()
  406. if(OpenMP_${LANG}_FLAGS)
  407. separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}")
  408. set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
  409. INTERFACE_COMPILE_OPTIONS "${_OpenMP_${LANG}_OPTIONS}")
  410. unset(_OpenMP_${LANG}_OPTIONS)
  411. endif()
  412. if(OpenMP_${LANG}_LIBRARIES)
  413. set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
  414. INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}")
  415. endif()
  416. endif()
  417. endif()
  418. endforeach()
  419. unset(_OpenMP_REQ_VARS)
  420. foreach(LANG IN ITEMS C CXX Fortran)
  421. if((NOT OpenMP_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST OpenMP_FIND_COMPONENTS)
  422. list(APPEND _OpenMP_REQ_VARS "OpenMP_${LANG}_FOUND")
  423. endif()
  424. endforeach()
  425. find_package_handle_standard_args(OpenMP
  426. REQUIRED_VARS ${_OpenMP_REQ_VARS}
  427. VERSION_VAR ${_OpenMP_MIN_VERSION}
  428. HANDLE_COMPONENTS)
  429. set(OPENMP_FOUND ${OpenMP_FOUND})
  430. if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND)
  431. if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
  432. set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "")
  433. endif()
  434. if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
  435. set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "")
  436. endif()
  437. endif()
  438. if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED ))
  439. message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled")
  440. endif()
  441. unset(OpenMP_C_CXX_TEST_SOURCE)
  442. unset(OpenMP_Fortran_TEST_SOURCE)
  443. unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE)
  444. unset(OpenMP_Fortran_CHECK_VERSION_SOURCE)
  445. unset(OpenMP_Fortran_INCLUDE_LINE)
  446. cmake_policy(POP)