| #.rst: | |
| # FindComputeCpp | |
| #--------------- | |
| # | |
| # Copyright 2016-2018 Codeplay Software Ltd. | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use these files except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| ######################### | |
| # FindComputeCpp.cmake | |
| ######################### | |
| # | |
| # Tools for finding and building with ComputeCpp. | |
| # | |
| # User must define ComputeCpp_DIR pointing to the ComputeCpp | |
| # installation. | |
| # | |
| # Latest version of this file can be found at: | |
| # https://github.com/codeplaysoftware/computecpp-sdk | |
| cmake_minimum_required(VERSION 3.4.3) | |
| include(FindPackageHandleStandardArgs) | |
| include(ComputeCppIRMap) | |
| set(COMPUTECPP_USER_FLAGS "" CACHE STRING "User flags for compute++") | |
| separate_arguments(COMPUTECPP_USER_FLAGS) | |
| mark_as_advanced(COMPUTECPP_USER_FLAGS) | |
| set(COMPUTECPP_BITCODE "spir64" CACHE STRING | |
| "Bitcode type to use as SYCL target in compute++") | |
| mark_as_advanced(COMPUTECPP_BITCODE) | |
| include(CMakeFindDependencyMacro) | |
| find_dependency(OpenCL REQUIRED) | |
| # Find ComputeCpp package | |
| if(DEFINED ComputeCpp_DIR) | |
| set(computecpp_find_hint ${ComputeCpp_DIR}) | |
| elseif(DEFINED ENV{COMPUTECPP_DIR}) | |
| set(computecpp_find_hint $ENV{COMPUTECPP_DIR}) | |
| endif() | |
| # Used for running executables on the host | |
| set(computecpp_host_find_hint ${computecpp_find_hint}) | |
| if(CMAKE_CROSSCOMPILING) | |
| # ComputeCpp_HOST_DIR is used to find executables that are run on the host | |
| if(DEFINED ComputeCpp_HOST_DIR) | |
| set(computecpp_host_find_hint ${ComputeCpp_HOST_DIR}) | |
| elseif(DEFINED ENV{COMPUTECPP_HOST_DIR}) | |
| set(computecpp_host_find_hint $ENV{COMPUTECPP_HOST_DIR}) | |
| endif() | |
| endif() | |
| find_program(ComputeCpp_DEVICE_COMPILER_EXECUTABLE compute++ | |
| HINTS ${computecpp_host_find_hint} | |
| PATH_SUFFIXES bin | |
| NO_SYSTEM_ENVIRONMENT_PATH) | |
| find_program(ComputeCpp_INFO_EXECUTABLE computecpp_info | |
| HINTS ${computecpp_host_find_hint} | |
| PATH_SUFFIXES bin | |
| NO_SYSTEM_ENVIRONMENT_PATH) | |
| find_library(COMPUTECPP_RUNTIME_LIBRARY | |
| NAMES ComputeCpp ComputeCpp_vs2015 | |
| HINTS ${computecpp_find_hint} | |
| PATH_SUFFIXES lib | |
| DOC "ComputeCpp Runtime Library") | |
| find_library(COMPUTECPP_RUNTIME_LIBRARY_DEBUG | |
| NAMES ComputeCpp_d ComputeCpp ComputeCpp_vs2015_d | |
| HINTS ${computecpp_find_hint} | |
| PATH_SUFFIXES lib | |
| DOC "ComputeCpp Debug Runtime Library") | |
| find_path(ComputeCpp_INCLUDE_DIRS | |
| NAMES "CL/sycl.hpp" | |
| HINTS ${computecpp_find_hint}/include | |
| DOC "The ComputeCpp include directory") | |
| get_filename_component(ComputeCpp_INCLUDE_DIRS ${ComputeCpp_INCLUDE_DIRS} ABSOLUTE) | |
| get_filename_component(computecpp_canonical_root_dir "${ComputeCpp_INCLUDE_DIRS}/.." ABSOLUTE) | |
| set(ComputeCpp_ROOT_DIR "${computecpp_canonical_root_dir}" CACHE PATH | |
| "The root of the ComputeCpp install") | |
| if(NOT ComputeCpp_INFO_EXECUTABLE) | |
| message(WARNING "Can't find computecpp_info - check ComputeCpp_DIR") | |
| else() | |
| execute_process(COMMAND ${ComputeCpp_INFO_EXECUTABLE} "--dump-version" | |
| OUTPUT_VARIABLE ComputeCpp_VERSION | |
| RESULT_VARIABLE ComputeCpp_INFO_EXECUTABLE_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE) | |
| if(NOT ComputeCpp_INFO_EXECUTABLE_RESULT EQUAL "0") | |
| message(WARNING "Package version - Error obtaining version!") | |
| endif() | |
| execute_process(COMMAND ${ComputeCpp_INFO_EXECUTABLE} "--dump-is-supported" | |
| OUTPUT_VARIABLE COMPUTECPP_PLATFORM_IS_SUPPORTED | |
| RESULT_VARIABLE ComputeCpp_INFO_EXECUTABLE_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE) | |
| if(NOT ComputeCpp_INFO_EXECUTABLE_RESULT EQUAL "0") | |
| message(WARNING "platform - Error checking platform support!") | |
| else() | |
| mark_as_advanced(COMPUTECPP_PLATFORM_IS_SUPPORTED) | |
| if (COMPUTECPP_PLATFORM_IS_SUPPORTED) | |
| message(STATUS "platform - your system can support ComputeCpp") | |
| else() | |
| message(STATUS "platform - your system is not officially supported") | |
| endif() | |
| endif() | |
| endif() | |
| find_package_handle_standard_args(ComputeCpp | |
| REQUIRED_VARS ComputeCpp_ROOT_DIR | |
| ComputeCpp_DEVICE_COMPILER_EXECUTABLE | |
| ComputeCpp_INFO_EXECUTABLE | |
| COMPUTECPP_RUNTIME_LIBRARY | |
| COMPUTECPP_RUNTIME_LIBRARY_DEBUG | |
| ComputeCpp_INCLUDE_DIRS | |
| VERSION_VAR ComputeCpp_VERSION) | |
| mark_as_advanced(ComputeCpp_ROOT_DIR | |
| ComputeCpp_DEVICE_COMPILER_EXECUTABLE | |
| ComputeCpp_INFO_EXECUTABLE | |
| COMPUTECPP_RUNTIME_LIBRARY | |
| COMPUTECPP_RUNTIME_LIBRARY_DEBUG | |
| ComputeCpp_INCLUDE_DIRS | |
| ComputeCpp_VERSION) | |
| if(NOT ComputeCpp_FOUND) | |
| return() | |
| endif() | |
| list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS -O2 -mllvm -inline-threshold=1000 -intelspirmetadata) | |
| mark_as_advanced(COMPUTECPP_DEVICE_COMPILER_FLAGS) | |
| if(CMAKE_CROSSCOMPILING) | |
| if(NOT COMPUTECPP_DONT_USE_TOOLCHAIN) | |
| list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS --gcc-toolchain=${COMPUTECPP_TOOLCHAIN_DIR}) | |
| endif() | |
| list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS --sysroot=${COMPUTECPP_SYSROOT_DIR}) | |
| list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS -target ${COMPUTECPP_TARGET_TRIPLE}) | |
| endif() | |
| list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS -sycl-target ${COMPUTECPP_BITCODE}) | |
| message(STATUS "compute++ flags - ${COMPUTECPP_DEVICE_COMPILER_FLAGS}") | |
| include(ComputeCppCompilerChecks) | |
| if(NOT TARGET OpenCL::OpenCL) | |
| add_library(OpenCL::OpenCL UNKNOWN IMPORTED) | |
| set_target_properties(OpenCL::OpenCL PROPERTIES | |
| IMPORTED_LOCATION "${OpenCL_LIBRARIES}" | |
| INTERFACE_INCLUDE_DIRECTORIES "${OpenCL_INCLUDE_DIRS}" | |
| ) | |
| endif() | |
| if(NOT TARGET ComputeCpp::ComputeCpp) | |
| add_library(ComputeCpp::ComputeCpp UNKNOWN IMPORTED) | |
| set_target_properties(ComputeCpp::ComputeCpp PROPERTIES | |
| IMPORTED_LOCATION_DEBUG "${COMPUTECPP_RUNTIME_LIBRARY_DEBUG}" | |
| IMPORTED_LOCATION_RELWITHDEBINFO "${COMPUTECPP_RUNTIME_LIBRARY}" | |
| IMPORTED_LOCATION "${COMPUTECPP_RUNTIME_LIBRARY}" | |
| INTERFACE_INCLUDE_DIRECTORIES "${ComputeCpp_INCLUDE_DIRS}" | |
| INTERFACE_LINK_LIBRARIES "OpenCL::OpenCL" | |
| ) | |
| endif() | |
| # This property allows targets to specify that their sources should be | |
| # compiled with the integration header included after the user's | |
| # sources, not before (e.g. when an enum is used in a kernel name, this | |
| # is not technically valid SYCL code but can work with ComputeCpp) | |
| define_property( | |
| TARGET PROPERTY COMPUTECPP_INCLUDE_AFTER | |
| BRIEF_DOCS "Include integration header after user source" | |
| FULL_DOCS "Changes compiler arguments such that the source file is | |
| actually the integration header, and the .cpp file is included on | |
| the command line so that it is seen by the compiler first. Enables | |
| non-standards-conformant SYCL code to compile with ComputeCpp." | |
| ) | |
| define_property( | |
| TARGET PROPERTY INTERFACE_COMPUTECPP_FLAGS | |
| BRIEF_DOCS "Interface compile flags to provide compute++" | |
| FULL_DOCS "Set additional compile flags to pass to compute++ when compiling | |
| any target which links to this one." | |
| ) | |
| define_property( | |
| SOURCE PROPERTY COMPUTECPP_SOURCE_FLAGS | |
| BRIEF_DOCS "Source file compile flags for compute++" | |
| FULL_DOCS "Set additional compile flags for compiling the SYCL integration | |
| header for the given source file." | |
| ) | |
| #################### | |
| # __build_ir | |
| #################### | |
| # | |
| # Adds a custom target for running compute++ and adding a dependency for the | |
| # resulting integration header and kernel binary. | |
| # | |
| # TARGET : Name of the target. | |
| # SOURCE : Source file to be compiled. | |
| # COUNTER : Counter included in name of custom target. Different counter | |
| # values prevent duplicated names of custom target when source files with | |
| # the same name, but located in different directories, are used for the | |
| # same target. | |
| # | |
| function(__build_ir) | |
| set(options) | |
| set(one_value_args | |
| TARGET | |
| SOURCE | |
| COUNTER | |
| ) | |
| set(multi_value_args) | |
| cmake_parse_arguments(SDK_BUILD_IR | |
| "${options}" | |
| "${one_value_args}" | |
| "${multi_value_args}" | |
| ${ARGN} | |
| ) | |
| get_filename_component(sourceFileName ${SDK_BUILD_IR_SOURCE} NAME) | |
| # Set the path to the integration header. | |
| # The .sycl filename must depend on the target so that different targets | |
| # using the same source file will be generated with a different rule. | |
| set(baseSyclName ${CMAKE_CURRENT_BINARY_DIR}/${SDK_BUILD_IR_TARGET}_${sourceFileName}) | |
| set(outputSyclFile ${baseSyclName}.sycl) | |
| set(outputDeviceFile ${baseSyclName}.${IR_MAP_${COMPUTECPP_BITCODE}}) | |
| set(depFileName ${baseSyclName}.sycl.d) | |
| set(include_directories "$<TARGET_PROPERTY:${SDK_BUILD_IR_TARGET},INCLUDE_DIRECTORIES>") | |
| set(compile_definitions "$<TARGET_PROPERTY:${SDK_BUILD_IR_TARGET},COMPILE_DEFINITIONS>") | |
| set(generated_include_directories | |
| $<$<BOOL:${include_directories}>:-I\"$<JOIN:${include_directories},\"\t-I\">\">) | |
| set(generated_compile_definitions | |
| $<$<BOOL:${compile_definitions}>:-D$<JOIN:${compile_definitions},\t-D>>) | |
| # Obtain language standard of the file | |
| set(device_compiler_cxx_standard) | |
| get_target_property(targetCxxStandard ${SDK_BUILD_IR_TARGET} CXX_STANDARD) | |
| if (targetCxxStandard MATCHES 17) | |
| set(device_compiler_cxx_standard "-std=c++1z") | |
| elseif (targetCxxStandard MATCHES 14) | |
| set(device_compiler_cxx_standard "-std=c++14") | |
| elseif (targetCxxStandard MATCHES 11) | |
| set(device_compiler_cxx_standard "-std=c++11") | |
| elseif (targetCxxStandard MATCHES 98) | |
| message(FATAL_ERROR "SYCL applications cannot be compiled using C++98") | |
| else () | |
| set(device_compiler_cxx_standard "") | |
| endif() | |
| get_property(source_compile_flags | |
| SOURCE ${SDK_BUILD_IR_SOURCE} | |
| PROPERTY COMPUTECPP_SOURCE_FLAGS | |
| ) | |
| separate_arguments(source_compile_flags) | |
| if(source_compile_flags) | |
| list(APPEND computecpp_source_flags ${source_compile_flags}) | |
| endif() | |
| list(APPEND COMPUTECPP_DEVICE_COMPILER_FLAGS | |
| ${device_compiler_cxx_standard} | |
| ${COMPUTECPP_USER_FLAGS} | |
| ${computecpp_source_flags} | |
| ) | |
| set(ir_dependencies ${SDK_BUILD_IR_SOURCE}) | |
| get_target_property(target_libraries ${SDK_BUILD_IR_TARGET} LINK_LIBRARIES) | |
| if(target_libraries) | |
| foreach(library ${target_libraries}) | |
| if(TARGET ${library}) | |
| list(APPEND ir_dependencies ${library}) | |
| endif() | |
| endforeach() | |
| endif() | |
| # Depfile support was only added in CMake 3.7 | |
| # CMake throws an error if it is unsupported by the generator (i. e. not ninja) | |
| if((NOT CMAKE_VERSION VERSION_LESS 3.7.0) AND | |
| CMAKE_GENERATOR MATCHES "Ninja") | |
| file(RELATIVE_PATH relOutputFile ${CMAKE_BINARY_DIR} ${outputDeviceFile}) | |
| set(generate_depfile -MMD -MF ${depFileName} -MT ${relOutputFile}) | |
| set(enable_depfile DEPFILE ${depFileName}) | |
| endif() | |
| # Add custom command for running compute++ | |
| add_custom_command( | |
| OUTPUT ${outputDeviceFile} ${outputSyclFile} | |
| COMMAND ${ComputeCpp_DEVICE_COMPILER_EXECUTABLE} | |
| ${COMPUTECPP_DEVICE_COMPILER_FLAGS} | |
| ${generated_include_directories} | |
| ${generated_compile_definitions} | |
| -sycl-ih ${outputSyclFile} | |
| -o ${outputDeviceFile} | |
| -c ${SDK_BUILD_IR_SOURCE} | |
| ${generate_depfile} | |
| DEPENDS ${ir_dependencies} | |
| IMPLICIT_DEPENDS CXX ${SDK_BUILD_IR_SOURCE} | |
| ${enable_depfile} | |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} | |
| COMMENT "Building ComputeCpp integration header file ${outputSyclFile}") | |
| # Name: (user-defined name)_(source file)_(counter)_ih | |
| set(headerTargetName | |
| ${SDK_BUILD_IR_TARGET}_${sourceFileName}_${SDK_BUILD_IR_COUNTER}_ih) | |
| if(NOT MSVC) | |
| # Add a custom target for the generated integration header | |
| add_custom_target(${headerTargetName} DEPENDS ${outputDeviceFile} ${outputSyclFile}) | |
| add_dependencies(${SDK_BUILD_IR_TARGET} ${headerTargetName}) | |
| endif() | |
| # This property can be set on a per-target basis to indicate that the | |
| # integration header should appear after the main source listing | |
| get_target_property(includeAfter ${SDK_ADD_SYCL_TARGET} COMPUTECPP_INCLUDE_AFTER) | |
| if(includeAfter) | |
| # Change the source file to the integration header - e.g. | |
| # g++ -c source_file_name.cpp.sycl | |
| get_target_property(current_sources ${SDK_BUILD_IR_TARGET} SOURCES) | |
| # Remove absolute path to source file | |
| list(REMOVE_ITEM current_sources ${SDK_BUILD_IR_SOURCE}) | |
| # Remove relative path to source file | |
| string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" | |
| rel_source_file ${SDK_BUILD_IR_SOURCE} | |
| ) | |
| list(REMOVE_ITEM current_sources ${rel_source_file}) | |
| # Add SYCL header to source list | |
| list(APPEND current_sources ${outputSyclFile}) | |
| set_property(TARGET ${SDK_BUILD_IR_TARGET} | |
| PROPERTY SOURCES ${current_sources}) | |
| # CMake/gcc don't know what language a .sycl file is, so tell them | |
| set_property(SOURCE ${outputSyclFile} PROPERTY LANGUAGE CXX) | |
| set(includedFile ${SDK_BUILD_IR_SOURCE}) | |
| set(cppFile ${outputSyclFile}) | |
| else() | |
| set_property(SOURCE ${outputSyclFile} PROPERTY HEADER_FILE_ONLY ON) | |
| set(includedFile ${outputSyclFile}) | |
| set(cppFile ${SDK_BUILD_IR_SOURCE}) | |
| endif() | |
| # Force inclusion of the integration header for the host compiler | |
| if(MSVC) | |
| # Group SYCL files inside Visual Studio | |
| source_group("SYCL" FILES ${outputSyclFile}) | |
| if(includeAfter) | |
| # Allow the source file to be edited using Visual Studio. | |
| # It will be added as a header file so it won't be compiled. | |
| set_property(SOURCE ${SDK_BUILD_IR_SOURCE} PROPERTY HEADER_FILE_ONLY true) | |
| endif() | |
| # Add both source and the sycl files to the VS solution. | |
| target_sources(${SDK_BUILD_IR_TARGET} PUBLIC ${SDK_BUILD_IR_SOURCE} ${outputSyclFile}) | |
| set(forceIncludeFlags "/FI${includedFile} /TP") | |
| else() | |
| set(forceIncludeFlags "-include ${includedFile} -x c++") | |
| endif() | |
| set_property( | |
| SOURCE ${cppFile} | |
| APPEND_STRING PROPERTY COMPILE_FLAGS "${forceIncludeFlags}" | |
| ) | |
| endfunction(__build_ir) | |
| ####################### | |
| # add_sycl_to_target | |
| ####################### | |
| # | |
| # Adds a SYCL compilation custom command associated with an existing | |
| # target and sets a dependency on that new command. | |
| # | |
| # TARGET : Name of the target to add SYCL to. | |
| # SOURCES : Source files to be compiled for SYCL. | |
| # | |
| function(add_sycl_to_target) | |
| set(options) | |
| set(one_value_args | |
| TARGET | |
| ) | |
| set(multi_value_args | |
| SOURCES | |
| ) | |
| cmake_parse_arguments(SDK_ADD_SYCL | |
| "${options}" | |
| "${one_value_args}" | |
| "${multi_value_args}" | |
| ${ARGN} | |
| ) | |
| set_target_properties(${SDK_ADD_SYCL_TARGET} PROPERTIES LINKER_LANGUAGE CXX) | |
| # If the CXX compiler is set to compute++ enable the driver. | |
| get_filename_component(cmakeCxxCompilerFileName "${CMAKE_CXX_COMPILER}" NAME) | |
| if("${cmakeCxxCompilerFileName}" STREQUAL "compute++") | |
| if(MSVC) | |
| message(FATAL_ERROR "The compiler driver is not supported by this system, | |
| revert the CXX compiler to your default host compiler.") | |
| endif() | |
| get_target_property(includeAfter ${SDK_ADD_SYCL_TARGET} COMPUTECPP_INCLUDE_AFTER) | |
| if(includeAfter) | |
| list(APPEND COMPUTECPP_USER_FLAGS -fsycl-ih-last) | |
| endif() | |
| list(INSERT COMPUTECPP_DEVICE_COMPILER_FLAGS 0 -sycl-driver) | |
| # Prepend COMPUTECPP_DEVICE_COMPILER_FLAGS and append COMPUTECPP_USER_FLAGS | |
| foreach(prop COMPILE_OPTIONS INTERFACE_COMPILE_OPTIONS) | |
| get_target_property(target_compile_options ${SDK_ADD_SYCL_TARGET} ${prop}) | |
| if(NOT target_compile_options) | |
| set(target_compile_options "") | |
| endif() | |
| set_property( | |
| TARGET ${SDK_ADD_SYCL_TARGET} | |
| PROPERTY ${prop} | |
| ${COMPUTECPP_DEVICE_COMPILER_FLAGS} | |
| ${target_compile_options} | |
| ${COMPUTECPP_USER_FLAGS} | |
| ) | |
| endforeach() | |
| else() | |
| set(fileCounter 0) | |
| list(INSERT COMPUTECPP_DEVICE_COMPILER_FLAGS 0 -sycl) | |
| # Add custom target to run compute++ and generate the integration header | |
| foreach(sourceFile ${SDK_ADD_SYCL_SOURCES}) | |
| if(NOT IS_ABSOLUTE ${sourceFile}) | |
| set(sourceFile "${CMAKE_CURRENT_SOURCE_DIR}/${sourceFile}") | |
| endif() | |
| __build_ir( | |
| TARGET ${SDK_ADD_SYCL_TARGET} | |
| SOURCE ${sourceFile} | |
| COUNTER ${fileCounter} | |
| ) | |
| MATH(EXPR fileCounter "${fileCounter} + 1") | |
| endforeach() | |
| endif() | |
| set_property(TARGET ${SDK_ADD_SYCL_TARGET} | |
| APPEND PROPERTY LINK_LIBRARIES ComputeCpp::ComputeCpp) | |
| set_property(TARGET ${SDK_ADD_SYCL_TARGET} | |
| APPEND PROPERTY INTERFACE_LINK_LIBRARIES ComputeCpp::ComputeCpp) | |
| endfunction(add_sycl_to_target) |