1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
4 #[=======================================================================[.rst:
10 Detect OpenACC support by the compiler.
12 This module can be used to detect OpenACC support in a compiler.
13 If the compiler supports OpenACC, the flags required to compile with
14 OpenACC support are returned in variables for the different languages.
15 Currently, only NVHPC, PGI, GNU and Cray compilers are supported.
20 .. versionadded:: 3.16
22 The module provides :prop_tgt:`IMPORTED` targets:
24 ``OpenACC::OpenACC_<lang>``
25 Target for using OpenACC from ``<lang>``.
30 The module defines the following variables:
33 .. versionadded:: 3.25
35 Variable indicating that OpenACC flags for at least one languages have been found.
37 This module will set the following variables per language in your
38 project, where ``<lang>`` is one of C, CXX, or Fortran:
40 ``OpenACC_<lang>_FOUND``
41 Variable indicating if OpenACC support for ``<lang>`` was detected.
42 ``OpenACC_<lang>_FLAGS``
43 OpenACC compiler flags for ``<lang>``, separated by spaces.
44 ``OpenACC_<lang>_OPTIONS``
45 .. versionadded:: 3.16
47 OpenACC compiler flags for ``<lang>``, as a list. Suitable for usage
48 with target_compile_options or target_link_options.
50 The module will also try to provide the OpenACC version variables:
52 ``OpenACC_<lang>_SPEC_DATE``
53 Date of the OpenACC specification implemented by the ``<lang>`` compiler.
54 ``OpenACC_<lang>_VERSION_MAJOR``
55 Major version of OpenACC implemented by the ``<lang>`` compiler.
56 ``OpenACC_<lang>_VERSION_MINOR``
57 Minor version of OpenACC implemented by the ``<lang>`` compiler.
58 ``OpenACC_<lang>_VERSION``
59 OpenACC version implemented by the ``<lang>`` compiler.
61 The specification date is formatted as given in the OpenACC standard:
62 ``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of
63 the OpenACC specification implemented by the ``<lang>`` compiler.
68 ``OpenACC_ACCEL_TARGET=<target>``
69 If set, will the correct target accelerator flag set to the <target> will
70 be returned with OpenACC_<lang>_FLAGS.
71 #]=======================================================================]
74 cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
76 set(OpenACC_C_CXX_TEST_SOURCE
87 set(OpenACC_Fortran_TEST_SOURCE
96 set(OpenACC_C_CXX_CHECK_VERSION_SOURCE
99 const char accver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'A',
100 'C', 'C', '-', 'd', 'a', 't', 'e', '[',
101 ('0' + ((_OPENACC/100000)%10)),
102 ('0' + ((_OPENACC/10000)%10)),
103 ('0' + ((_OPENACC/1000)%10)),
104 ('0' + ((_OPENACC/100)%10)),
105 ('0' + ((_OPENACC/10)%10)),
106 ('0' + ((_OPENACC/1)%10)),
114 set(OpenACC_Fortran_CHECK_VERSION_SOURCE
118 integer, parameter :: zero = ichar('0')
119 character, dimension(25), parameter :: accver_str =&
120 (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'A', 'C', 'C', '-',&
121 'd', 'a', 't', 'e', '[',&
122 char(zero + mod(_OPENACC/100000, 10)),&
123 char(zero + mod(_OPENACC/10000, 10)),&
124 char(zero + mod(_OPENACC/1000, 10)),&
125 char(zero + mod(_OPENACC/100, 10)),&
126 char(zero + mod(_OPENACC/10, 10)),&
127 char(zero + mod(_OPENACC/1, 10)), ']' /)
134 macro(_OPENACC_PREPARE_SOURCE LANG CONTENT_ID NAME_PREFIX FULLNAME_VAR CONTENT_VAR)
135 if("${LANG}" STREQUAL "C")
136 set(${FULLNAME_VAR} "${NAME_PREFIX}.c")
137 set(${CONTENT_VAR} "${OpenACC_C_CXX_${CONTENT_ID}}")
138 elseif("${LANG}" STREQUAL "CXX")
139 set(${FULLNAME_VAR} "${NAME_PREFIX}.cpp")
140 set(${CONTENT_VAR} "${OpenACC_C_CXX_${CONTENT_ID}}")
141 elseif("${LANG}" STREQUAL "Fortran")
142 set(${FULLNAME_VAR} "${NAME_PREFIX}.F90")
143 set(${CONTENT_VAR} "${OpenACC_Fortran_${CONTENT_ID}}")
148 function(_OPENACC_GET_FLAGS_CANDIDATE LANG FLAG_VAR)
149 set(ACC_FLAG_NVHPC "-acc")
150 set(ACC_FLAG_PGI "-acc")
151 set(ACC_FLAG_GNU "-fopenacc")
152 set(ACC_FLAG_Cray "-h acc")
153 set(ACC_FLAG_Clang "-fopenacc")
155 if(DEFINED ACC_FLAG_${CMAKE_${LANG}_COMPILER_ID})
156 set("${FLAG_VAR}" "${ACC_FLAG_${CMAKE_${LANG}_COMPILER_ID}}" PARENT_SCOPE)
158 # Fall back to a few common flags.
159 set("${FLAG_VAR}" ${ACC_FLAG_GNU} ${ACC_FLAG_PGI})
165 function(_OPENACC_GET_ACCEL_TARGET_FLAG LANG TARGET FLAG_VAR)
166 # Find target accelerator flags.
167 set(ACC_TARGET_FLAG_NVHPC "-ta")
168 set(ACC_TARGET_FLAG_PGI "-ta")
169 if(DEFINED ACC_TARGET_FLAG_${CMAKE_${LANG}_COMPILER_ID})
170 set("${FLAG_VAR}" "${ACC_TARGET_FLAG_${CMAKE_${LANG}_COMPILER_ID}}=${TARGET}" PARENT_SCOPE)
175 function(_OPENACC_GET_VERBOSE_FLAG LANG FLAG_VAR)
176 # Find compiler's verbose flag for OpenACC.
177 set(ACC_VERBOSE_FLAG_NVHPC "-Minfo=accel")
178 set(ACC_VERBOSE_FLAG_PGI "-Minfo=accel")
179 if(DEFINED ACC_VERBOSE_FLAG_${CMAKE_${LANG}_COMPILER_ID})
180 set("${FLAG_VAR}" "${ACC_VERBOSE_FLAG_${CMAKE_${LANG}_COMPILER_ID}}" PARENT_SCOPE)
185 function(_OPENACC_GET_FLAGS LANG FLAG_VAR)
186 set(FLAG_CANDIDATES "")
187 _OPENACC_GET_FLAGS_CANDIDATE("${LANG}" FLAG_CANDIDATES)
188 _OPENACC_PREPARE_SOURCE("${LANG}" TEST_SOURCE OpenACCTryFlag
189 _OPENACC_TEST_SRC_NAME _OPENACC_TEST_SRC_CONTENT)
191 foreach(FLAG IN LISTS FLAG_CANDIDATES)
192 try_compile(OpenACC_FLAG_TEST_RESULT
193 SOURCE_FROM_VAR "${_OPENACC_TEST_SRC_NAME}" _OPENACC_TEST_SRC_CONTENT
194 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${FLAG}"
195 OUTPUT_VARIABLE OpenACC_TRY_COMPILE_OUTPUT
197 if(OpenACC_FLAG_TEST_RESULT)
198 set("${FLAG_VAR}" "${FLAG}")
199 if(DEFINED OpenACC_ACCEL_TARGET)
200 _OPENACC_GET_ACCEL_TARGET_FLAG("${LANG}" "${OpenACC_ACCEL_TARGET}" TARGET_FLAG)
201 string(APPEND "${FLAG_VAR}" " ${TARGET_FLAG}")
204 if(CMAKE_VERBOSE_MAKEFILE)
205 # -Minfo=accel prints out OpenACC's messages on optimizations.
206 _OPENACC_GET_VERBOSE_FLAG("${LANG}" OpenACC_VERBOSE_FLAG)
207 string(APPEND "${FLAG_VAR}" " ${OpenACC_VERBOSE_FLAG}")
209 set("${FLAG_VAR}" "${${FLAG_VAR}}" PARENT_SCOPE)
217 function(_OPENACC_GET_SPEC_DATE LANG SPEC_DATE)
218 _OPENACC_PREPARE_SOURCE(${LANG} CHECK_VERSION_SOURCE OpenACCCheckVersion
219 _OPENACC_TEST_SRC_NAME _OPENACC_TEST_SRC_CONTENT)
221 set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenACC/accver_${LANG}.bin")
222 try_compile(OpenACC_SPECTEST_${LANG}
223 SOURCE_FROM_VAR "${_OPENACC_TEST_SRC_NAME}" _OPENACC_TEST_SRC_CONTENT
224 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenACC_${LANG}_FLAGS}"
225 COPY_FILE "${BIN_FILE}"
226 OUTPUT_VARIABLE OUTPUT)
228 if(${OpenACC_SPECTEST_${LANG}})
229 file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenACC-date")
230 set(regex_spec_date ".*INFO:OpenACC-date\\[0*([^]]*)\\].*")
231 if("${specstr}" MATCHES "${regex_spec_date}")
232 set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
238 macro(_OPENACC_SET_VERSION_BY_SPEC_DATE LANG)
239 set(OpenACC_SPEC_DATE_MAP
240 # Combined versions, 2.5 onwards
242 # 2013 08 is the corrected version.
248 string(REGEX MATCHALL "${OpenACC_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenACC_SPEC_DATE_MAP}")
249 if(NOT _version_match STREQUAL "")
250 set(OpenACC_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1})
251 set(OpenACC_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2})
252 set(OpenACC_${LANG}_VERSION "${OpenACC_${LANG}_VERSION_MAJOR}.${OpenACC_${LANG}_VERSION_MINOR}")
254 unset(OpenACC_${LANG}_VERSION_MAJOR)
255 unset(OpenACC_${LANG}_VERSION_MINOR)
256 unset(OpenACC_${LANG}_VERSION)
258 unset(_version_match)
259 unset(OpenACC_SPEC_DATE_MAP)
263 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
264 foreach (LANG IN ITEMS C CXX Fortran)
265 if(CMAKE_${LANG}_COMPILER_LOADED)
266 set(OpenACC_${LANG}_FIND_QUIETLY ${OpenACC_FIND_QUIETLY})
267 set(OpenACC_${LANG}_FIND_REQUIRED ${OpenACC_FIND_REQUIRED})
268 set(OpenACC_${LANG}_FIND_VERSION ${OpenACC_FIND_VERSION})
269 set(OpenACC_${LANG}_FIND_VERSION_EXACT ${OpenACC_FIND_VERSION_EXACT})
271 if(NOT DEFINED OpenACC_${LANG}_FLAGS)
272 _OPENACC_GET_FLAGS("${LANG}" OpenACC_${LANG}_FLAGS)
274 if(NOT DEFINED OpenACC_${LANG}_OPTIONS)
275 separate_arguments(OpenACC_${LANG}_OPTIONS NATIVE_COMMAND "${OpenACC_${LANG}_FLAGS}")
277 _OPENACC_GET_SPEC_DATE("${LANG}" OpenACC_${LANG}_SPEC_DATE)
278 _OPENACC_SET_VERSION_BY_SPEC_DATE("${LANG}")
280 find_package_handle_standard_args(OpenACC_${LANG}
282 REQUIRED_VARS OpenACC_${LANG}_FLAGS
283 VERSION_VAR OpenACC_${LANG}_VERSION
285 if(OpenACC_${LANG}_FOUND)
286 set(OpenACC_FOUND TRUE)
291 foreach (LANG IN ITEMS C CXX Fortran)
292 if(OpenACC_${LANG}_FOUND AND NOT TARGET OpenACC::OpenACC_${LANG})
293 add_library(OpenACC::OpenACC_${LANG} INTERFACE IMPORTED)
295 if(OpenACC_${LANG}_LIBRARIES)
296 set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY
297 INTERFACE_LINK_LIBRARIES "${OpenACC_${LANG}_LIBRARIES}")
299 if(OpenACC_${LANG}_FLAGS)
300 set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY
301 INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:SHELL:${OpenACC_${LANG}_FLAGS}>")
302 set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY
303 INTERFACE_LINK_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:SHELL:${OpenACC_${LANG}_FLAGS}>")
304 unset(_OpenACC_${LANG}_OPTIONS)
308 unset(OpenACC_C_CXX_TEST_SOURCE)
309 unset(OpenACC_Fortran_TEST_SOURCE)
310 unset(OpenACC_C_CXX_CHECK_VERSION_SOURCE)
311 unset(OpenACC_Fortran_CHECK_VERSION_SOURCE)