1# Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2# file Copyright.txt or https://cmake.org/licensing for details. 3 4#[=======================================================================[.rst: 5FindOpenMP 6---------- 7 8Finds Open Multi-Processing (OpenMP) support. 9 10This module can be used to detect OpenMP support in a compiler. If 11the compiler supports OpenMP, the flags required to compile with 12OpenMP support are returned in variables for the different languages. 13The variables may be empty if the compiler does not need a special 14flag to support OpenMP. 15 16.. versionadded:: 3.5 17 Clang support. 18 19Variables 20^^^^^^^^^ 21 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. 25 26Depending on the enabled components the following variables will be set: 27 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. 35 36This module will set the following variables per language in your 37project, where ``<lang>`` is one of C, CXX, or Fortran: 38 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. 46 47For linking with OpenMP code written in ``<lang>``, the following 48variables are provided: 49 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>``. 56 57Additionally, the module provides :prop_tgt:`IMPORTED` targets: 58 59``OpenMP::OpenMP_<lang>`` 60 Target for using OpenMP from ``<lang>``. 61 62Specifically for Fortran, the module sets the following variables: 63 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. 68 69The module will also try to provide the OpenMP version variables: 70 71``OpenMP_<lang>_SPEC_DATE`` 72 .. versionadded:: 3.7 73 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. 81 82The specification date is formatted as given in the OpenMP standard: 83``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of 84the OpenMP specification implemented by the ``<lang>`` compiler. 85 86For some compilers, it may be necessary to add a header search path to find 87the relevant OpenMP headers. This location may be language-specific. Where 88this is needed, the module may attempt to find the location, but it can be 89provided directly by setting the ``OpenMP_<lang>_INCLUDE_DIR`` cache variable. 90Note that this variable is an _input_ control to the module. Project code 91should use the ``OpenMP_<lang>_INCLUDE_DIRS`` _output_ variable if it needs 92to know what include directories are needed. 93#]=======================================================================] 94 95cmake_policy(PUSH) 96cmake_policy(SET CMP0012 NEW) # if() recognizes numbers and booleans 97cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced 98cmake_policy(SET CMP0057 NEW) # if IN_LIST 99 100function(_OPENMP_FLAG_CANDIDATES LANG) 101 if(NOT OpenMP_${LANG}_FLAG) 102 unset(OpenMP_FLAG_CANDIDATES) 103 104 set(OMP_FLAG_GNU "-fopenmp") 105 set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp" "-Xclang -fopenmp") 106 set(OMP_FLAG_AppleClang "-Xclang -fopenmp") 107 set(OMP_FLAG_HP "+Oopenmp") 108 if(WIN32) 109 set(OMP_FLAG_Intel "-Qopenmp") 110 elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND 111 "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528") 112 set(OMP_FLAG_Intel "-openmp") 113 else() 114 set(OMP_FLAG_Intel "-qopenmp") 115 endif() 116 if(CMAKE_${LANG}_COMPILER_ID STREQUAL "IntelLLVM" AND 117 "x${CMAKE_${LANG}_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") 118 set(OMP_FLAG_IntelLLVM "-Qiopenmp") 119 else() 120 set(OMP_FLAG_IntelLLVM "-fiopenmp") 121 endif() 122 set(OMP_FLAG_MSVC "-openmp") 123 set(OMP_FLAG_PathScale "-openmp") 124 set(OMP_FLAG_NAG "-openmp") 125 set(OMP_FLAG_Absoft "-openmp") 126 set(OMP_FLAG_NVHPC "-mp") 127 set(OMP_FLAG_PGI "-mp") 128 set(OMP_FLAG_Flang "-fopenmp") 129 set(OMP_FLAG_SunPro "-xopenmp") 130 set(OMP_FLAG_XL "-qsmp=omp") 131 # Cray compiler activate OpenMP with -h omp, which is enabled by default. 132 set(OMP_FLAG_Cray " " "-h omp") 133 set(OMP_FLAG_Fujitsu "-Kopenmp" "-KOMP") 134 set(OMP_FLAG_FujitsuClang "-fopenmp" "-Kopenmp") 135 136 # If we know the correct flags, use those 137 if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}) 138 set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}") 139 # Fall back to reasonable default tries otherwise 140 else() 141 set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ") 142 endif() 143 set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE) 144 else() 145 set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE) 146 endif() 147endfunction() 148 149# sample openmp source code to test 150set(OpenMP_C_CXX_TEST_SOURCE 151" 152#include <omp.h> 153int main(void) { 154#ifdef _OPENMP 155 omp_get_max_threads(); 156 return 0; 157#elif defined(__HIP_DEVICE_COMPILE__) 158 return 0; 159#else 160 breaks_on_purpose 161#endif 162} 163") 164 165# in Fortran, an implementation may provide an omp_lib.h header 166# or omp_lib module, or both (OpenMP standard, section 3.1) 167# Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2) 168# Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code 169# while not actually enabling OpenMP, building code sequentially 170set(OpenMP_Fortran_TEST_SOURCE 171 " 172 program test 173 @OpenMP_Fortran_INCLUDE_LINE@ 174 !$ integer :: n 175 n = omp_get_num_threads() 176 end program test 177 " 178) 179 180function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH) 181 set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP) 182 if("${LANG}" STREQUAL "C") 183 set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c") 184 file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}") 185 elseif("${LANG}" STREQUAL "CXX") 186 set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp") 187 file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}") 188 elseif("${LANG}" STREQUAL "Fortran") 189 set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90") 190 file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}") 191 configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY) 192 endif() 193 set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE) 194endfunction() 195 196include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseImplicitLinkInfo.cmake) 197 198function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) 199 _OPENMP_FLAG_CANDIDATES("${LANG}") 200 _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC) 201 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() 209 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 try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} 217 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" 218 LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} 219 OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT 220 ) 221 222 if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) 223 set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE) 224 225 if(CMAKE_${LANG}_VERBOSE_FLAG) 226 unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES) 227 unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS) 228 unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS) 229 unset(OpenMP_${LANG}_LOG_VAR) 230 231 file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log 232 "Detecting ${LANG} OpenMP compiler ABI info compiled with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n") 233 234 cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}" 235 OpenMP_${LANG}_IMPLICIT_LIBRARIES 236 OpenMP_${LANG}_IMPLICIT_LINK_DIRS 237 OpenMP_${LANG}_IMPLICIT_FWK_DIRS 238 OpenMP_${LANG}_LOG_VAR 239 "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}" 240 ) 241 242 file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log 243 "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n") 244 245 unset(_OPENMP_LIB_NAMES) 246 foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES) 247 get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY) 248 get_filename_component(_OPENMP_IMPLICIT_LIB_NAME "${_OPENMP_IMPLICIT_LIB}" NAME) 249 get_filename_component(_OPENMP_IMPLICIT_LIB_PLAIN "${_OPENMP_IMPLICIT_LIB}" NAME_WE) 250 string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PLAIN_ESC "${_OPENMP_IMPLICIT_LIB_PLAIN}") 251 string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PATH_ESC "${_OPENMP_IMPLICIT_LIB}") 252 if(NOT ( "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES 253 OR "${CMAKE_${LANG}_STANDARD_LIBRARIES}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" 254 OR "${CMAKE_${LANG}_LINK_EXECUTABLE}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" ) ) 255 if(_OPENMP_IMPLICIT_LIB_DIR) 256 set(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY "${_OPENMP_IMPLICIT_LIB}" CACHE FILEPATH 257 "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP") 258 else() 259 find_library(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY 260 NAMES "${_OPENMP_IMPLICIT_LIB_NAME}" 261 DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP" 262 HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS} 263 CMAKE_FIND_ROOT_PATH_BOTH 264 NO_DEFAULT_PATH 265 ) 266 endif() 267 mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY) 268 list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB_PLAIN}) 269 endif() 270 endforeach() 271 set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE) 272 else() 273 # We do not know how to extract implicit OpenMP libraries for this compiler. 274 # Assume that it handles them automatically, e.g. the Intel Compiler on 275 # Windows should put the dependency in its object files. 276 set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE) 277 endif() 278 break() 279 elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang" 280 AND CMAKE_${LANG}_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0") 281 282 # Check for separate OpenMP library on AppleClang 7+ 283 find_library(OpenMP_libomp_LIBRARY 284 NAMES omp gomp iomp5 285 HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES} 286 ) 287 mark_as_advanced(OpenMP_libomp_LIBRARY) 288 289 if(OpenMP_libomp_LIBRARY) 290 # Try without specifying include directory first. We only want to 291 # explicitly add a search path if the header can't be found on the 292 # default header search path already. 293 try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} 294 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" 295 LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} 296 OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT 297 ) 298 if(NOT OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) 299 find_path(OpenMP_${LANG}_INCLUDE_DIR omp.h) 300 mark_as_advanced(OpenMP_${LANG}_INCLUDE_DIR) 301 set(OpenMP_${LANG}_INCLUDE_DIR "${OpenMP_${LANG}_INCLUDE_DIR}" PARENT_SCOPE) 302 if(OpenMP_${LANG}_INCLUDE_DIR) 303 try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} 304 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" 305 "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}" 306 LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} 307 OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT 308 ) 309 endif() 310 endif() 311 if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) 312 set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE) 313 set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE) 314 break() 315 endif() 316 endif() 317 elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Clang" AND WIN32) 318 # Check for separate OpenMP library for Clang on Windows 319 find_library(OpenMP_libomp_LIBRARY 320 NAMES libomp libgomp libiomp5 321 HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES} 322 ) 323 mark_as_advanced(OpenMP_libomp_LIBRARY) 324 if(OpenMP_libomp_LIBRARY) 325 try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} 326 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" 327 LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} 328 OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT 329 ) 330 if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) 331 set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE) 332 set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE) 333 break() 334 endif() 335 endif() 336 else() 337 file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 338 "Detecting ${LANG} OpenMP failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n") 339 endif() 340 set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE) 341 set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE) 342 endforeach() 343 344 unset(OpenMP_VERBOSE_COMPILE_OPTIONS) 345endfunction() 346 347set(OpenMP_C_CXX_CHECK_VERSION_SOURCE 348" 349#include <stdio.h> 350#include <omp.h> 351const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 352 'P', '-', 'd', 'a', 't', 'e', '[', 353 ('0' + ((_OPENMP/100000)%10)), 354 ('0' + ((_OPENMP/10000)%10)), 355 ('0' + ((_OPENMP/1000)%10)), 356 ('0' + ((_OPENMP/100)%10)), 357 ('0' + ((_OPENMP/10)%10)), 358 ('0' + ((_OPENMP/1)%10)), 359 ']', '\\0' }; 360int main(void) 361{ 362 puts(ompver_str); 363 return 0; 364} 365") 366 367set(OpenMP_Fortran_CHECK_VERSION_SOURCE 368" 369 program omp_ver 370 @OpenMP_Fortran_INCLUDE_LINE@ 371 integer, parameter :: zero = ichar('0') 372 integer, parameter :: ompv = openmp_version 373 character, dimension(24), parameter :: ompver_str =& 374 (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 'P', '-',& 375 'd', 'a', 't', 'e', '[',& 376 char(zero + mod(ompv/100000, 10)),& 377 char(zero + mod(ompv/10000, 10)),& 378 char(zero + mod(ompv/1000, 10)),& 379 char(zero + mod(ompv/100, 10)),& 380 char(zero + mod(ompv/10, 10)),& 381 char(zero + mod(ompv/1, 10)), ']' /) 382 print *, ompver_str 383 end program omp_ver 384") 385 386function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE) 387 _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC) 388 389 unset(_includeDirFlags) 390 if(OpenMP_${LANG}_INCLUDE_DIR) 391 set(_includeDirFlags "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}") 392 endif() 393 394 set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin") 395 string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}") 396 try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}" 397 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}" ${_includeDirFlags} 398 COPY_FILE ${BIN_FILE} 399 OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT) 400 401 if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}}) 402 file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date") 403 set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*") 404 if("${specstr}" MATCHES "${regex_spec_date}") 405 set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE) 406 endif() 407 else() 408 file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 409 "Detecting ${LANG} OpenMP version failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n") 410 endif() 411endfunction() 412 413macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG) 414 set(OpenMP_SPEC_DATE_MAP 415 # Preview versions 416 "201611=5.0" # OpenMP 5.0 preview 1 417 # Combined versions, 2.5 onwards 418 "201811=5.0" 419 "201511=4.5" 420 "201307=4.0" 421 "201107=3.1" 422 "200805=3.0" 423 "200505=2.5" 424 # C/C++ version 2.0 425 "200203=2.0" 426 # Fortran version 2.0 427 "200011=2.0" 428 # Fortran version 1.1 429 "199911=1.1" 430 # C/C++ version 1.0 (there's no 1.1 for C/C++) 431 "199810=1.0" 432 # Fortran version 1.0 433 "199710=1.0" 434 ) 435 if(MSVC) 436 list(APPEND OpenMP_SPEC_DATE_MAP "2019=2.0") 437 endif() 438 439 if(OpenMP_${LANG}_SPEC_DATE) 440 string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}") 441 else() 442 set(_version_match "") 443 endif() 444 if(NOT _version_match STREQUAL "") 445 set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1}) 446 set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2}) 447 set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}") 448 else() 449 unset(OpenMP_${LANG}_VERSION_MAJOR) 450 unset(OpenMP_${LANG}_VERSION_MINOR) 451 unset(OpenMP_${LANG}_VERSION) 452 endif() 453 unset(_version_match) 454 unset(OpenMP_SPEC_DATE_MAP) 455endmacro() 456 457foreach(LANG IN ITEMS C CXX) 458 if(CMAKE_${LANG}_COMPILER_LOADED) 459 if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND" 460 OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND") 461 _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK) 462 set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}" 463 CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE) 464 set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}" 465 CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE) 466 mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES) 467 endif() 468 endif() 469endforeach() 470 471if(CMAKE_Fortran_COMPILER_LOADED) 472 if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND" 473 OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND" 474 OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE) 475 set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none") 476 _OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK) 477 if(OpenMP_Fortran_FLAGS_WORK) 478 set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "") 479 endif() 480 481 set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" 482 CACHE STRING "Fortran compiler flags for OpenMP parallelization") 483 set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}" 484 CACHE STRING "Fortran compiler libraries for OpenMP parallelization") 485 mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES) 486 endif() 487 488 if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND" 489 OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND" 490 OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER) 491 set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'") 492 _OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK) 493 if(OpenMP_Fortran_FLAGS_WORK) 494 set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "") 495 endif() 496 497 set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" 498 CACHE STRING "Fortran compiler flags for OpenMP parallelization") 499 500 set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}" 501 CACHE STRING "Fortran compiler libraries for OpenMP parallelization") 502 endif() 503 504 if(OpenMP_Fortran_HAVE_OMPLIB_MODULE) 505 set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none") 506 else() 507 set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'") 508 endif() 509endif() 510 511if(NOT OpenMP_FIND_COMPONENTS) 512 set(OpenMP_FINDLIST C CXX Fortran) 513else() 514 set(OpenMP_FINDLIST ${OpenMP_FIND_COMPONENTS}) 515endif() 516 517unset(_OpenMP_MIN_VERSION) 518 519include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) 520 521foreach(LANG IN LISTS OpenMP_FINDLIST) 522 if(CMAKE_${LANG}_COMPILER_LOADED) 523 if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS) 524 _OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL) 525 set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE 526 INTERNAL "${LANG} compiler's OpenMP specification date") 527 endif() 528 _OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}") 529 530 set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY}) 531 set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED}) 532 set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION}) 533 set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT}) 534 535 set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS) 536 if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND") 537 set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES) 538 else() 539 foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES) 540 list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY) 541 endforeach() 542 endif() 543 544 find_package_handle_standard_args(OpenMP_${LANG} 545 NAME_MISMATCHED 546 REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS} 547 VERSION_VAR OpenMP_${LANG}_VERSION 548 ) 549 550 if(OpenMP_${LANG}_FOUND) 551 if(DEFINED OpenMP_${LANG}_VERSION) 552 if(NOT _OpenMP_MIN_VERSION OR _OpenMP_MIN_VERSION VERSION_GREATER OpenMP_${LANG}_VERSION) 553 set(_OpenMP_MIN_VERSION OpenMP_${LANG}_VERSION) 554 endif() 555 endif() 556 set(OpenMP_${LANG}_LIBRARIES "") 557 foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES) 558 list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}") 559 endforeach() 560 if(OpenMP_${LANG}_INCLUDE_DIR) 561 set(OpenMP_${LANG}_INCLUDE_DIRS ${OpenMP_${LANG}_INCLUDE_DIR}) 562 else() 563 set(OpenMP_${LANG}_INCLUDE_DIRS "") 564 endif() 565 566 if(NOT TARGET OpenMP::OpenMP_${LANG}) 567 add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED) 568 endif() 569 if(OpenMP_${LANG}_FLAGS) 570 separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}") 571 set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY 572 INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${_OpenMP_${LANG}_OPTIONS}>") 573 if(CMAKE_${LANG}_COMPILER_ID STREQUAL "Fujitsu") 574 set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY 575 INTERFACE_LINK_OPTIONS "${OpenMP_${LANG}_FLAGS}") 576 endif() 577 unset(_OpenMP_${LANG}_OPTIONS) 578 endif() 579 if(OpenMP_${LANG}_INCLUDE_DIRS) 580 set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY 581 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${OpenMP_${LANG}_INCLUDE_DIRS}>") 582 endif() 583 if(OpenMP_${LANG}_LIBRARIES) 584 set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY 585 INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}") 586 endif() 587 endif() 588 endif() 589endforeach() 590 591unset(_OpenMP_REQ_VARS) 592foreach(LANG IN ITEMS C CXX Fortran) 593 if((NOT OpenMP_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST OpenMP_FIND_COMPONENTS) 594 list(APPEND _OpenMP_REQ_VARS "OpenMP_${LANG}_FOUND") 595 endif() 596endforeach() 597 598find_package_handle_standard_args(OpenMP 599 REQUIRED_VARS ${_OpenMP_REQ_VARS} 600 VERSION_VAR ${_OpenMP_MIN_VERSION} 601 HANDLE_COMPONENTS) 602 603set(OPENMP_FOUND ${OpenMP_FOUND}) 604 605if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND) 606 if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE) 607 set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "") 608 endif() 609 if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER) 610 set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "") 611 endif() 612endif() 613 614if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED )) 615 message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled") 616endif() 617 618unset(OpenMP_C_CXX_TEST_SOURCE) 619unset(OpenMP_Fortran_TEST_SOURCE) 620unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE) 621unset(OpenMP_Fortran_CHECK_VERSION_SOURCE) 622unset(OpenMP_Fortran_INCLUDE_LINE) 623 624cmake_policy(POP) 625