1#.rst: 2# FindComputeCpp 3#--------------- 4# 5# Copyright 2016-2018 Codeplay Software Ltd. 6# 7# Licensed under the Apache License, Version 2.0 (the "License"); 8# you may not use these files except in compliance with the License. 9# You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# 14# Unless required by applicable law or agreed to in writing, software 15# distributed under the License is distributed on an "AS IS" BASIS, 16# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17# See the License for the specific language governing permissions and 18# limitations under the License. 19 20######################### 21# FindComputeCpp.cmake 22######################### 23# 24# Tools for finding and building with ComputeCpp. 25# 26# User must define ComputeCpp_DIR pointing to the ComputeCpp 27# installation. 28# 29# Latest version of this file can be found at: 30# https://github.com/codeplaysoftware/computecpp-sdk 31 32cmake_minimum_required(VERSION 3.4.3) 33include(FindPackageHandleStandardArgs) 34include(ComputeCppIRMap) 35 36set(COMPUTECPP_USER_FLAGS "" CACHE STRING "User flags for compute++") 37separate_arguments(COMPUTECPP_USER_FLAGS) 38mark_as_advanced(COMPUTECPP_USER_FLAGS) 39 40set(COMPUTECPP_BITCODE "spir64" CACHE STRING 41 "Bitcode type to use as SYCL target in compute++") 42mark_as_advanced(COMPUTECPP_BITCODE) 43 44include(CMakeFindDependencyMacro) 45find_dependency(OpenCL REQUIRED) 46 47# Find ComputeCpp package 48 49if(DEFINED ComputeCpp_DIR) 50 set(computecpp_find_hint ${ComputeCpp_DIR}) 51elseif(DEFINED ENV{COMPUTECPP_DIR}) 52 set(computecpp_find_hint $ENV{COMPUTECPP_DIR}) 53endif() 54 55# Used for running executables on the host 56set(computecpp_host_find_hint ${computecpp_find_hint}) 57 58if(CMAKE_CROSSCOMPILING) 59 # ComputeCpp_HOST_DIR is used to find executables that are run on the host 60 if(DEFINED ComputeCpp_HOST_DIR) 61 set(computecpp_host_find_hint ${ComputeCpp_HOST_DIR}) 62 elseif(DEFINED ENV{COMPUTECPP_HOST_DIR}) 63 set(computecpp_host_find_hint $ENV{COMPUTECPP_HOST_DIR}) 64 endif() 65endif() 66 67find_program(ComputeCpp_DEVICE_COMPILER_EXECUTABLE compute++ 68 HINTS ${computecpp_host_find_hint} 69 PATH_SUFFIXES bin 70 NO_SYSTEM_ENVIRONMENT_PATH) 71 72find_program(ComputeCpp_INFO_EXECUTABLE computecpp_info 73 HINTS ${computecpp_host_find_hint} 74 PATH_SUFFIXES bin 75 NO_SYSTEM_ENVIRONMENT_PATH) 76 77find_library(COMPUTECPP_RUNTIME_LIBRARY 78 NAMES ComputeCpp ComputeCpp_vs2015 79 HINTS ${computecpp_find_hint} 80 PATH_SUFFIXES lib 81 DOC "ComputeCpp Runtime Library") 82 83find_library(COMPUTECPP_RUNTIME_LIBRARY_DEBUG 84 NAMES ComputeCpp_d ComputeCpp ComputeCpp_vs2015_d 85 HINTS ${computecpp_find_hint} 86 PATH_SUFFIXES lib 87 DOC "ComputeCpp Debug Runtime Library") 88 89find_path(ComputeCpp_INCLUDE_DIRS 90 NAMES "CL/sycl.hpp" 91 HINTS ${computecpp_find_hint}/include 92 DOC "The ComputeCpp include directory") 93get_filename_component(ComputeCpp_INCLUDE_DIRS ${ComputeCpp_INCLUDE_DIRS} ABSOLUTE) 94 95get_filename_component(computecpp_canonical_root_dir "${ComputeCpp_INCLUDE_DIRS}/.." ABSOLUTE) 96set(ComputeCpp_ROOT_DIR "${computecpp_canonical_root_dir}" CACHE PATH 97 "The root of the ComputeCpp install") 98 99if(NOT ComputeCpp_INFO_EXECUTABLE) 100 message(WARNING "Can't find computecpp_info - check ComputeCpp_DIR") 101else() 102 execute_process(COMMAND ${ComputeCpp_INFO_EXECUTABLE} "--dump-version" 103 OUTPUT_VARIABLE ComputeCpp_VERSION 104 RESULT_VARIABLE ComputeCpp_INFO_EXECUTABLE_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE) 105 if(NOT ComputeCpp_INFO_EXECUTABLE_RESULT EQUAL "0") 106 message(WARNING "Package version - Error obtaining version!") 107 endif() 108 109 execute_process(COMMAND ${ComputeCpp_INFO_EXECUTABLE} "--dump-is-supported" 110 OUTPUT_VARIABLE COMPUTECPP_PLATFORM_IS_SUPPORTED 111 RESULT_VARIABLE ComputeCpp_INFO_EXECUTABLE_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE) 112 if(NOT ComputeCpp_INFO_EXECUTABLE_RESULT EQUAL "0") 113 message(WARNING "platform - Error checking platform support!") 114 else() 115 mark_as_advanced(COMPUTECPP_PLATFORM_IS_SUPPORTED) 116 if (COMPUTECPP_PLATFORM_IS_SUPPORTED) 117 message(STATUS "platform - your system can support ComputeCpp") 118 else() 119 message(STATUS "platform - your system is not officially supported") 120 endif() 121 endif() 122endif() 123 124find_package_handle_standard_args(ComputeCpp 125 REQUIRED_VARS ComputeCpp_ROOT_DIR 126 ComputeCpp_DEVICE_COMPILER_EXECUTABLE 127 ComputeCpp_INFO_EXECUTABLE 128 COMPUTECPP_RUNTIME_LIBRARY 129 COMPUTECPP_RUNTIME_LIBRARY_DEBUG 130 ComputeCpp_INCLUDE_DIRS 131 VERSION_VAR ComputeCpp_VERSION) 132mark_as_advanced(ComputeCpp_ROOT_DIR 133 ComputeCpp_DEVICE_COMPILER_EXECUTABLE 134 ComputeCpp_INFO_EXECUTABLE 135 COMPUTECPP_RUNTIME_LIBRARY 136 COMPUTECPP_RUNTIME_LIBRARY_DEBUG 137 ComputeCpp_INCLUDE_DIRS 138 ComputeCpp_VERSION) 139 140if(NOT ComputeCpp_FOUND) 141 return() 142endif() 143 144list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS -O2 -mllvm -inline-threshold=1000 -intelspirmetadata) 145mark_as_advanced(COMPUTECPP_DEVICE_COMPILER_FLAGS) 146 147if(CMAKE_CROSSCOMPILING) 148 if(NOT COMPUTECPP_DONT_USE_TOOLCHAIN) 149 list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS --gcc-toolchain=${COMPUTECPP_TOOLCHAIN_DIR}) 150 endif() 151 list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS --sysroot=${COMPUTECPP_SYSROOT_DIR}) 152 list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS -target ${COMPUTECPP_TARGET_TRIPLE}) 153endif() 154 155list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS -sycl-target ${COMPUTECPP_BITCODE}) 156message(STATUS "compute++ flags - ${COMPUTECPP_DEVICE_COMPILER_FLAGS}") 157 158include(ComputeCppCompilerChecks) 159 160if(NOT TARGET OpenCL::OpenCL) 161 add_library(OpenCL::OpenCL UNKNOWN IMPORTED) 162 set_target_properties(OpenCL::OpenCL PROPERTIES 163 IMPORTED_LOCATION "${OpenCL_LIBRARIES}" 164 INTERFACE_INCLUDE_DIRECTORIES "${OpenCL_INCLUDE_DIRS}" 165 ) 166endif() 167 168if(NOT TARGET ComputeCpp::ComputeCpp) 169 add_library(ComputeCpp::ComputeCpp UNKNOWN IMPORTED) 170 set_target_properties(ComputeCpp::ComputeCpp PROPERTIES 171 IMPORTED_LOCATION_DEBUG "${COMPUTECPP_RUNTIME_LIBRARY_DEBUG}" 172 IMPORTED_LOCATION_RELWITHDEBINFO "${COMPUTECPP_RUNTIME_LIBRARY}" 173 IMPORTED_LOCATION "${COMPUTECPP_RUNTIME_LIBRARY}" 174 INTERFACE_INCLUDE_DIRECTORIES "${ComputeCpp_INCLUDE_DIRS}" 175 INTERFACE_LINK_LIBRARIES "OpenCL::OpenCL" 176 ) 177endif() 178 179# This property allows targets to specify that their sources should be 180# compiled with the integration header included after the user's 181# sources, not before (e.g. when an enum is used in a kernel name, this 182# is not technically valid SYCL code but can work with ComputeCpp) 183define_property( 184 TARGET PROPERTY COMPUTECPP_INCLUDE_AFTER 185 BRIEF_DOCS "Include integration header after user source" 186 FULL_DOCS "Changes compiler arguments such that the source file is 187 actually the integration header, and the .cpp file is included on 188 the command line so that it is seen by the compiler first. Enables 189 non-standards-conformant SYCL code to compile with ComputeCpp." 190) 191define_property( 192 TARGET PROPERTY INTERFACE_COMPUTECPP_FLAGS 193 BRIEF_DOCS "Interface compile flags to provide compute++" 194 FULL_DOCS "Set additional compile flags to pass to compute++ when compiling 195 any target which links to this one." 196) 197define_property( 198 SOURCE PROPERTY COMPUTECPP_SOURCE_FLAGS 199 BRIEF_DOCS "Source file compile flags for compute++" 200 FULL_DOCS "Set additional compile flags for compiling the SYCL integration 201 header for the given source file." 202) 203 204#################### 205# __build_ir 206#################### 207# 208# Adds a custom target for running compute++ and adding a dependency for the 209# resulting integration header and kernel binary. 210# 211# TARGET : Name of the target. 212# SOURCE : Source file to be compiled. 213# COUNTER : Counter included in name of custom target. Different counter 214# values prevent duplicated names of custom target when source files with 215# the same name, but located in different directories, are used for the 216# same target. 217# 218function(__build_ir) 219 set(options) 220 set(one_value_args 221 TARGET 222 SOURCE 223 COUNTER 224 ) 225 set(multi_value_args) 226 cmake_parse_arguments(SDK_BUILD_IR 227 "${options}" 228 "${one_value_args}" 229 "${multi_value_args}" 230 ${ARGN} 231 ) 232 get_filename_component(sourceFileName ${SDK_BUILD_IR_SOURCE} NAME) 233 234 # Set the path to the integration header. 235 # The .sycl filename must depend on the target so that different targets 236 # using the same source file will be generated with a different rule. 237 set(baseSyclName ${CMAKE_CURRENT_BINARY_DIR}/${SDK_BUILD_IR_TARGET}_${sourceFileName}) 238 set(outputSyclFile ${baseSyclName}.sycl) 239 set(outputDeviceFile ${baseSyclName}.${IR_MAP_${COMPUTECPP_BITCODE}}) 240 set(depFileName ${baseSyclName}.sycl.d) 241 242 set(include_directories "$<TARGET_PROPERTY:${SDK_BUILD_IR_TARGET},INCLUDE_DIRECTORIES>") 243 set(compile_definitions "$<TARGET_PROPERTY:${SDK_BUILD_IR_TARGET},COMPILE_DEFINITIONS>") 244 set(generated_include_directories 245 $<$<BOOL:${include_directories}>:-I\"$<JOIN:${include_directories},\"\t-I\">\">) 246 set(generated_compile_definitions 247 $<$<BOOL:${compile_definitions}>:-D$<JOIN:${compile_definitions},\t-D>>) 248 249 # Obtain language standard of the file 250 set(device_compiler_cxx_standard) 251 get_target_property(targetCxxStandard ${SDK_BUILD_IR_TARGET} CXX_STANDARD) 252 if (targetCxxStandard MATCHES 17) 253 set(device_compiler_cxx_standard "-std=c++1z") 254 elseif (targetCxxStandard MATCHES 14) 255 set(device_compiler_cxx_standard "-std=c++14") 256 elseif (targetCxxStandard MATCHES 11) 257 set(device_compiler_cxx_standard "-std=c++11") 258 elseif (targetCxxStandard MATCHES 98) 259 message(FATAL_ERROR "SYCL applications cannot be compiled using C++98") 260 else () 261 set(device_compiler_cxx_standard "") 262 endif() 263 264 get_property(source_compile_flags 265 SOURCE ${SDK_BUILD_IR_SOURCE} 266 PROPERTY COMPUTECPP_SOURCE_FLAGS 267 ) 268 separate_arguments(source_compile_flags) 269 if(source_compile_flags) 270 list(APPEND computecpp_source_flags ${source_compile_flags}) 271 endif() 272 273 list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS 274 ${device_compiler_cxx_standard} 275 ${COMPUTECPP_USER_FLAGS} 276 ${computecpp_source_flags} 277 ) 278 279 set(ir_dependencies ${SDK_BUILD_IR_SOURCE}) 280 get_target_property(target_libraries ${SDK_BUILD_IR_TARGET} LINK_LIBRARIES) 281 if(target_libraries) 282 foreach(library ${target_libraries}) 283 if(TARGET ${library}) 284 list(APPEND ir_dependencies ${library}) 285 endif() 286 endforeach() 287 endif() 288 289 # Depfile support was only added in CMake 3.7 290 # CMake throws an error if it is unsupported by the generator (i. e. not ninja) 291 if((NOT CMAKE_VERSION VERSION_LESS 3.7.0) AND 292 CMAKE_GENERATOR MATCHES "Ninja") 293 file(RELATIVE_PATH relOutputFile ${CMAKE_BINARY_DIR} ${outputDeviceFile}) 294 set(generate_depfile -MMD -MF ${depFileName} -MT ${relOutputFile}) 295 set(enable_depfile DEPFILE ${depFileName}) 296 endif() 297 298 # Add custom command for running compute++ 299 add_custom_command( 300 OUTPUT ${outputDeviceFile} ${outputSyclFile} 301 COMMAND ${ComputeCpp_DEVICE_COMPILER_EXECUTABLE} 302 ${COMPUTECPP_DEVICE_COMPILER_FLAGS} 303 ${generated_include_directories} 304 ${generated_compile_definitions} 305 -sycl-ih ${outputSyclFile} 306 -o ${outputDeviceFile} 307 -c ${SDK_BUILD_IR_SOURCE} 308 ${generate_depfile} 309 DEPENDS ${ir_dependencies} 310 IMPLICIT_DEPENDS CXX ${SDK_BUILD_IR_SOURCE} 311 ${enable_depfile} 312 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 313 COMMENT "Building ComputeCpp integration header file ${outputSyclFile}") 314 315 # Name: (user-defined name)_(source file)_(counter)_ih 316 set(headerTargetName 317 ${SDK_BUILD_IR_TARGET}_${sourceFileName}_${SDK_BUILD_IR_COUNTER}_ih) 318 319 if(NOT MSVC) 320 # Add a custom target for the generated integration header 321 add_custom_target(${headerTargetName} DEPENDS ${outputDeviceFile} ${outputSyclFile}) 322 add_dependencies(${SDK_BUILD_IR_TARGET} ${headerTargetName}) 323 endif() 324 325 # This property can be set on a per-target basis to indicate that the 326 # integration header should appear after the main source listing 327 get_target_property(includeAfter ${SDK_ADD_SYCL_TARGET} COMPUTECPP_INCLUDE_AFTER) 328 329 if(includeAfter) 330 # Change the source file to the integration header - e.g. 331 # g++ -c source_file_name.cpp.sycl 332 get_target_property(current_sources ${SDK_BUILD_IR_TARGET} SOURCES) 333 # Remove absolute path to source file 334 list(REMOVE_ITEM current_sources ${SDK_BUILD_IR_SOURCE}) 335 # Remove relative path to source file 336 string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" 337 rel_source_file ${SDK_BUILD_IR_SOURCE} 338 ) 339 list(REMOVE_ITEM current_sources ${rel_source_file}) 340 # Add SYCL header to source list 341 list(APPEND current_sources ${outputSyclFile}) 342 set_property(TARGET ${SDK_BUILD_IR_TARGET} 343 PROPERTY SOURCES ${current_sources}) 344 # CMake/gcc don't know what language a .sycl file is, so tell them 345 set_property(SOURCE ${outputSyclFile} PROPERTY LANGUAGE CXX) 346 set(includedFile ${SDK_BUILD_IR_SOURCE}) 347 set(cppFile ${outputSyclFile}) 348 else() 349 set_property(SOURCE ${outputSyclFile} PROPERTY HEADER_FILE_ONLY ON) 350 set(includedFile ${outputSyclFile}) 351 set(cppFile ${SDK_BUILD_IR_SOURCE}) 352 endif() 353 354 # Force inclusion of the integration header for the host compiler 355 if(MSVC) 356 # Group SYCL files inside Visual Studio 357 source_group("SYCL" FILES ${outputSyclFile}) 358 359 if(includeAfter) 360 # Allow the source file to be edited using Visual Studio. 361 # It will be added as a header file so it won't be compiled. 362 set_property(SOURCE ${SDK_BUILD_IR_SOURCE} PROPERTY HEADER_FILE_ONLY true) 363 endif() 364 365 # Add both source and the sycl files to the VS solution. 366 target_sources(${SDK_BUILD_IR_TARGET} PUBLIC ${SDK_BUILD_IR_SOURCE} ${outputSyclFile}) 367 368 set(forceIncludeFlags "/FI${includedFile} /TP") 369 else() 370 set(forceIncludeFlags "-include ${includedFile} -x c++") 371 endif() 372 373 set_property( 374 SOURCE ${cppFile} 375 APPEND_STRING PROPERTY COMPILE_FLAGS "${forceIncludeFlags}" 376 ) 377 378endfunction(__build_ir) 379 380####################### 381# add_sycl_to_target 382####################### 383# 384# Adds a SYCL compilation custom command associated with an existing 385# target and sets a dependancy on that new command. 386# 387# TARGET : Name of the target to add SYCL to. 388# SOURCES : Source files to be compiled for SYCL. 389# 390function(add_sycl_to_target) 391 set(options) 392 set(one_value_args 393 TARGET 394 ) 395 set(multi_value_args 396 SOURCES 397 ) 398 cmake_parse_arguments(SDK_ADD_SYCL 399 "${options}" 400 "${one_value_args}" 401 "${multi_value_args}" 402 ${ARGN} 403 ) 404 405 set_target_properties(${SDK_ADD_SYCL_TARGET} PROPERTIES LINKER_LANGUAGE CXX) 406 407 # If the CXX compiler is set to compute++ enable the driver. 408 get_filename_component(cmakeCxxCompilerFileName "${CMAKE_CXX_COMPILER}" NAME) 409 if("${cmakeCxxCompilerFileName}" STREQUAL "compute++") 410 if(MSVC) 411 message(FATAL_ERROR "The compiler driver is not supported by this system, 412 revert the CXX compiler to your default host compiler.") 413 endif() 414 415 get_target_property(includeAfter ${SDK_ADD_SYCL_TARGET} COMPUTECPP_INCLUDE_AFTER) 416 if(includeAfter) 417 list(APPEND COMPUTECPP_USER_FLAGS -fsycl-ih-last) 418 endif() 419 list(INSERT COMPUTECPP_DEVICE_COMPILER_FLAGS 0 -sycl-driver) 420 # Prepend COMPUTECPP_DEVICE_COMPILER_FLAGS and append COMPUTECPP_USER_FLAGS 421 foreach(prop COMPILE_OPTIONS INTERFACE_COMPILE_OPTIONS) 422 get_target_property(target_compile_options ${SDK_ADD_SYCL_TARGET} ${prop}) 423 if(NOT target_compile_options) 424 set(target_compile_options "") 425 endif() 426 set_property( 427 TARGET ${SDK_ADD_SYCL_TARGET} 428 PROPERTY ${prop} 429 ${COMPUTECPP_DEVICE_COMPILER_FLAGS} 430 ${target_compile_options} 431 ${COMPUTECPP_USER_FLAGS} 432 ) 433 endforeach() 434 else() 435 set(fileCounter 0) 436 list(INSERT COMPUTECPP_DEVICE_COMPILER_FLAGS 0 -sycl) 437 # Add custom target to run compute++ and generate the integration header 438 foreach(sourceFile ${SDK_ADD_SYCL_SOURCES}) 439 if(NOT IS_ABSOLUTE ${sourceFile}) 440 set(sourceFile "${CMAKE_CURRENT_SOURCE_DIR}/${sourceFile}") 441 endif() 442 __build_ir( 443 TARGET ${SDK_ADD_SYCL_TARGET} 444 SOURCE ${sourceFile} 445 COUNTER ${fileCounter} 446 ) 447 MATH(EXPR fileCounter "${fileCounter} + 1") 448 endforeach() 449 endif() 450 451 set_property(TARGET ${SDK_ADD_SYCL_TARGET} 452 APPEND PROPERTY LINK_LIBRARIES ComputeCpp::ComputeCpp) 453 set_property(TARGET ${SDK_ADD_SYCL_TARGET} 454 APPEND PROPERTY INTERFACE_LINK_LIBRARIES ComputeCpp::ComputeCpp) 455endfunction(add_sycl_to_target) 456