FindOpenMP.cmake 22 KB

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