# # find_package(Thrust) config file. # # Provided by NVIDIA under the same license as the associated Thrust library. # # Reply-To: Allison Vacanti # # ***************************************************************************** # ** The following is a short reference to using Thrust from CMake. ** # ** For more details, see the README.md in the same directory as this file. ** # ***************************************************************************** # # # General Usage: # find_package(Thrust REQUIRED CONFIG) # thrust_create_target(Thrust [options]) # target_link_libraries(some_project_lib Thrust) # # # Create default target with: HOST=CPP DEVICE=CUDA # thrust_create_target(TargetName) # # # Create target with: HOST=CPP DEVICE=TBB # thrust_create_target(TargetName DEVICE TBB) # # # Create target with: HOST=TBB DEVICE=OMP # thrust_create_target(TargetName HOST TBB DEVICE OMP) # # # Create CMake cache options THRUST_[HOST|DEVICE]_SYSTEM and configure a # # target from them. This allows these systems to be changed by developers at # # configure time, per build. # thrust_create_target(TargetName FROM_OPTIONS # [HOST_OPTION ] # Optionally rename the host system option # [DEVICE_OPTION ] # Optionally rename the device system option # [HOST_OPTION_DOC ] # Optionally change the cache label # [DEVICE_OPTION_DOC ] # Optionally change the cache label # [HOST ] # Optionally change the default backend # [DEVICE ] # Optionally change the default backend # [ADVANCED] # Optionally mark options as advanced # [GLOBAL] # Optionally mark the target as GLOBAL # ) # # # Use a custom TBB, CUB, and/or OMP # # (Note that once set, these cannot be changed. This includes COMPONENT # # preloading and lazy lookups in thrust_create_target) # find_package(Thrust REQUIRED) # thrust_set_CUB_target(MyCUBTarget) # MyXXXTarget contains an existing # thrust_set_TBB_target(MyTBBTarget) # interface to XXX for Thrust to use. # thrust_set_OMP_target(MyOMPTarget) # thrust_create_target(ThrustWithMyCUB DEVICE CUDA) # thrust_create_target(ThrustWithMyTBB DEVICE TBB) # thrust_create_target(ThrustWithMyOMP DEVICE OMP) # # # Create target with HOST=CPP DEVICE=CUDA and some advanced flags set # thrust_create_target(TargetName # IGNORE_DEPRECATED_API # Silence build warnings about deprecated APIs # IGNORE_DEPRECATED_CPP_DIALECT # Silence build warnings about deprecated compilers and C++ standards # IGNORE_DEPRECATED_CPP_11 # Only silence deprecation warnings for C++11 # IGNORE_DEPRECATED_CPP_14 # Only silence deprecation warnings for C++14 # IGNORE_DEPRECATED_COMPILER # Only silence deprecation warnings for old compilers # IGNORE_CUB_VERSION # Skip configure-time and compile-time CUB version checks # ) # # # Test if a particular system has been loaded. ${var_name} is set to TRUE or # # FALSE to indicate if "system" is found. # thrust_is_system_found( ) # thrust_is_cuda_system_found() # thrust_is_tbb_system_found() # thrust_is_omp_system_found() # thrust_is_cpp_system_found() # # # Define / update THRUST_${system}_FOUND flags in current scope # thrust_update_system_found_flags() # # # View verbose log with target and dependency information: # $ cmake . --log-level=VERBOSE (CMake 3.15.7 and above) # # # Print debugging output to status channel: # thrust_debug_internal_targets() # thrust_debug_target(TargetName "${THRUST_VERSION}") cmake_minimum_required(VERSION 3.15) cmake_policy(PUSH) cmake_policy(SET CMP0074 NEW) # Minimum supported libcudacxx version: set(thrust_libcudacxx_version "${Thrust_VERSION}") ################################################################################ # User variables and APIs. Users can rely on these: # # Advertise system options: set(THRUST_HOST_SYSTEM_OPTIONS CPP OMP TBB CACHE INTERNAL "Valid Thrust host systems." FORCE ) set(THRUST_DEVICE_SYSTEM_OPTIONS CUDA CPP OMP TBB CACHE INTERNAL "Valid Thrust device systems" FORCE ) # Workaround cmake issue #20670 https://gitlab.kitware.com/cmake/cmake/-/issues/20670 set(THRUST_VERSION ${${CMAKE_FIND_PACKAGE_NAME}_VERSION} CACHE INTERNAL "" FORCE) set(THRUST_VERSION_MAJOR ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_MAJOR} CACHE INTERNAL "" FORCE) set(THRUST_VERSION_MINOR ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_MINOR} CACHE INTERNAL "" FORCE) set(THRUST_VERSION_PATCH ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_PATCH} CACHE INTERNAL "" FORCE) set(THRUST_VERSION_TWEAK ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_TWEAK} CACHE INTERNAL "" FORCE) set(THRUST_VERSION_COUNT ${${CMAKE_FIND_PACKAGE_NAME}_VERSION_COUNT} CACHE INTERNAL "" FORCE) function(thrust_create_target target_name) thrust_debug("Assembling target ${target_name}. Options: ${ARGN}" internal) set(options GLOBAL ADVANCED FROM_OPTIONS IGNORE_CUB_VERSION_CHECK IGNORE_DEPRECATED_API IGNORE_DEPRECATED_COMPILER IGNORE_DEPRECATED_CPP_11 IGNORE_DEPRECATED_CPP_14 IGNORE_DEPRECATED_CPP_DIALECT ) set(keys DEVICE DEVICE_OPTION DEVICE_OPTION_DOC HOST HOST_OPTION HOST_OPTION_DOC ) cmake_parse_arguments(TCT "${options}" "${keys}" "" ${ARGN}) if (TCT_UNPARSED_ARGUMENTS) message(AUTHOR_WARNING "Unrecognized arguments passed to thrust_create_target: " ${TCT_UNPARSED_ARGUMENTS} ) endif() # Check that the main Thrust internal target is available # (functions have global scope, targets have directory scope, so this # might happen) if (NOT TARGET Thrust::Thrust) message(AUTHOR_WARNING "The `thrust_create_target` function was called outside the scope of the " "thrust targets. Call find_package again to recreate targets." ) endif() _thrust_set_if_undefined(TCT_HOST CPP) _thrust_set_if_undefined(TCT_DEVICE CUDA) _thrust_set_if_undefined(TCT_HOST_OPTION THRUST_HOST_SYSTEM) _thrust_set_if_undefined(TCT_DEVICE_OPTION THRUST_DEVICE_SYSTEM) _thrust_set_if_undefined(TCT_HOST_OPTION_DOC "Thrust host system.") _thrust_set_if_undefined(TCT_DEVICE_OPTION_DOC "Thrust device system.") if (NOT TCT_HOST IN_LIST THRUST_HOST_SYSTEM_OPTIONS) message(FATAL_ERROR "Requested HOST=${TCT_HOST}; must be one of ${THRUST_HOST_SYSTEM_OPTIONS}" ) endif() if (NOT TCT_DEVICE IN_LIST THRUST_DEVICE_SYSTEM_OPTIONS) message(FATAL_ERROR "Requested DEVICE=${TCT_DEVICE}; must be one of ${THRUST_DEVICE_SYSTEM_OPTIONS}" ) endif() if (TCT_FROM_OPTIONS) _thrust_create_cache_options( ${TCT_HOST} ${TCT_DEVICE} ${TCT_HOST_OPTION} ${TCT_DEVICE_OPTION} ${TCT_HOST_OPTION_DOC} ${TCT_DEVICE_OPTION_DOC} ${TCT_ADVANCED} ) set(TCT_HOST ${${TCT_HOST_OPTION}}) set(TCT_DEVICE ${${TCT_DEVICE_OPTION}}) thrust_debug("Current option settings:" internal) thrust_debug(" - ${TCT_HOST_OPTION}=${TCT_HOST}" internal) thrust_debug(" - ${TCT_DEVICE_OPTION}=${TCT_DEVICE}" internal) endif() _thrust_find_backend(${TCT_HOST} REQUIRED) _thrust_find_backend(${TCT_DEVICE} REQUIRED) # We can just create an INTERFACE IMPORTED target here instead of going # through _thrust_declare_interface_alias as long as we aren't hanging any # Thrust/CUB include paths directly on ${target_name}. set(TCT_AS_GLOBAL ) if (TCT_GLOBAL) set(TCT_AS_GLOBAL GLOBAL) endif() add_library(${target_name} INTERFACE IMPORTED ${TCT_AS_GLOBAL}) target_link_libraries(${target_name} INTERFACE Thrust::${TCT_HOST}::Host Thrust::${TCT_DEVICE}::Device ) # This would be nice to enforce, but breaks when using old cmake + new # compiler, since cmake doesn't know what features the new compiler version # supports. # Leaving this here as a reminder not to add it back. Just let the # compile-time checks in thrust/detail/config/cpp_dialect.h handle it. # # if (NOT TCT_IGNORE_DEPRECATED_CPP_DIALECT) # if (TCT_IGNORE_DEPRECATED_CPP_11) # target_compile_features(${target_name} INTERFACE cxx_std_11) # else() # target_compile_features(${target_name} INTERFACE cxx_std_14) # endif() # endif() if (TCT_IGNORE_DEPRECATED_CPP_DIALECT) target_compile_definitions(${target_name} INTERFACE "THRUST_IGNORE_DEPRECATED_CPP_DIALECT") endif() if (TCT_IGNORE_DEPRECATED_API) target_compile_definitions(${target_name} INTERFACE "THRUST_IGNORE_DEPRECATED_API") endif() if (TCT_IGNORE_DEPRECATED_CPP_11) target_compile_definitions(${target_name} INTERFACE "THRUST_IGNORE_DEPRECATED_CPP_11") endif() if (TCT_IGNORE_DEPRECATED_CPP_14) target_compile_definitions(${target_name} INTERFACE "THRUST_IGNORE_DEPRECATED_CPP_14") endif() if (TCT_IGNORE_DEPRECATED_COMPILER) target_compile_definitions(${target_name} INTERFACE "THRUST_IGNORE_DEPRECATED_COMPILER") endif() if (TCT_IGNORE_CUB_VERSION_CHECK) target_compile_definitions(${target_name} INTERFACE "THRUST_IGNORE_CUB_VERSION_CHECK") else() if (("${TCT_HOST}" STREQUAL "CUDA" OR "${TCT_DEVICE}" STREQUAL "CUDA") AND (NOT THRUST_VERSION VERSION_EQUAL THRUST_CUB_VERSION)) message(FATAL_ERROR "The version of CUB found by CMake is not compatible with this release of Thrust. " "CUB is now included in the CUDA Toolkit, so you no longer need to use your own checkout of CUB. " "Pass IGNORE_CUB_VERSION_CHECK to thrust_create_target to ignore. " "(CUB ${THRUST_CUB_VERSION}, Thrust ${THRUST_VERSION})." ) endif() endif() thrust_debug_target(${target_name} "Thrust ${THRUST_VERSION}" internal) endfunction() function(thrust_is_system_found system var_name) if (TARGET Thrust::${system}) set(${var_name} TRUE PARENT_SCOPE) else() set(${var_name} FALSE PARENT_SCOPE) endif() endfunction() function(thrust_is_cpp_system_found var_name) thrust_is_system_found(CPP ${var_name}) set(${var_name} ${${var_name}} PARENT_SCOPE) endfunction() function(thrust_is_cuda_system_found var_name) thrust_is_system_found(CUDA ${var_name}) set(${var_name} ${${var_name}} PARENT_SCOPE) endfunction() function(thrust_is_tbb_system_found var_name) thrust_is_system_found(TBB ${var_name}) set(${var_name} ${${var_name}} PARENT_SCOPE) endfunction() function(thrust_is_omp_system_found var_name) thrust_is_system_found(OMP ${var_name}) set(${var_name} ${${var_name}} PARENT_SCOPE) endfunction() # Since components are loaded lazily, this will refresh the # THRUST_${component}_FOUND flags in the current scope. # Alternatively, check system states individually using the # thrust_is_system_found functions. macro(thrust_update_system_found_flags) set(THRUST_FOUND TRUE) thrust_is_system_found(CPP THRUST_CPP_FOUND) thrust_is_system_found(CUDA THRUST_CUDA_FOUND) thrust_is_system_found(TBB THRUST_TBB_FOUND) thrust_is_system_found(OMP THRUST_OMP_FOUND) endmacro() function(thrust_debug msg) # Use the VERBOSE channel when called internally # Run `cmake . --log-level=VERBOSE` to view. if ("${ARGN}" STREQUAL "internal") # If CMake is too old to know about the VERBOSE channel, just be silent. # Users reproduce much the same output on the STATUS channel by using: # thrust_create_target(Thrust [...]) # thrust_debug_internal_targets() # thrust_debug_target(Thrust) if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.15.7") set(channel VERBOSE) else() return() endif() else() set(channel STATUS) endif() message(${channel} "Thrust: ${msg}") endfunction() # Print details of the specified target. function(thrust_debug_target target_name version) if (NOT TARGET ${target_name}) return() endif() set(is_internal "${ARGN}") if (version) set(version "(${version})") endif() thrust_debug("TargetInfo: ${target_name}: ${version}" ${is_internal}) function(_thrust_print_prop_if_set target_name prop) get_target_property(value ${target_name} ${prop}) if (value) thrust_debug("TargetInfo: ${target_name} > ${prop}: ${value}" ${is_internal}) endif() endfunction() function(_thrust_print_imported_prop_if_set target_name prop) get_target_property(imported ${target_name} IMPORTED) get_target_property(type ${target_name} TYPE) if (imported AND NOT ${type} STREQUAL "INTERFACE_LIBRARY") _thrust_print_prop_if_set(${target_name} ${prop}) endif() endfunction() _thrust_print_prop_if_set(${target_name} ALIASED_TARGET) _thrust_print_prop_if_set(${target_name} IMPORTED) _thrust_print_prop_if_set(${target_name} INTERFACE_COMPILE_DEFINITIONS) _thrust_print_prop_if_set(${target_name} INTERFACE_COMPILE_FEATURES) _thrust_print_prop_if_set(${target_name} INTERFACE_COMPILE_OPTIONS) _thrust_print_prop_if_set(${target_name} INTERFACE_INCLUDE_DIRECTORIES) _thrust_print_prop_if_set(${target_name} INTERFACE_LINK_DEPENDS) _thrust_print_prop_if_set(${target_name} INTERFACE_LINK_DIRECTORIES) _thrust_print_prop_if_set(${target_name} INTERFACE_LINK_LIBRARIES) _thrust_print_prop_if_set(${target_name} INTERFACE_LINK_OPTIONS) _thrust_print_prop_if_set(${target_name} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) _thrust_print_prop_if_set(${target_name} INTERFACE_THRUST_HOST) _thrust_print_prop_if_set(${target_name} INTERFACE_THRUST_DEVICE) _thrust_print_imported_prop_if_set(${target_name} IMPORTED_LOCATION) _thrust_print_imported_prop_if_set(${target_name} IMPORTED_LOCATION_DEBUG) _thrust_print_imported_prop_if_set(${target_name} IMPORTED_LOCATION_RELEASE) endfunction() function(thrust_debug_internal_targets) function(_thrust_debug_backend_targets backend version) thrust_debug_target(Thrust::${backend} "${version}") thrust_debug_target(Thrust::${backend}::Host "${version}") thrust_debug_target(Thrust::${backend}::Device "${version}") endfunction() thrust_debug_target(Thrust::Thrust "${THRUST_VERSION}") _thrust_debug_backend_targets(CPP "Thrust ${THRUST_VERSION}") _thrust_debug_backend_targets(OMP "${THRUST_OMP_VERSION}") thrust_debug_target(OpenMP::OpenMP_CXX "${THRUST_OMP_VERSION}") _thrust_debug_backend_targets(TBB "${THRUST_TBB_VERSION}") thrust_debug_target(TBB::tbb "${THRUST_TBB_VERSION}") _thrust_debug_backend_targets(CUDA "CUB ${THRUST_CUB_VERSION}") thrust_debug_target(CUB::CUB "${THRUST_CUB_VERSION}") thrust_debug_target(libcudacxx::libcudacxx "${THRUST_libcudacxx_VERSION}") endfunction() ################################################################################ # Internal utilities. Subject to change. # function(_thrust_set_if_undefined var) if (NOT DEFINED ${var}) set(${var} ${ARGN} PARENT_SCOPE) endif() endfunction() function(_thrust_declare_interface_alias alias_name ugly_name) # 1) Only IMPORTED and ALIAS targets can be placed in a namespace. # 2) When an IMPORTED library is linked to another target, its include # directories are treated as SYSTEM includes. # 3) nvcc will automatically check the CUDA Toolkit include path *before* the # system includes. This means that the Toolkit Thrust will *always* be used # during compilation, and the include paths of an IMPORTED Thrust::Thrust # target will never have any effect. # 4) This behavior can be fixed by setting the property NO_SYSTEM_FROM_IMPORTED # on EVERY target that links to Thrust::Thrust. This would be a burden and a # footgun for our users. Forgetting this would silently pull in the wrong thrust! # 5) A workaround is to make a non-IMPORTED library outside of the namespace, # configure it, and then ALIAS it into the namespace (or ALIAS and then # configure, that seems to work too). add_library(${ugly_name} INTERFACE) add_library(${alias_name} ALIAS ${ugly_name}) endfunction() # Create cache options for selecting the user/device systems with ccmake/cmake-gui. function(_thrust_create_cache_options host device host_option device_option host_doc device_doc advanced) thrust_debug("Creating system cache options: (advanced=${advanced})" internal) thrust_debug(" - Host Option=${host_option} Default=${host} Doc='${host_doc}'" internal) thrust_debug(" - Device Option=${device_option} Default=${device} Doc='${device_doc}'" internal) set(${host_option} ${host} CACHE STRING "${host_doc}") set_property(CACHE ${host_option} PROPERTY STRINGS ${THRUST_HOST_SYSTEM_OPTIONS}) set(${device_option} ${device} CACHE STRING "${device_doc}") set_property(CACHE ${device_option} PROPERTY STRINGS ${THRUST_DEVICE_SYSTEM_OPTIONS}) if (advanced) mark_as_advanced(${host_option} ${device_option}) endif() endfunction() # Create Thrust::${backend}::Host and Thrust::${backend}::Device targets. # Assumes that `Thrust::${backend}` and `_Thrust_${backend}` have been created # by _thrust_declare_interface_alias and configured to bring in system # dependency interfaces (including Thrust::Thrust). function(_thrust_setup_system backend) set(backend_target_alias "Thrust::${backend}") if (backend IN_LIST THRUST_HOST_SYSTEM_OPTIONS) set(host_target "_Thrust_${backend}_Host") set(host_target_alias "Thrust::${backend}::Host") if (NOT TARGET ${host_target_alias}) _thrust_declare_interface_alias(${host_target_alias} ${host_target}) target_compile_definitions(${host_target} INTERFACE "THRUST_HOST_SYSTEM=THRUST_HOST_SYSTEM_${backend}") target_link_libraries(${host_target} INTERFACE ${backend_target_alias}) set_property(TARGET ${host_target} PROPERTY INTERFACE_THRUST_HOST ${backend}) set_property(TARGET ${host_target} APPEND PROPERTY COMPATIBLE_INTERFACE_STRING THRUST_HOST) thrust_debug_target(${host_target_alias} "" internal) endif() endif() if (backend IN_LIST THRUST_DEVICE_SYSTEM_OPTIONS) set(device_target "_Thrust_${backend}_Device") set(device_target_alias "Thrust::${backend}::Device") if (NOT TARGET ${device_target_alias}) _thrust_declare_interface_alias(${device_target_alias} ${device_target}) target_compile_definitions(${device_target} INTERFACE "THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_${backend}") target_link_libraries(${device_target} INTERFACE ${backend_target_alias}) set_property(TARGET ${device_target} PROPERTY INTERFACE_THRUST_DEVICE ${backend}) set_property(TARGET ${device_target} APPEND PROPERTY COMPATIBLE_INTERFACE_STRING THRUST_DEVICE) thrust_debug_target(${device_target_alias} "" internal) endif() endif() endfunction() # Use the provided cub_target for the CUDA backend. If Thrust::CUB already # exists, this call has no effect. function(thrust_set_CUB_target cub_target) if (NOT TARGET Thrust::CUB) thrust_debug("Setting CUB target to ${cub_target}" internal) # Workaround cmake issue #20670 https://gitlab.kitware.com/cmake/cmake/-/issues/20670 set(THRUST_CUB_VERSION ${CUB_VERSION} CACHE INTERNAL "CUB version used by Thrust" FORCE ) _thrust_declare_interface_alias(Thrust::CUB _Thrust_CUB) target_link_libraries(_Thrust_CUB INTERFACE ${cub_target}) thrust_debug_target(${cub_target} "${THRUST_CUB_VERSION}" internal) thrust_debug_target(Thrust::CUB "CUB ${THRUST_CUB_VERSION}" internal) endif() endfunction() # Internal use only -- libcudacxx must be found during the initial # `find_package(Thrust)` call and cannot be set afterwards. See README.md in # this directory for details on using a specific libcudacxx target. function(_thrust_set_libcudacxx_target libcudacxx_target) if (NOT TARGET Thrust::libcudacxx) thrust_debug("Setting libcudacxx target to ${libcudacxx_target}" internal) # Workaround cmake issue #20670 https://gitlab.kitware.com/cmake/cmake/-/issues/20670 set(THRUST_libcudacxx_VERSION ${libcudacxx_VERSION} CACHE INTERNAL "libcudacxx version used by Thrust" FORCE ) _thrust_declare_interface_alias(Thrust::libcudacxx _Thrust_libcudacxx) target_link_libraries(_Thrust_libcudacxx INTERFACE ${libcudacxx_target}) thrust_debug_target(${libcudacxx_target} "${THRUST_libcudacxx_VERSION}" internal) thrust_debug_target(Thrust::libcudacxx "libcudacxx ${THRUST_libcudacxx_VERSION}" internal) endif() endfunction() # Use the provided tbb_target for the TBB backend. If Thrust::TBB already # exists, this call has no effect. function(thrust_set_TBB_target tbb_target) if (NOT TARGET Thrust::TBB) thrust_debug("Setting TBB target to ${tbb_target}" internal) # Workaround cmake issue #20670 https://gitlab.kitware.com/cmake/cmake/-/issues/20670 set(THRUST_TBB_VERSION ${TBB_VERSION} CACHE INTERNAL "TBB version used by Thrust" FORCE ) _thrust_declare_interface_alias(Thrust::TBB _Thrust_TBB) target_link_libraries(_Thrust_TBB INTERFACE Thrust::Thrust ${tbb_target}) thrust_debug_target(${tbb_target} "${THRUST_TBB_VERSION}" internal) thrust_debug_target(Thrust::TBB "${THRUST_TBB_VERSION}" internal) _thrust_setup_system(TBB) endif() endfunction() # Use the provided omp_target for the OMP backend. If Thrust::OMP already # exists, this call has no effect. function(thrust_set_OMP_target omp_target) if (NOT TARGET Thrust::OMP) thrust_debug("Setting OMP target to ${omp_target}" internal) # Workaround cmake issue #20670 https://gitlab.kitware.com/cmake/cmake/-/issues/20670 set(THRUST_OMP_VERSION ${OpenMP_CXX_VERSION} CACHE INTERNAL "OpenMP version used by Thrust" FORCE ) _thrust_declare_interface_alias(Thrust::OMP _Thrust_OMP) target_link_libraries(_Thrust_OMP INTERFACE Thrust::Thrust ${omp_target}) thrust_debug_target(${omp_target} "${THRUST_OMP_VERSION}" internal) thrust_debug_target(Thrust::OMP "${THRUST_OMP_VERSION}" internal) _thrust_setup_system(OMP) endif() endfunction() function(_thrust_find_CPP required) if (NOT TARGET Thrust::CPP) thrust_debug("Generating CPP targets." internal) _thrust_declare_interface_alias(Thrust::CPP _Thrust_CPP) target_link_libraries(_Thrust_CPP INTERFACE Thrust::Thrust) thrust_debug_target(Thrust::CPP "Thrust ${THRUST_VERSION}" internal) _thrust_setup_system(CPP) endif() endfunction() # This must be a macro instead of a function to ensure that backends passed to # find_package(Thrust COMPONENTS [...]) have their full configuration loaded # into the current scope. This provides at least some remedy for CMake issue # #20670 -- otherwise variables like CUB_VERSION, etc won't be in the caller's # scope. macro(_thrust_find_CUDA required) if (NOT TARGET Thrust::CUB) thrust_debug("Searching for CUB ${required}" internal) find_package(CUB ${THRUST_VERSION} CONFIG ${_THRUST_QUIET_FLAG} ${required} NO_DEFAULT_PATH # Only check the explicit HINTS below: HINTS "${_THRUST_INCLUDE_DIR}/dependencies/cub" # Source layout (GitHub) "${_THRUST_INCLUDE_DIR}/../cub/cub/cmake" # Source layout (Perforce) "${_THRUST_CMAKE_DIR}/.." # Install layout ) if (TARGET CUB::CUB) thrust_set_CUB_target(CUB::CUB) else() thrust_debug("CUB not found!" internal) endif() endif() if (NOT TARGET Thrust::CUDA) _thrust_declare_interface_alias(Thrust::CUDA _Thrust_CUDA) _thrust_setup_system(CUDA) target_link_libraries(_Thrust_CUDA INTERFACE Thrust::Thrust Thrust::CUB ) thrust_debug_target(Thrust::CUDA "" internal) endif() endmacro() # This must be a macro instead of a function to ensure that backends passed to # find_package(Thrust COMPONENTS [...]) have their full configuration loaded # into the current scope. This provides at least some remedy for CMake issue # #20670 -- otherwise variables like TBB_VERSION, etc won't be in the caller's # scope. macro(_thrust_find_TBB required) if(NOT TARGET Thrust::TBB) thrust_debug("Searching for TBB ${required}" internal) # Try to find the CMake package that newer versions of TBB install themselves: if (NOT TARGET TBB::tbb) find_package(TBB CONFIG ${_THRUST_QUIET_FLAG}) endif() # If that fails, fall back to the Path of Sadness: FindTBB.cmake if (NOT TARGET TBB::tbb) # Swap in a temporary module path to make sure we use our FindTBB.cmake set(_THRUST_STASH_MODULE_PATH "${CMAKE_MODULE_PATH}") set(CMAKE_MODULE_PATH "${_THRUST_CMAKE_DIR}") # Legacy support for a removed THRUST_TBB_ROOT option: if (THRUST_TBB_ROOT AND NOT TBB_ROOT) set(TBB_ROOT "${THRUST_TBB_ROOT}") endif() find_package(TBB ${_THRUST_QUIET_FLAG} ${required} ) set(CMAKE_MODULE_PATH "${_THRUST_STASH_MODULE_PATH}") endif() if (TARGET TBB::tbb) thrust_set_TBB_target(TBB::tbb) else() thrust_debug("TBB not found!" internal) endif() endif() endmacro() # Wrap the OpenMP flags for CUDA targets function(thrust_fixup_omp_target omp_target) get_target_property(opts ${omp_target} INTERFACE_COMPILE_OPTIONS) if (opts MATCHES "\\$<\\$:([^>]*)>") target_compile_options(${omp_target} INTERFACE $<$:-Xcompiler=${CMAKE_MATCH_1}> ) endif() endfunction() # This must be a macro instead of a function to ensure that backends passed to # find_package(Thrust COMPONENTS [...]) have their full configuration loaded # into the current scope. This provides at least some remedy for CMake issue # #20670 -- otherwise variables like OpenMP_CXX_VERSION, etc won't be in the caller's # scope. macro(_thrust_find_OMP required) if (NOT TARGET Thrust::OMP) thrust_debug("Searching for OMP ${required}" internal) find_package(OpenMP ${_THRUST_QUIET_FLAG} ${_THRUST_REQUIRED_FLAG_OMP} COMPONENTS CXX ) if (TARGET OpenMP::OpenMP_CXX) thrust_fixup_omp_target(OpenMP::OpenMP_CXX) thrust_set_OMP_target(OpenMP::OpenMP_CXX) else() thrust_debug("OpenMP::OpenMP_CXX not found!" internal) endif() endif() endmacro() # This must be a macro instead of a function to ensure that backends passed to # find_package(Thrust COMPONENTS [...]) have their full configuration loaded # into the current scope. This provides at least some remedy for CMake issue # #20670 -- otherwise variables like CUB_VERSION, etc won't be in the caller's # scope. macro(_thrust_find_backend backend required) # Unfortunately, _thrust_find_${backend}(req) is not valid CMake syntax. Hence # why this function exists. if ("${backend}" STREQUAL "CPP") _thrust_find_CPP("${required}") elseif ("${backend}" STREQUAL "CUDA") _thrust_find_CUDA("${required}") elseif ("${backend}" STREQUAL "TBB") _thrust_find_TBB("${required}") elseif ("${backend}" STREQUAL "OMP") _thrust_find_OMP("${required}") else() message(FATAL_ERROR "_thrust_find_backend: Invalid system: ${backend}") endif() endmacro() ################################################################################ # Initialization. Executed inside find_package(Thrust) call. # if (${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) set(_THRUST_QUIET ON CACHE INTERNAL "Quiet mode enabled for Thrust find_package calls." FORCE) set(_THRUST_QUIET_FLAG "QUIET" CACHE INTERNAL "" FORCE) else() unset(_THRUST_QUIET CACHE) unset(_THRUST_QUIET_FLAG CACHE) endif() set(_THRUST_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "Location of thrust-config.cmake" FORCE ) # Internal target that actually holds the Thrust interface. Used by all other Thrust targets. if (NOT TARGET Thrust::Thrust) _thrust_declare_interface_alias(Thrust::Thrust _Thrust_Thrust) # Pull in the include dir detected by thrust-config-version.cmake set(_THRUST_INCLUDE_DIR "${_THRUST_VERSION_INCLUDE_DIR}" CACHE INTERNAL "Location of Thrust headers." FORCE ) unset(_THRUST_VERSION_INCLUDE_DIR CACHE) # Clear tmp variable from cache target_include_directories(_Thrust_Thrust INTERFACE "${_THRUST_INCLUDE_DIR}") thrust_debug_target(Thrust::Thrust "${THRUST_VERSION}" internal) endif() # Find libcudacxx prior to locating backend-specific deps. This ensures that CUB # finds the same package. if (NOT TARGET Thrust::libcudacxx) thrust_debug("Searching for libcudacxx REQUIRED" internal) # First do a non-required search for any co-packaged versions. # These are preferred. find_package(libcudacxx ${thrust_libcudacxx_version} CONFIG ${_THRUST_QUIET_FLAG} NO_DEFAULT_PATH # Only check the explicit HINTS below: HINTS "${_THRUST_INCLUDE_DIR}/../libcudacxx" # Source layout "${_THRUST_CMAKE_DIR}/.." # Install layout ) # A second required search allows externally packaged to be used and fails if # no suitable package exists. find_package(libcudacxx ${thrust_libcudacxx_version} CONFIG REQUIRED ${_THRUST_QUIET_FLAG} ) if (TARGET libcudacxx::libcudacxx) _thrust_set_libcudacxx_target(libcudacxx::libcudacxx) else() thrust_debug("Expected libcudacxx::libcudacxx target not found!" internal) endif() target_link_libraries(_Thrust_Thrust INTERFACE Thrust::libcudacxx) endif() # Handle find_package COMPONENT requests: foreach(component ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS}) if (NOT component IN_LIST THRUST_HOST_SYSTEM_OPTIONS AND NOT component IN_LIST THRUST_DEVICE_SYSTEM_OPTIONS) message(FATAL_ERROR "Invalid component requested: '${component}'") endif() unset(req) if (${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED_${component}) set(req "REQUIRED") endif() thrust_debug("Preloading COMPONENT '${component}' ${req}" internal) _thrust_find_backend(${component} "${req}") endforeach() thrust_update_system_found_flags() include(FindPackageHandleStandardArgs) if (NOT Thrust_CONFIG) set(Thrust_CONFIG "${CMAKE_CURRENT_LIST_FILE}") endif() find_package_handle_standard_args(Thrust CONFIG_MODE) cmake_policy(POP)