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: 5FindOpenACC 6----------- 7 8.. versionadded:: 3.10 9 10Detect OpenACC support by the compiler. 11 12This module can be used to detect OpenACC support in a compiler. 13If the compiler supports OpenACC, the flags required to compile with 14OpenACC support are returned in variables for the different languages. 15Currently, only NVHPC, PGI, GNU and Cray compilers are supported. 16 17Imported Targets 18^^^^^^^^^^^^^^^^ 19 20.. versionadded:: 3.16 21 22The module provides :prop_tgt:`IMPORTED` targets: 23 24``OpenACC::OpenACC_<lang>`` 25 Target for using OpenACC from ``<lang>``. 26 27Variables 28^^^^^^^^^ 29 30This module will set the following variables per language in your 31project, where ``<lang>`` is one of C, CXX, or Fortran: 32 33``OpenACC_<lang>_FOUND`` 34 Variable indicating if OpenACC support for ``<lang>`` was detected. 35``OpenACC_<lang>_FLAGS`` 36 OpenACC compiler flags for ``<lang>``, separated by spaces. 37``OpenACC_<lang>_OPTIONS`` 38 .. versionadded:: 3.16 39 40 OpenACC compiler flags for ``<lang>``, as a list. Suitable for usage 41 with target_compile_options or target_link_options. 42 43The module will also try to provide the OpenACC version variables: 44 45``OpenACC_<lang>_SPEC_DATE`` 46 Date of the OpenACC specification implemented by the ``<lang>`` compiler. 47``OpenACC_<lang>_VERSION_MAJOR`` 48 Major version of OpenACC implemented by the ``<lang>`` compiler. 49``OpenACC_<lang>_VERSION_MINOR`` 50 Minor version of OpenACC implemented by the ``<lang>`` compiler. 51``OpenACC_<lang>_VERSION`` 52 OpenACC version implemented by the ``<lang>`` compiler. 53 54The specification date is formatted as given in the OpenACC standard: 55``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of 56the OpenACC specification implemented by the ``<lang>`` compiler. 57 58Input Variables 59^^^^^^^^^^^^^^^ 60 61``OpenACC_ACCEL_TARGET=<target>`` 62If set, will the correct target accelerator flag set to the <target> will 63be returned with OpenACC_<lang>_FLAGS. 64#]=======================================================================] 65 66set(OpenACC_C_CXX_TEST_SOURCE 67" 68int main(){ 69#ifdef _OPENACC 70 return 0; 71#else 72 breaks_on_purpose 73#endif 74} 75" 76) 77set(OpenACC_Fortran_TEST_SOURCE 78" 79program test 80#ifndef _OPENACC 81 breaks_on_purpose 82#endif 83endprogram test 84" 85) 86set(OpenACC_C_CXX_CHECK_VERSION_SOURCE 87" 88#include <stdio.h> 89const char accver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'A', 90 'C', 'C', '-', 'd', 'a', 't', 'e', '[', 91 ('0' + ((_OPENACC/100000)%10)), 92 ('0' + ((_OPENACC/10000)%10)), 93 ('0' + ((_OPENACC/1000)%10)), 94 ('0' + ((_OPENACC/100)%10)), 95 ('0' + ((_OPENACC/10)%10)), 96 ('0' + ((_OPENACC/1)%10)), 97 ']', '\\0' }; 98int main() 99{ 100 puts(accver_str); 101 return 0; 102} 103") 104set(OpenACC_Fortran_CHECK_VERSION_SOURCE 105" 106 program acc_ver 107 implicit none 108 integer, parameter :: zero = ichar('0') 109 character, dimension(25), parameter :: accver_str =& 110 (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'A', 'C', 'C', '-',& 111 'd', 'a', 't', 'e', '[',& 112 char(zero + mod(_OPENACC/100000, 10)),& 113 char(zero + mod(_OPENACC/10000, 10)),& 114 char(zero + mod(_OPENACC/1000, 10)),& 115 char(zero + mod(_OPENACC/100, 10)),& 116 char(zero + mod(_OPENACC/10, 10)),& 117 char(zero + mod(_OPENACC/1, 10)), ']' /) 118 print *, accver_str 119 end program acc_ver 120" 121) 122 123 124function(_OPENACC_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH) 125 set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenACC) 126 if("${LANG}" STREQUAL "C") 127 set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c") 128 file(WRITE "${SRC_FILE}" "${OpenACC_C_CXX_${SRC_FILE_CONTENT_VAR}}") 129 elseif("${LANG}" STREQUAL "CXX") 130 set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp") 131 file(WRITE "${SRC_FILE}" "${OpenACC_C_CXX_${SRC_FILE_CONTENT_VAR}}") 132 elseif("${LANG}" STREQUAL "Fortran") 133 set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.F90") 134 file(WRITE "${SRC_FILE}_in" "${OpenACC_Fortran_${SRC_FILE_CONTENT_VAR}}") 135 configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY) 136 endif() 137 set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE) 138endfunction() 139 140 141function(_OPENACC_GET_FLAGS_CANDIDATE LANG FLAG_VAR) 142 set(ACC_FLAG_NVHPC "-acc") 143 set(ACC_FLAG_PGI "-acc") 144 set(ACC_FLAG_GNU "-fopenacc") 145 set(ACC_FLAG_Cray "-h acc") 146 147 if(DEFINED ACC_FLAG_${CMAKE_${LANG}_COMPILER_ID}) 148 set("${FLAG_VAR}" "${ACC_FLAG_${CMAKE_${LANG}_COMPILER_ID}}" PARENT_SCOPE) 149 else() 150 # Fall back to a few common flags. 151 set("${FLAG_VAR}" ${ACC_FLAG_GNU} ${ACC_FLAG_PGI}) 152 endif() 153 154endfunction() 155 156 157function(_OPENACC_GET_ACCEL_TARGET_FLAG LANG TARGET FLAG_VAR) 158 # Find target accelerator flags. 159 set(ACC_TARGET_FLAG_NVHPC "-ta") 160 set(ACC_TARGET_FLAG_PGI "-ta") 161 if(DEFINED ACC_TARGET_FLAG_${CMAKE_${LANG}_COMPILER_ID}) 162 set("${FLAG_VAR}" "${ACC_TARGET_FLAG_${CMAKE_${LANG}_COMPILER_ID}}=${TARGET}" PARENT_SCOPE) 163 endif() 164endfunction() 165 166 167function(_OPENACC_GET_VERBOSE_FLAG LANG FLAG_VAR) 168 # Find compiler's verbose flag for OpenACC. 169 set(ACC_VERBOSE_FLAG_NVHPC "-Minfo=accel") 170 set(ACC_VERBOSE_FLAG_PGI "-Minfo=accel") 171 if(DEFINED ACC_VERBOSE_FLAG_${CMAKE_${LANG}_COMPILER_ID}) 172 set("${FLAG_VAR}" "${ACC_VERBOSE_FLAG_${CMAKE_${LANG}_COMPILER_ID}}" PARENT_SCOPE) 173 endif() 174endfunction() 175 176 177function(_OPENACC_GET_FLAGS LANG FLAG_VAR) 178 set(FLAG_CANDIDATES "") 179 _OPENACC_GET_FLAGS_CANDIDATE("${LANG}" FLAG_CANDIDATES) 180 _OPENACC_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenACCTryFlag _OPENACC_TEST_SRC) 181 182 foreach(FLAG IN LISTS FLAG_CANDIDATES) 183 try_compile(OpenACC_FLAG_TEST_RESULT ${CMAKE_BINARY_DIR} ${_OPENACC_TEST_SRC} 184 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${FLAG}" 185 OUTPUT_VARIABLE OpenACC_TRY_COMPILE_OUTPUT 186 ) 187 if(OpenACC_FLAG_TEST_RESULT) 188 set("${FLAG_VAR}" "${FLAG}") 189 if(DEFINED OpenACC_ACCEL_TARGET) 190 _OPENACC_GET_ACCEL_TARGET_FLAG("${LANG}" "${OpenACC_ACCEL_TARGET}" TARGET_FLAG) 191 string(APPEND "${FLAG_VAR}" " ${TARGET_FLAG}") 192 endif() 193 194 if(CMAKE_VERBOSE_MAKEFILE) 195 # -Minfo=accel prints out OpenACC's messages on optimizations. 196 _OPENACC_GET_VERBOSE_FLAG("${LANG}" OpenACC_VERBOSE_FLAG) 197 string(APPEND "${FLAG_VAR}" " ${OpenACC_VERBOSE_FLAG}") 198 endif() 199 set("${FLAG_VAR}" "${${FLAG_VAR}}" PARENT_SCOPE) 200 break() 201 endif() 202 endforeach() 203 204endfunction() 205 206 207function(_OPENACC_GET_SPEC_DATE LANG SPEC_DATE) 208 _OPENACC_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenACCCheckVersion _OPENACC_TEST_SRC) 209 210 set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenACC/accver_${LANG}.bin") 211 try_compile(OpenACC_SPECTEST_${LANG} "${CMAKE_BINARY_DIR}" "${_OPENACC_TEST_SRC}" 212 CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenACC_${LANG}_FLAGS}" 213 COPY_FILE ${BIN_FILE} 214 OUTPUT_VARIABLE OUTPUT) 215 216 if(${OpenACC_SPECTEST_${LANG}}) 217 file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenACC-date") 218 set(regex_spec_date ".*INFO:OpenACC-date\\[0*([^]]*)\\].*") 219 if("${specstr}" MATCHES "${regex_spec_date}") 220 set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE) 221 endif() 222 endif() 223endfunction() 224 225 226macro(_OPENACC_SET_VERSION_BY_SPEC_DATE LANG) 227 set(OpenACC_SPEC_DATE_MAP 228 # Combined versions, 2.5 onwards 229 "201510=2.5" 230 # 2013 08 is the corrected version. 231 "201308=2.0" 232 "201306=2.0" 233 "201111=1.0" 234 ) 235 236 string(REGEX MATCHALL "${OpenACC_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenACC_SPEC_DATE_MAP}") 237 if(NOT _version_match STREQUAL "") 238 set(OpenACC_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1}) 239 set(OpenACC_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2}) 240 set(OpenACC_${LANG}_VERSION "${OpenACC_${LANG}_VERSION_MAJOR}.${OpenACC_${LANG}_VERSION_MINOR}") 241 else() 242 unset(OpenACC_${LANG}_VERSION_MAJOR) 243 unset(OpenACC_${LANG}_VERSION_MINOR) 244 unset(OpenACC_${LANG}_VERSION) 245 endif() 246 unset(_version_match) 247 unset(OpenACC_SPEC_DATE_MAP) 248endmacro() 249 250 251include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) 252foreach (LANG IN ITEMS C CXX Fortran) 253 if(CMAKE_${LANG}_COMPILER_LOADED) 254 set(OpenACC_${LANG}_FIND_QUIETLY ${OpenACC_FIND_QUIETLY}) 255 set(OpenACC_${LANG}_FIND_REQUIRED ${OpenACC_FIND_REQUIRED}) 256 set(OpenACC_${LANG}_FIND_VERSION ${OpenACC_FIND_VERSION}) 257 set(OpenACC_${LANG}_FIND_VERSION_EXACT ${OpenACC_FIND_VERSION_EXACT}) 258 259 if(NOT DEFINED OpenACC_${LANG}_FLAGS) 260 _OPENACC_GET_FLAGS("${LANG}" OpenACC_${LANG}_FLAGS) 261 endif() 262 if(NOT DEFINED OpenACC_${LANG}_OPTIONS) 263 separate_arguments(OpenACC_${LANG}_OPTIONS NATIVE_COMMAND "${OpenACC_${LANG}_FLAGS}") 264 endif() 265 _OPENACC_GET_SPEC_DATE("${LANG}" OpenACC_${LANG}_SPEC_DATE) 266 _OPENACC_SET_VERSION_BY_SPEC_DATE("${LANG}") 267 268 find_package_handle_standard_args(OpenACC_${LANG} 269 NAME_MISMATCHED 270 REQUIRED_VARS OpenACC_${LANG}_FLAGS 271 VERSION_VAR OpenACC_${LANG}_VERSION 272 ) 273 endif() 274endforeach() 275 276foreach (LANG IN ITEMS C CXX Fortran) 277 if(OpenACC_${LANG}_FOUND AND NOT TARGET OpenACC::OpenACC_${LANG}) 278 add_library(OpenACC::OpenACC_${LANG} INTERFACE IMPORTED) 279 endif() 280 if(OpenACC_${LANG}_LIBRARIES) 281 set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY 282 INTERFACE_LINK_LIBRARIES "${OpenACC_${LANG}_LIBRARIES}") 283 endif() 284 if(OpenACC_${LANG}_FLAGS) 285 set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY 286 INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${OpenACC_${LANG}_OPTIONS}>") 287 set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY 288 INTERFACE_LINK_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${OpenACC_${LANG}_OPTIONS}>") 289 unset(_OpenACC_${LANG}_OPTIONS) 290 endif() 291endforeach() 292 293unset(OpenACC_C_CXX_TEST_SOURCE) 294unset(OpenACC_Fortran_TEST_SOURCE) 295unset(OpenACC_C_CXX_CHECK_VERSION_SOURCE) 296unset(OpenACC_Fortran_CHECK_VERSION_SOURCE) 297