cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

FindComputeCpp.cmake (16685B)


      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 
     32 cmake_minimum_required(VERSION 3.4.3)
     33 include(FindPackageHandleStandardArgs)
     34 include(ComputeCppIRMap)
     35 
     36 set(COMPUTECPP_USER_FLAGS "" CACHE STRING "User flags for compute++")
     37 separate_arguments(COMPUTECPP_USER_FLAGS)
     38 mark_as_advanced(COMPUTECPP_USER_FLAGS)
     39 
     40 set(COMPUTECPP_BITCODE "spir64" CACHE STRING
     41   "Bitcode type to use as SYCL target in compute++")
     42 mark_as_advanced(COMPUTECPP_BITCODE)
     43 
     44 include(CMakeFindDependencyMacro)
     45 find_dependency(OpenCL REQUIRED)
     46 
     47 # Find ComputeCpp package
     48 
     49 if(DEFINED ComputeCpp_DIR)
     50   set(computecpp_find_hint ${ComputeCpp_DIR})
     51 elseif(DEFINED ENV{COMPUTECPP_DIR})
     52   set(computecpp_find_hint $ENV{COMPUTECPP_DIR})
     53 endif()
     54 
     55 # Used for running executables on the host
     56 set(computecpp_host_find_hint ${computecpp_find_hint})
     57 
     58 if(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()
     65 endif()
     66 
     67 find_program(ComputeCpp_DEVICE_COMPILER_EXECUTABLE compute++
     68   HINTS ${computecpp_host_find_hint}
     69   PATH_SUFFIXES bin
     70   NO_SYSTEM_ENVIRONMENT_PATH)
     71 
     72 find_program(ComputeCpp_INFO_EXECUTABLE computecpp_info
     73   HINTS ${computecpp_host_find_hint}
     74   PATH_SUFFIXES bin
     75   NO_SYSTEM_ENVIRONMENT_PATH)
     76 
     77 find_library(COMPUTECPP_RUNTIME_LIBRARY
     78   NAMES ComputeCpp ComputeCpp_vs2015
     79   HINTS ${computecpp_find_hint}
     80   PATH_SUFFIXES lib
     81   DOC "ComputeCpp Runtime Library")
     82 
     83 find_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 
     89 find_path(ComputeCpp_INCLUDE_DIRS
     90   NAMES "CL/sycl.hpp"
     91   HINTS ${computecpp_find_hint}/include
     92   DOC "The ComputeCpp include directory")
     93 get_filename_component(ComputeCpp_INCLUDE_DIRS ${ComputeCpp_INCLUDE_DIRS} ABSOLUTE)
     94 
     95 get_filename_component(computecpp_canonical_root_dir "${ComputeCpp_INCLUDE_DIRS}/.." ABSOLUTE)
     96 set(ComputeCpp_ROOT_DIR "${computecpp_canonical_root_dir}" CACHE PATH
     97     "The root of the ComputeCpp install")
     98 
     99 if(NOT ComputeCpp_INFO_EXECUTABLE)
    100   message(WARNING "Can't find computecpp_info - check ComputeCpp_DIR")
    101 else()
    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()
    122 endif()
    123 
    124 find_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)
    132 mark_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 
    140 if(NOT ComputeCpp_FOUND)
    141   return()
    142 endif()
    143 
    144 list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS -O2 -mllvm -inline-threshold=1000 -intelspirmetadata)
    145 mark_as_advanced(COMPUTECPP_DEVICE_COMPILER_FLAGS)
    146 
    147 if(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})
    153 endif()
    154 
    155 list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS -sycl-target ${COMPUTECPP_BITCODE})
    156 message(STATUS "compute++ flags - ${COMPUTECPP_DEVICE_COMPILER_FLAGS}")
    157 
    158 include(ComputeCppCompilerChecks)
    159 
    160 if(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   )
    166 endif()
    167 
    168 if(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   )
    177 endif()
    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)
    183 define_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 )
    191 define_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 )
    197 define_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 #
    218 function(__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 
    378 endfunction(__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 #
    390 function(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)
    455 endfunction(add_sycl_to_target)