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 #]=======================================================================]
73 set(OpenACC_C_CXX_TEST_SOURCE
84 set(OpenACC_Fortran_TEST_SOURCE
93 set(OpenACC_C_CXX_CHECK_VERSION_SOURCE
96 const char accver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'A',
97 'C', 'C', '-', 'd', 'a', 't', 'e', '[',
98 ('0' + ((_OPENACC/100000)%10)),
99 ('0' + ((_OPENACC/10000)%10)),
100 ('0' + ((_OPENACC/1000)%10)),
101 ('0' + ((_OPENACC/100)%10)),
102 ('0' + ((_OPENACC/10)%10)),
103 ('0' + ((_OPENACC/1)%10)),
111 set(OpenACC_Fortran_CHECK_VERSION_SOURCE
115 integer, parameter :: zero = ichar('0')
116 character, dimension(25), parameter :: accver_str =&
117 (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'A', 'C', 'C', '-',&
118 'd', 'a', 't', 'e', '[',&
119 char(zero + mod(_OPENACC/100000, 10)),&
120 char(zero + mod(_OPENACC/10000, 10)),&
121 char(zero + mod(_OPENACC/1000, 10)),&
122 char(zero + mod(_OPENACC/100, 10)),&
123 char(zero + mod(_OPENACC/10, 10)),&
124 char(zero + mod(_OPENACC/1, 10)), ']' /)
131 macro(_OPENACC_PREPARE_SOURCE LANG CONTENT_ID NAME_PREFIX FULLNAME_VAR CONTENT_VAR)
132 if("${LANG}" STREQUAL "C")
133 set(${FULLNAME_VAR} "${NAME_PREFIX}.c")
134 set(${CONTENT_VAR} "${OpenACC_C_CXX_${CONTENT_ID}}")
135 elseif("${LANG}" STREQUAL "CXX")
136 set(${FULLNAME_VAR} "${NAME_PREFIX}.cpp")
137 set(${CONTENT_VAR} "${OpenACC_C_CXX_${CONTENT_ID}}")
138 elseif("${LANG}" STREQUAL "Fortran")
139 set(${FULLNAME_VAR} "${NAME_PREFIX}.F90")
140 set(${CONTENT_VAR} "${OpenACC_Fortran_${CONTENT_ID}}")
145 function(_OPENACC_GET_FLAGS_CANDIDATE LANG FLAG_VAR)
146 set(ACC_FLAG_NVHPC "-acc")
147 set(ACC_FLAG_PGI "-acc")
148 set(ACC_FLAG_GNU "-fopenacc")
149 set(ACC_FLAG_Cray "-h acc")
151 if(DEFINED ACC_FLAG_${CMAKE_${LANG}_COMPILER_ID})
152 set("${FLAG_VAR}" "${ACC_FLAG_${CMAKE_${LANG}_COMPILER_ID}}" PARENT_SCOPE)
154 # Fall back to a few common flags.
155 set("${FLAG_VAR}" ${ACC_FLAG_GNU} ${ACC_FLAG_PGI})
161 function(_OPENACC_GET_ACCEL_TARGET_FLAG LANG TARGET FLAG_VAR)
162 # Find target accelerator flags.
163 set(ACC_TARGET_FLAG_NVHPC "-ta")
164 set(ACC_TARGET_FLAG_PGI "-ta")
165 if(DEFINED ACC_TARGET_FLAG_${CMAKE_${LANG}_COMPILER_ID})
166 set("${FLAG_VAR}" "${ACC_TARGET_FLAG_${CMAKE_${LANG}_COMPILER_ID}}=${TARGET}" PARENT_SCOPE)
171 function(_OPENACC_GET_VERBOSE_FLAG LANG FLAG_VAR)
172 # Find compiler's verbose flag for OpenACC.
173 set(ACC_VERBOSE_FLAG_NVHPC "-Minfo=accel")
174 set(ACC_VERBOSE_FLAG_PGI "-Minfo=accel")
175 if(DEFINED ACC_VERBOSE_FLAG_${CMAKE_${LANG}_COMPILER_ID})
176 set("${FLAG_VAR}" "${ACC_VERBOSE_FLAG_${CMAKE_${LANG}_COMPILER_ID}}" PARENT_SCOPE)
181 function(_OPENACC_GET_FLAGS LANG FLAG_VAR)
182 set(FLAG_CANDIDATES "")
183 _OPENACC_GET_FLAGS_CANDIDATE("${LANG}" FLAG_CANDIDATES)
184 _OPENACC_PREPARE_SOURCE("${LANG}" TEST_SOURCE OpenACCTryFlag
185 _OPENACC_TEST_SRC_NAME _OPENACC_TEST_SRC_CONTENT)
187 foreach(FLAG IN LISTS FLAG_CANDIDATES)
188 try_compile(OpenACC_FLAG_TEST_RESULT
189 SOURCE_FROM_VAR "${_OPENACC_TEST_SRC_NAME}" _OPENACC_TEST_SRC_CONTENT
190 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${FLAG}"
191 OUTPUT_VARIABLE OpenACC_TRY_COMPILE_OUTPUT
193 if(OpenACC_FLAG_TEST_RESULT)
194 set("${FLAG_VAR}" "${FLAG}")
195 if(DEFINED OpenACC_ACCEL_TARGET)
196 _OPENACC_GET_ACCEL_TARGET_FLAG("${LANG}" "${OpenACC_ACCEL_TARGET}" TARGET_FLAG)
197 string(APPEND "${FLAG_VAR}" " ${TARGET_FLAG}")
200 if(CMAKE_VERBOSE_MAKEFILE)
201 # -Minfo=accel prints out OpenACC's messages on optimizations.
202 _OPENACC_GET_VERBOSE_FLAG("${LANG}" OpenACC_VERBOSE_FLAG)
203 string(APPEND "${FLAG_VAR}" " ${OpenACC_VERBOSE_FLAG}")
205 set("${FLAG_VAR}" "${${FLAG_VAR}}" PARENT_SCOPE)
213 function(_OPENACC_GET_SPEC_DATE LANG SPEC_DATE)
214 _OPENACC_PREPARE_SOURCE(${LANG} CHECK_VERSION_SOURCE OpenACCCheckVersion
215 _OPENACC_TEST_SRC_NAME _OPENACC_TEST_SRC_CONTENT)
217 set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenACC/accver_${LANG}.bin")
218 try_compile(OpenACC_SPECTEST_${LANG}
219 SOURCE_FROM_VAR "${_OPENACC_TEST_SRC_NAME}" _OPENACC_TEST_SRC_CONTENT
220 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenACC_${LANG}_FLAGS}"
221 COPY_FILE "${BIN_FILE}"
222 OUTPUT_VARIABLE OUTPUT)
224 if(${OpenACC_SPECTEST_${LANG}})
225 file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenACC-date")
226 set(regex_spec_date ".*INFO:OpenACC-date\\[0*([^]]*)\\].*")
227 if("${specstr}" MATCHES "${regex_spec_date}")
228 set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
234 macro(_OPENACC_SET_VERSION_BY_SPEC_DATE LANG)
235 set(OpenACC_SPEC_DATE_MAP
236 # Combined versions, 2.5 onwards
238 # 2013 08 is the corrected version.
244 string(REGEX MATCHALL "${OpenACC_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenACC_SPEC_DATE_MAP}")
245 if(NOT _version_match STREQUAL "")
246 set(OpenACC_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1})
247 set(OpenACC_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2})
248 set(OpenACC_${LANG}_VERSION "${OpenACC_${LANG}_VERSION_MAJOR}.${OpenACC_${LANG}_VERSION_MINOR}")
250 unset(OpenACC_${LANG}_VERSION_MAJOR)
251 unset(OpenACC_${LANG}_VERSION_MINOR)
252 unset(OpenACC_${LANG}_VERSION)
254 unset(_version_match)
255 unset(OpenACC_SPEC_DATE_MAP)
259 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
260 foreach (LANG IN ITEMS C CXX Fortran)
261 if(CMAKE_${LANG}_COMPILER_LOADED)
262 set(OpenACC_${LANG}_FIND_QUIETLY ${OpenACC_FIND_QUIETLY})
263 set(OpenACC_${LANG}_FIND_REQUIRED ${OpenACC_FIND_REQUIRED})
264 set(OpenACC_${LANG}_FIND_VERSION ${OpenACC_FIND_VERSION})
265 set(OpenACC_${LANG}_FIND_VERSION_EXACT ${OpenACC_FIND_VERSION_EXACT})
267 if(NOT DEFINED OpenACC_${LANG}_FLAGS)
268 _OPENACC_GET_FLAGS("${LANG}" OpenACC_${LANG}_FLAGS)
270 if(NOT DEFINED OpenACC_${LANG}_OPTIONS)
271 separate_arguments(OpenACC_${LANG}_OPTIONS NATIVE_COMMAND "${OpenACC_${LANG}_FLAGS}")
273 _OPENACC_GET_SPEC_DATE("${LANG}" OpenACC_${LANG}_SPEC_DATE)
274 _OPENACC_SET_VERSION_BY_SPEC_DATE("${LANG}")
276 find_package_handle_standard_args(OpenACC_${LANG}
278 REQUIRED_VARS OpenACC_${LANG}_FLAGS
279 VERSION_VAR OpenACC_${LANG}_VERSION
281 if(OpenACC_${LANG}_FOUND)
282 set(OpenACC_FOUND TRUE)
287 foreach (LANG IN ITEMS C CXX Fortran)
288 if(OpenACC_${LANG}_FOUND AND NOT TARGET OpenACC::OpenACC_${LANG})
289 add_library(OpenACC::OpenACC_${LANG} INTERFACE IMPORTED)
291 if(OpenACC_${LANG}_LIBRARIES)
292 set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY
293 INTERFACE_LINK_LIBRARIES "${OpenACC_${LANG}_LIBRARIES}")
295 if(OpenACC_${LANG}_FLAGS)
296 set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY
297 INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${OpenACC_${LANG}_OPTIONS}>")
298 set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY
299 INTERFACE_LINK_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${OpenACC_${LANG}_OPTIONS}>")
300 unset(_OpenACC_${LANG}_OPTIONS)
304 unset(OpenACC_C_CXX_TEST_SOURCE)
305 unset(OpenACC_Fortran_TEST_SOURCE)
306 unset(OpenACC_C_CXX_CHECK_VERSION_SOURCE)
307 unset(OpenACC_Fortran_CHECK_VERSION_SOURCE)