Merge topic 'cxx-checks-tolerate-unused-arguments'
[kiteware-cmake.git] / Modules / FindOpenACC.cmake
blobd5d26a1f12dc16f5a6e654ec364a67265b01b3e3
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:
5 FindOpenACC
6 -----------
8 .. versionadded:: 3.10
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.
17 Imported Targets
18 ^^^^^^^^^^^^^^^^
20 .. versionadded:: 3.16
22 The module provides :prop_tgt:`IMPORTED` targets:
24 ``OpenACC::OpenACC_<lang>``
25   Target for using OpenACC from ``<lang>``.
27 Variables
28 ^^^^^^^^^
30 The module defines the following variables:
32 ``OpenACC_FOUND``
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.
65 Input Variables
66 ^^^^^^^^^^^^^^^
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 cmake_policy(PUSH)
74 cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
76 set(OpenACC_C_CXX_TEST_SOURCE
78 int main(void){
79 #ifdef _OPENACC
80   return 0;
81 #else
82   breaks_on_purpose
83 #endif
87 set(OpenACC_Fortran_TEST_SOURCE
89 program test
90 #ifndef _OPENACC
91   breaks_on_purpose
92 #endif
93 endprogram test
96 set(OpenACC_C_CXX_CHECK_VERSION_SOURCE
98 #include <stdio.h>
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)),
107                             ']', '\\0' };
108 int main(void)
110   puts(accver_str);
111   return 0;
114 set(OpenACC_Fortran_CHECK_VERSION_SOURCE
116       program acc_ver
117       implicit none
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)), ']' /)
128       print *, accver_str
129       end program acc_ver
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}}")
144   endif()
145 endmacro()
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)
157   else()
158     # Fall back to a few common flags.
159     set("${FLAG_VAR}" ${ACC_FLAG_GNU} ${ACC_FLAG_PGI})
160   endif()
162 endfunction()
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)
171   endif()
172 endfunction()
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)
181   endif()
182 endfunction()
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
196     )
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}")
202       endif()
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}")
208       endif()
209       set("${FLAG_VAR}" "${${FLAG_VAR}}" PARENT_SCOPE)
210       break()
211     endif()
212   endforeach()
214 endfunction()
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)
233     endif()
234   endif()
235 endfunction()
238 macro(_OPENACC_SET_VERSION_BY_SPEC_DATE LANG)
239   set(OpenACC_SPEC_DATE_MAP
240     # Combined versions, 2.5 onwards
241     "201510=2.5"
242     # 2013 08 is the corrected version.
243     "201308=2.0"
244     "201306=2.0"
245     "201111=1.0"
246   )
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}")
253   else()
254     unset(OpenACC_${LANG}_VERSION_MAJOR)
255     unset(OpenACC_${LANG}_VERSION_MINOR)
256     unset(OpenACC_${LANG}_VERSION)
257   endif()
258   unset(_version_match)
259   unset(OpenACC_SPEC_DATE_MAP)
260 endmacro()
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)
273     endif()
274     if(NOT DEFINED OpenACC_${LANG}_OPTIONS)
275       separate_arguments(OpenACC_${LANG}_OPTIONS NATIVE_COMMAND "${OpenACC_${LANG}_FLAGS}")
276     endif()
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}
281       NAME_MISMATCHED
282       REQUIRED_VARS OpenACC_${LANG}_FLAGS
283       VERSION_VAR OpenACC_${LANG}_VERSION
284     )
285     if(OpenACC_${LANG}_FOUND)
286       set(OpenACC_FOUND TRUE)
287     endif()
288   endif()
289 endforeach()
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)
294   endif()
295   if(OpenACC_${LANG}_LIBRARIES)
296     set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY
297       INTERFACE_LINK_LIBRARIES "${OpenACC_${LANG}_LIBRARIES}")
298   endif()
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)
305   endif()
306 endforeach()
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)
313 cmake_policy(POP)