From bf06997eea196e9649b70e52c8ab06b05ed65aae Mon Sep 17 00:00:00 2001 From: Allison Vacanti Date: Tue, 21 Jul 2020 13:11:02 -0400 Subject: [PATCH] Allow thrust to be added to CMake projects via add_subdirectory. See issue #976. Added example in `examples/cmake/add_subdir/CMakeLists.txt` that is used for documentation and regression testing. --- CMakeLists.txt | 7 ++ cmake/ThrustAddSubdir.cmake | 6 ++ examples/CMakeLists.txt | 1 + examples/cmake/CMakeLists.txt | 16 +++++ examples/cmake/add_subdir/CMakeLists.txt | 91 ++++++++++++++++++++++++ examples/cmake/add_subdir/dummy.cpp | 32 +++++++++ examples/cmake/add_subdir/dummy.cu | 1 + 7 files changed, 154 insertions(+) create mode 100644 cmake/ThrustAddSubdir.cmake create mode 100644 examples/cmake/CMakeLists.txt create mode 100644 examples/cmake/add_subdir/CMakeLists.txt create mode 100644 examples/cmake/add_subdir/dummy.cpp create mode 100644 examples/cmake/add_subdir/dummy.cu diff --git a/CMakeLists.txt b/CMakeLists.txt index cbec542e06..038f625d84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,10 @@ +# Support adding Thrust to a parent project via add_subdirectory. +# See examples/cmake/add_subdir/CMakeLists.txt for details. +if (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_LIST_DIR}") + include(cmake/ThrustAddSubdir.cmake) + return() +endif() + # 3.15 is the minimum. # 3.17 for nvc++/Feta # 3.18 for C++17 + CUDA diff --git a/cmake/ThrustAddSubdir.cmake b/cmake/ThrustAddSubdir.cmake new file mode 100644 index 0000000000..d48aa14157 --- /dev/null +++ b/cmake/ThrustAddSubdir.cmake @@ -0,0 +1,6 @@ +find_package(Thrust REQUIRED CONFIG + NO_DEFAULT_PATH # Only check the explicit path in HINTS: + HINTS "${CMAKE_CURRENT_LIST_DIR}/.." + COMPONENTS ${THRUST_REQUIRED_SYSTEMS} + OPTIONAL_COMPONENTS ${THRUST_OPTIONAL_SYSTEMS} +) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 47cba3b8c4..b86d8a18b9 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -148,4 +148,5 @@ foreach(thrust_target IN LISTS THRUST_TARGETS) endforeach() endforeach() +add_subdirectory(cmake) add_subdirectory(cuda) diff --git a/examples/cmake/CMakeLists.txt b/examples/cmake/CMakeLists.txt new file mode 100644 index 0000000000..a193994f46 --- /dev/null +++ b/examples/cmake/CMakeLists.txt @@ -0,0 +1,16 @@ +thrust_update_system_found_flags() + +if (THRUST_CPP_FOUND AND THRUST_CUDA_FOUND) + # Do a basic check of the cmake/ThrustAddSubdir.cmake mechanism: + add_test( + NAME thrust.example.cmake.add_subdir + COMMAND "${CMAKE_COMMAND}" + --log-level=VERBOSE + -S "${CMAKE_CURRENT_SOURCE_DIR}/add_subdir" + -B "${CMAKE_CURRENT_BINARY_DIR}/add_subdir" + -D "THRUST_DIR=${Thrust_SOURCE_DIR}" + -D "CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" + -D "CMAKE_CUDA_COMPILER=${CMAKE_CUDA_COMPILER}" + -D "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" + ) +endif() diff --git a/examples/cmake/add_subdir/CMakeLists.txt b/examples/cmake/add_subdir/CMakeLists.txt new file mode 100644 index 0000000000..b66143fddc --- /dev/null +++ b/examples/cmake/add_subdir/CMakeLists.txt @@ -0,0 +1,91 @@ +# This example demonstrates / tests adding thrust via a CMake add_subdirectory +# call from a parent project. +# +# The variables THRUST_REQUIRED_SYSTEMS and THRUST_OPTIONAL_SYSTEMS must be +# set prior to add_subdirectory(thrust), and afterwards the thrust_create_target +# function may be used to create targets with the desired systems. See +# thrust/thrust/cmake/README.md for more details on thrust_create_target. + +cmake_minimum_required(VERSION 3.15) + +# Silence warnings about empty CUDA_ARCHITECTURES properties on example targets: +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.18) + cmake_policy(SET CMP0104 OLD) +endif() + +project(ThrustAddSubDirExample CXX) + +# Add required Thrust systems to THRUST_REQUIRED_SYSTEMS. +# Options are: CPP, CUDA, TBB or OMP. +# Multiple systems may be specified. +# An error is emitted if the system is not found. +set(THRUST_REQUIRED_SYSTEMS CPP) + +# Add optional Thrust systems to THRUST_OPTIONAL_SYSTEMS. +# Options are: CPP, CUDA, TBB or OMP. +# Multiple systems may be specified. +# No error is emitted if not found. +set(THRUST_OPTIONAL_SYSTEMS CUDA) + +# Use your project's checkout of Thrust here, for most cases +# `add_subdirectory(thrust)` will be sufficient. +add_subdirectory("${THRUST_DIR}" thrust) + +# Create a thrust target that only uses the serial CPP backend. +# See thrust/thrust/cmake/README.md for details and additional options: +thrust_create_target(ThrustCPP HOST CPP DEVICE CPP) + +# Create an executable that uses the CPP-only thrust target: +add_executable(ExecWithCPP dummy.cpp) +target_link_libraries(ExecWithCPP ThrustCPP) + +# To test for optional systems, first call thrust_update_system_found_flags to +# set the THRUST_${system}_FOUND flags in current scope. +# Required due to CMake scoping rules. +thrust_update_system_found_flags() + +# Create and use a Thrust target configured to use CUDA acceleration if CUDA +# is available: +if (THRUST_CUDA_FOUND) + enable_language(CUDA) + thrust_create_target(ThrustCUDA HOST CPP DEVICE CUDA) + add_executable(ExecWithCUDA dummy.cu) + target_link_libraries(ExecWithCUDA ThrustCUDA) +endif() + +# +# Validation +# + +function(assert_boolean var_name expect) + if (expect) + if (NOT ${var_name}) + message(FATAL_ERROR "'${var_name}' is false, expected true.") + endif() + else() + if (${var_name}) + message(FATAL_ERROR "'${var_name}' is true, expected false.") + endif() + endif() +endfunction() + +function(assert_target target_name) + if (NOT TARGET "${target_name}") + message(FATAL_ERROR "Target '${target_name}' not defined.") + endif() +endfunction() + +assert_boolean(THRUST_CPP_FOUND TRUE) +assert_boolean(THRUST_CUDA_FOUND TRUE) +assert_boolean(THRUST_OMP_FOUND FALSE) +assert_boolean(THRUST_TBB_FOUND FALSE) + +assert_target(ThrustCPP) +assert_target(ThrustCUDA) +assert_target(ExecWithCPP) +assert_target(ExecWithCUDA) + +thrust_debug_target(ThrustCPP "") +thrust_debug_target(ThrustCUDA "") +thrust_debug_target(ExecWithCPP "") +thrust_debug_target(ExecWithCUDA "") diff --git a/examples/cmake/add_subdir/dummy.cpp b/examples/cmake/add_subdir/dummy.cpp new file mode 100644 index 0000000000..ad7b9435ff --- /dev/null +++ b/examples/cmake/add_subdir/dummy.cpp @@ -0,0 +1,32 @@ +#include + +#include + +int main() +{ + std::cout << "Hello from Thrust version " << THRUST_VERSION << ":\n" + + << "Host system: " +#if THRUST_HOST_SYSTEM == THRUST_HOST_SYSTEM_CPP + << "CPP\n" +#elif THRUST_HOST_SYSTEM == THRUST_HOST_SYSTEM_OMP + << "OMP\n" +#elif THRUST_HOST_SYSTEM == THRUST_HOST_SYSTEM_TBB + << "TBB\n" +#else + << "Unknown\n" +#endif + + << "Device system: " +#if THRUST_DEVICE_SYSTEM == THRUST_DEVICE_SYSTEM_CPP + << "CPP\n"; +#elif THRUST_DEVICE_SYSTEM == THRUST_DEVICE_SYSTEM_CUDA + << "CUDA\n"; +#elif THRUST_DEVICE_SYSTEM == THRUST_DEVICE_SYSTEM_OMP + << "OMP\n"; +#elif THRUST_DEVICE_SYSTEM == THRUST_DEVICE_SYSTEM_TBB + << "TBB\n"; +#else + << "Unknown\n"; +#endif +} diff --git a/examples/cmake/add_subdir/dummy.cu b/examples/cmake/add_subdir/dummy.cu new file mode 100644 index 0000000000..b5645fc3d3 --- /dev/null +++ b/examples/cmake/add_subdir/dummy.cu @@ -0,0 +1 @@ +#include "dummy.cpp"