|
| 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: |
| 5 | +IntelDPCPPConfig |
| 6 | +------- |
| 7 | +
|
| 8 | +DPCPP Library to verify DPCPP/SYCL compatability of CMAKE_CXX_COMPILER |
| 9 | +and passes relevant compiler flags. |
| 10 | +
|
| 11 | +Result Variables |
| 12 | +^^^^^^^^^^^^^^^^ |
| 13 | +
|
| 14 | +This will define the following variables: |
| 15 | +
|
| 16 | +``IntelDPCPP_FOUND`` |
| 17 | + True if the system has the DPCPP library. |
| 18 | +``SYCL_LANGUAGE_VERSION`` |
| 19 | + The SYCL language spec version by Compiler. |
| 20 | +``SYCL_INCLUDE_DIR`` |
| 21 | + Include directories needed to use SYCL. |
| 22 | +``SYCL_IMPLEMENTATION_ID`` |
| 23 | + The SYCL compiler variant. |
| 24 | +``SYCL_FLAGS`` |
| 25 | + SYCL specific flags for the compiler. |
| 26 | +
|
| 27 | +Cache Variables |
| 28 | +^^^^^^^^^^^^^^^ |
| 29 | +
|
| 30 | +The following cache variables may also be set: |
| 31 | +
|
| 32 | +``SYCL_INCLUDE_DIR`` |
| 33 | + The directory containing ``sycl.hpp``. |
| 34 | +``SYCL_LIBRARY_DIR`` |
| 35 | + The path to the SYCL library. |
| 36 | +``SYCL_FLAGS`` |
| 37 | + SYCL specific flags for the compiler. |
| 38 | +``SYCL_LANGUAGE_VERSION`` |
| 39 | + The SYCL language spec version by Compiler. |
| 40 | +
|
| 41 | +
|
| 42 | +.. note:: |
| 43 | +
|
| 44 | + For now, user needs to set -DCMAKE_CXX_COMPILER or environment of |
| 45 | + CXX pointing to SYCL compatible compiler ( eg: icx, clang++, icpx) |
| 46 | +
|
| 47 | + Note: do not set to DPCPP compiler. If set to a Compiler family |
| 48 | + that supports dpcpp ( eg: IntelLLVM) both DPCPP and SYCL |
| 49 | + features are enabled. |
| 50 | +
|
| 51 | + And add this package to user's Cmake config file. |
| 52 | +
|
| 53 | + .. code-block:: cmake |
| 54 | +
|
| 55 | + find_package(IntelDPCPP REQUIRED) |
| 56 | +
|
| 57 | +#]=======================================================================] |
| 58 | + |
| 59 | +include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) |
| 60 | + |
| 61 | +find_package(PkgConfig QUIET) |
| 62 | +if(PKG_CONFIG_FOUND) |
| 63 | + # TODO add dependency package module checks, if any |
| 64 | +endif() |
| 65 | + |
| 66 | + |
| 67 | +# TODO: can't use find_program to override the CMAKE_CXX_COMPILER as |
| 68 | +# Platform/ files are executed, potentially for a different compiler. |
| 69 | +# Safer approach is to make user to define CMAKE_CXX_COMPILER. |
| 70 | + |
| 71 | +string(COMPARE EQUAL "${CMAKE_CXX_COMPILER}" "" nocmplr) |
| 72 | +if(nocmplr) |
| 73 | + set(IntelDPCPP_FOUND False) |
| 74 | + set(SYCL_REASON_FAILURE "SYCL: CMAKE_CXX_COMPILER not set!!") |
| 75 | + set(IntelDPCPP_NOT_FOUND_MESSAGE "${SYCL_REASON_FAILURE}") |
| 76 | +endif() |
| 77 | + |
| 78 | +# Check for known compiler family that supports SYCL |
| 79 | + |
| 80 | +if( NOT "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang" AND |
| 81 | + NOT "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntelLLVM") |
| 82 | + set(IntelDPCPP_FOUND False) |
| 83 | + set(SYCL_REASON_FAILURE "Unsupported compiler family ${CMAKE_CXX_COMPILER_ID} and compiler ${CMAKE_CXX_COMPILER}!!") |
| 84 | + set(IntelDPCPP_NOT_FOUND_MESSAGE "${SYCL_REASON_FAILURE}") |
| 85 | + return() |
| 86 | +endif() |
| 87 | + |
| 88 | +# Assume that CXX Compiler supports SYCL and then test to verify. |
| 89 | +set(SYCL_COMPILER ${CMAKE_CXX_COMPILER}) |
| 90 | + |
| 91 | + |
| 92 | +# Function to write a test case to verify SYCL features. |
| 93 | + |
| 94 | +function(SYCL_FEATURE_TEST_WRITE src) |
| 95 | + |
| 96 | + set(pp_if "#if") |
| 97 | + set(pp_endif "#endif") |
| 98 | + |
| 99 | + set(SYCL_TEST_CONTENT "") |
| 100 | + string(APPEND SYCL_TEST_CONTENT "#include <iostream>\nusing namespace std;\n") |
| 101 | + string(APPEND SYCL_TEST_CONTENT "int main(){\n") |
| 102 | + |
| 103 | + # Feature tests goes here |
| 104 | + |
| 105 | + string(APPEND SYCL_TEST_CONTENT "${pp_if} defined(SYCL_LANGUAGE_VERSION)\n") |
| 106 | + string(APPEND SYCL_TEST_CONTENT "cout << \"SYCL_LANGUAGE_VERSION=\"<<SYCL_LANGUAGE_VERSION<<endl;\n") |
| 107 | + string(APPEND SYCL_TEST_CONTENT "${pp_endif}\n") |
| 108 | + |
| 109 | + string(APPEND SYCL_TEST_CONTENT "return 0;}\n") |
| 110 | + |
| 111 | + file(WRITE ${src} "${SYCL_TEST_CONTENT}") |
| 112 | + |
| 113 | +endfunction() |
| 114 | + |
| 115 | +# Function to Build the feature check test case. |
| 116 | + |
| 117 | +function(SYCL_FEATURE_TEST_BUILD TEST_SRC_FILE TEST_EXE) |
| 118 | + |
| 119 | + # Convert CXX Flag string to list |
| 120 | + set(SYCL_CXX_FLAGS_LIST "${SYCL_CXX_FLAGS}") |
| 121 | + separate_arguments(SYCL_CXX_FLAGS_LIST) |
| 122 | + |
| 123 | + # Spawn a process to build the test case. |
| 124 | + execute_process( |
| 125 | + COMMAND "${SYCL_COMPILER}" |
| 126 | + ${SYCL_CXX_FLAGS_LIST} |
| 127 | + ${TEST_SRC_FILE} |
| 128 | + "-o" |
| 129 | + ${TEST_EXE} |
| 130 | + WORKING_DIRECTORY ${SYCL_TEST_DIR} |
| 131 | + OUTPUT_VARIABLE output ERROR_VARIABLE output |
| 132 | + OUTPUT_FILE ${SYCL_TEST_DIR}/Compile.log |
| 133 | + RESULT_VARIABLE result |
| 134 | + TIMEOUT 20 |
| 135 | + ) |
| 136 | + |
| 137 | + # Verify if test case build properly. |
| 138 | + if(result) |
| 139 | + message("SYCL feature test compile failed!") |
| 140 | + message("compile output is: ${output}") |
| 141 | + endif() |
| 142 | + |
| 143 | + # TODO: what to do if it doesn't build |
| 144 | + |
| 145 | +endfunction() |
| 146 | + |
| 147 | +# Function to run the test case to generate feature info. |
| 148 | + |
| 149 | +function(SYCL_FEATURE_TEST_RUN TEST_EXE) |
| 150 | + |
| 151 | + # Spawn a process to run the test case. |
| 152 | + |
| 153 | + execute_process( |
| 154 | + COMMAND ${TEST_EXE} |
| 155 | + WORKING_DIRECTORY ${SYCL_TEST_DIR} |
| 156 | + OUTPUT_VARIABLE output ERROR_VARIABLE output |
| 157 | + RESULT_VARIABLE result |
| 158 | + TIMEOUT 20 |
| 159 | + ) |
| 160 | + |
| 161 | + # Verify the test execution output. |
| 162 | + if(test_result) |
| 163 | + set(IntelDPCPP_FOUND False) |
| 164 | + set(SYCL_REASON_FAILURE "SYCL: feature test execution failed!!") |
| 165 | + endif() |
| 166 | + # TODO: what iff the result is false.. error or ignore? |
| 167 | + |
| 168 | + set( test_result "${result}" PARENT_SCOPE) |
| 169 | + set( test_output "${output}" PARENT_SCOPE) |
| 170 | + |
| 171 | +endfunction() |
| 172 | + |
| 173 | + |
| 174 | +# Function to extract the information from test execution. |
| 175 | +function(SYCL_FEATURE_TEST_EXTRACT test_output) |
| 176 | + |
| 177 | + string(REGEX REPLACE "\n" ";" test_output_list "${test_output}") |
| 178 | + |
| 179 | + set(SYCL_LANGUAGE_VERSION "") |
| 180 | + foreach(strl ${test_output_list}) |
| 181 | + if(${strl} MATCHES "^SYCL_LANGUAGE_VERSION=([A-Za-z0-9_]+)$") |
| 182 | + string(REGEX REPLACE "^SYCL_LANGUAGE_VERSION=" "" extracted_sycl_lang "${strl}") |
| 183 | + set(SYCL_LANGUAGE_VERSION ${extracted_sycl_lang}) |
| 184 | + endif() |
| 185 | + endforeach() |
| 186 | + |
| 187 | + set(SYCL_LANGUAGE_VERSION "${SYCL_LANGUAGE_VERSION}" PARENT_SCOPE) |
| 188 | +endfunction() |
| 189 | + |
| 190 | +if(SYCL_COMPILER) |
| 191 | + # TODO ensure CMAKE_LINKER and CMAKE_CXX_COMPILER are same/supports SYCL. |
| 192 | + # set(CMAKE_LINKER ${SYCL_COMPILER}) |
| 193 | + |
| 194 | + # use REALPATH to resolve symlinks |
| 195 | + get_filename_component(_REALPATH_SYCL_COMPILER "${SYCL_COMPILER}" REALPATH) |
| 196 | + get_filename_component(SYCL_BIN_DIR "${_REALPATH_SYCL_COMPILER}" DIRECTORY) |
| 197 | + get_filename_component(SYCL_PACKAGE_DIR "${SYCL_BIN_DIR}" DIRECTORY CACHE) |
| 198 | + |
| 199 | + # Find Include path from binary |
| 200 | + find_file(SYCL_INCLUDE_DIR |
| 201 | + NAMES |
| 202 | + include |
| 203 | + HINTS |
| 204 | + ${SYCL_PACKAGE_DIR} ENV SYCL_INCLUDE_DIR_HINT |
| 205 | + NO_DEFAULT_PATH |
| 206 | + ) |
| 207 | + |
| 208 | + # Find Library directory |
| 209 | + find_file(SYCL_LIBRARY_DIR |
| 210 | + NAMES |
| 211 | + lib lib64 |
| 212 | + HINTS |
| 213 | + ${SYCL_PACKAGE_DIR} ENV SYCL_LIBRARY_DIR_HINT |
| 214 | + NO_DEFAULT_PATH |
| 215 | + ) |
| 216 | + |
| 217 | +endif() |
| 218 | + |
| 219 | + |
| 220 | +set(SYCL_FLAGS "") |
| 221 | + |
| 222 | +# Based on Compiler ID, add support for SYCL |
| 223 | +if( "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang" OR |
| 224 | + "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntelLLVM") |
| 225 | + set(SYCL_FLAGS "-fsycl ") |
| 226 | +endif() |
| 227 | + |
| 228 | +# Based on Compiler ID, add support for DPCPP |
| 229 | +if( "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntelLLVM") |
| 230 | + set(SYCL_FLAGS "--dpcpp ${SYCL_FLAGS}") |
| 231 | +endif() |
| 232 | + |
| 233 | +# TODO verify if this is needed |
| 234 | +# Windows: Add Exception handling |
| 235 | +if(WIN32) |
| 236 | + set(SYCL_FLAGS "${SYCL_FLAGS} /EHsc") |
| 237 | +endif() |
| 238 | + |
| 239 | +set(SYCL_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SYCL_FLAGS}") |
| 240 | + |
| 241 | +# And now test the assumptions. |
| 242 | + |
| 243 | +# Create a clean working directory. |
| 244 | +set(SYCL_TEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/TESTSYCL") |
| 245 | +file(REMOVE_RECURSE ${SYCL_TEST_DIR}) |
| 246 | +file(MAKE_DIRECTORY ${SYCL_TEST_DIR}) |
| 247 | + |
| 248 | +# Create the test source file |
| 249 | +set(TEST_SRC_FILE "${SYCL_TEST_DIR}/sycl_features.cpp") |
| 250 | +set(TEST_EXE "${TEST_SRC_FILE}.exe") |
| 251 | +SYCL_FEATURE_TEST_WRITE(${TEST_SRC_FILE}) |
| 252 | + |
| 253 | +# Build the test and create test executable |
| 254 | +SYCL_FEATURE_TEST_BUILD(${TEST_SRC_FILE} ${TEST_EXE}) |
| 255 | + |
| 256 | +# Execute the test to extract information |
| 257 | +SYCL_FEATURE_TEST_RUN(${TEST_EXE}) |
| 258 | + |
| 259 | +# Extract test output for information |
| 260 | +SYCL_FEATURE_TEST_EXTRACT(${test_output}) |
| 261 | + |
| 262 | +# As per specification, all the SYCL compatible compilers should |
| 263 | +# define macro SYCL_LANGUAGE_VERSION |
| 264 | +string(COMPARE EQUAL "${SYCL_LANGUAGE_VERSION}" "" nosycllang) |
| 265 | +if(nosycllang) |
| 266 | + set(IntelDPCPP_FOUND False) |
| 267 | + set(SYCL_REASON_FAILURE "SYCL: It appears that the ${CMAKE_CXX_COMPILER} does not support SYCL") |
| 268 | + set(IntelDPCPP_NOT_FOUND_MESSAGE "${SYCL_REASON_FAILURE}") |
| 269 | +endif() |
| 270 | + |
| 271 | +# Placeholder for identifying various implemenations of SYCL compilers. |
| 272 | +# for now, set to the CMAKE_CXX_COMPILER_ID |
| 273 | +set(SYCL_IMPLEMENTATION_ID "${CMAKE_CXX_COMPILER_ID}") |
| 274 | + |
| 275 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SYCL_FLAGS}") |
| 276 | + |
| 277 | +message(STATUS "Echo from ${CMAKE_CURRENT_SOURCE_DIR}/IntelDPCPPConfig.cmake") |
| 278 | +message(STATUS "The SYCL compiler is ${SYCL_COMPILER}") |
| 279 | +message(STATUS "The SYCL Flags are ${SYCL_FLAGS}") |
| 280 | +message(STATUS "The SYCL Language Version is ${SYCL_LANGUAGE_VERSION}") |
| 281 | + |
| 282 | +find_package_handle_standard_args( |
| 283 | + IntelDPCPP |
| 284 | + FOUND_VAR IntelDPCPP_FOUND |
| 285 | + REQUIRED_VARS SYCL_INCLUDE_DIR SYCL_LIBRARY_DIR SYCL_FLAGS |
| 286 | + VERSION_VAR SYCL_LANGUAGE_VERSION |
| 287 | + REASON_FAILURE_MESSAGE "${SYCL_REASON_FAILURE}") |
| 288 | + |
| 289 | +# Include in Cache |
| 290 | +set(SYCL_LANGUAGE_VERSION "${SYCL_LANGUAGE_VERSION}" CACHE STRING "SYCL Language version") |
| 291 | +set(SYCL_INCLUDE_DIR "${SYCL_INCLUDE_DIR}" CACHE FILEPATH "SYCL Include directory") |
| 292 | +set(SYCL_LIBRARY_DIR "${SYCL_LIBRARY_DIR}" CACHE FILEPATH "SYCL Library Directory") |
| 293 | +set(SYCL_FLAGS "${SYCL_FLAGS}" CACHE STRING "SYCL flags for the compiler") |
0 commit comments