xref: /aosp_15_r20/external/eigen/cmake/FindComputeCpp.cmake (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
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