Skip to content

Commit

Permalink
Thrust when exporte now automatically calls thrust_create_target
Browse files Browse the repository at this point in the history
Instead of having each consuming project inject a code block into
the `project-config.cmake` we instead have rapids-cmake call
`thrust_create_target` right after `find_package(Thrust)`,
only when thrust was found.

This fixes two existing issues:
  1. It removes the need for `rapids_cpm_thrust` to remove the
  the custom Thrust target from the global target set. Now that
  target will exist when rapids-cmake tries to promote it to global
  2. It removes issues when multiple calls to `find_package(thrust)`
  occur before any calls to `thrust_create_target`. This creates
  some vexing issues when the thrust find calls resolve to different
  major versions of thrust
  • Loading branch information
robertmaynard committed Sep 28, 2023
1 parent 133eaec commit 21db3d8
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 34 deletions.
29 changes: 9 additions & 20 deletions rapids-cmake/cpm/thrust.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,27 @@ function(rapids_cpm_thrust NAMESPACE namespaces_name)
set(multi_value)
cmake_parse_arguments(_RAPIDS "${options}" "${one_value}" "${multi_value}" ${ARGN})

set(post_find_code "if(NOT TARGET ${namespaces_name}::Thrust)"
" thrust_create_target(${namespaces_name}::Thrust FROM_OPTIONS)" "endif()")

if(Thrust_SOURCE_DIR AND _RAPIDS_BUILD_EXPORT_SET)
# Store where CMake can find the Thrust-config.cmake that comes part of Thrust source code
include("${rapids-cmake-dir}/export/find_package_root.cmake")
include("${rapids-cmake-dir}/export/detail/post_find_package_code.cmake")
rapids_export_find_package_root(BUILD Thrust "${Thrust_SOURCE_DIR}/cmake"
${_RAPIDS_BUILD_EXPORT_SET})
rapids_export_post_find_package_code(BUILD Thrust "${post_find_code}"
${_RAPIDS_BUILD_EXPORT_SET})
endif()

if(Thrust_SOURCE_DIR AND _RAPIDS_INSTALL_EXPORT_SET AND to_install)
include("${rapids-cmake-dir}/export/find_package_root.cmake")
include("${rapids-cmake-dir}/export/detail/post_find_package_code.cmake")
rapids_export_find_package_root(INSTALL Thrust
[=[${CMAKE_CURRENT_LIST_DIR}/../../rapids/cmake/thrust]=]
${_RAPIDS_INSTALL_EXPORT_SET})
rapids_export_post_find_package_code(INSTALL Thrust "${post_find_code}"
${_RAPIDS_INSTALL_EXPORT_SET})
endif()

# Check for the existence of thrust_create_target so we support fetching Thrust with DOWNLOAD_ONLY
Expand All @@ -113,26 +122,6 @@ function(rapids_cpm_thrust NAMESPACE namespaces_name)
endif()
endif()

# Since `GLOBAL_TARGET ${namespaces_name}::Thrust` will list the target to be promoted to global
# by `rapids_export` this will break consumers as the target doesn't exist when generating the
# dependencies.cmake file, but requires a call to `thrust_create_target`
#
# So determine what `BUILD_EXPORT_SET` and `INSTALL_EXPORT_SET` this was added to and remove
# ${namespaces_name}::Thrust
if(_RAPIDS_BUILD_EXPORT_SET)
set(target_name rapids_export_build_${_RAPIDS_BUILD_EXPORT_SET})
get_target_property(global_targets ${target_name} GLOBAL_TARGETS)
list(REMOVE_ITEM global_targets "${namespaces_name}::Thrust")
set_target_properties(${target_name} PROPERTIES GLOBAL_TARGETS "${global_targets}")
endif()

if(_RAPIDS_INSTALL_EXPORT_SET)
set(target_name rapids_export_install_${_RAPIDS_INSTALL_EXPORT_SET})
get_target_property(global_targets ${target_name} GLOBAL_TARGETS)
list(REMOVE_ITEM global_targets "${namespaces_name}::Thrust")
set_target_properties(${target_name} PROPERTIES GLOBAL_TARGETS "${global_targets}")
endif()

# Propagate up variables that CPMFindPackage provide
set(Thrust_SOURCE_DIR "${Thrust_SOURCE_DIR}" PARENT_SCOPE)
set(Thrust_BINARY_DIR "${Thrust_BINARY_DIR}" PARENT_SCOPE)
Expand Down
65 changes: 65 additions & 0 deletions rapids-cmake/export/detail/post_find_package_code.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#=============================================================================
# Copyright (c) 2023, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file 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.
#=============================================================================
include_guard(GLOBAL)

#[=======================================================================[.rst:
rapids_export_post_find_package_code
------------------------------------
.. versionadded:: v23.12.00
Record for <PackageName> a set of CMake instructions to be executed after the package
has ben found successfully.
.. code-block:: cmake
rapids_export_post_find_package_code((BUILD|INSTALL)
<PackageName>
<code>
<ExportSet>
)
When using complicated find modules like `Thrust` you might need to run some code after
execution. Multiple calls to :cmake:command:`rapids_export_post_find_package_code` will append the
instructions to execute in call order.
.. note:
The code will only be run if the package was found
``BUILD``
Record code to be executed immediately after `PackageName` has been found
for our our build directory export set.
``INSTALL``
Record code to be executed immediately after `PackageName` has been found
for our our install directory export set.
#]=======================================================================]
function(rapids_export_post_find_package_code type name code export_set)
list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.export.post_find_package_code")

string(TOLOWER ${type} type)

if(NOT TARGET rapids_export_${type}_${export_set})
add_library(rapids_export_${type}_${export_set} INTERFACE)
endif()

# if the code coming in is a list of string we will have `;`, so transform those to "\n" so we
# have a single string
string(REPLACE ";" "\n" code "${code}")
set_property(TARGET rapids_export_${type}_${export_set} APPEND_STRING
PROPERTY "${name}_POST_FIND_CODE" "${code}\n")
endfunction()
7 changes: 7 additions & 0 deletions rapids-cmake/export/write_dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ a given export_set for the requested mode.
CMake config module.
#]=======================================================================]
# cmake-lint: disable=R0915
function(rapids_export_write_dependencies type export_set file_path)
list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.export.write_dependencies")

Expand Down Expand Up @@ -116,6 +117,12 @@ endif()\n")
file(READ "${dep_dir}/package_${dep}.cmake" dep_content)
endif()
string(APPEND _RAPIDS_EXPORT_CONTENTS "${dep_content}\n")

get_property(post_find_code TARGET rapids_export_${type}_${export_set}
PROPERTY "${dep}_POST_FIND_CODE")
if(post_find_code)
string(APPEND _RAPIDS_EXPORT_CONTENTS "if(${dep}_FOUND)\n${post_find_code}\nendif()\n")
endif()
endforeach()
string(APPEND _RAPIDS_EXPORT_CONTENTS "\n")

Expand Down
1 change: 1 addition & 0 deletions testing/cpm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,4 @@ add_cmake_config_test( cpm_spdlog-simple.cmake )

add_cmake_config_test( cpm_thrust-export.cmake )
add_cmake_config_test( cpm_thrust-simple.cmake )
add_cmake_build_test( cpm_thrust-verify-post-find-code )
12 changes: 1 addition & 11 deletions testing/cpm/cpm_thrust-export.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#=============================================================================
# Copyright (c) 2021, NVIDIA CORPORATION.
# Copyright (c) 2021-2023, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,13 +30,3 @@ get_target_property(packages rapids_export_install_test2 PACKAGE_NAMES)
if(NOT Thrust IN_LIST packages)
message(FATAL_ERROR "rapids_cpm_thrust failed to record thrust needs to be exported")
endif()

get_target_property(packages rapids_export_build_test GLOBAL_TARGETS)
if(A::Thrust IN_LIST packages)
message(FATAL_ERROR "rapids_cpm_thrust incorrectly added A::Thrust to build GLOBAL_TARGETS")
endif()

get_target_property(packages rapids_export_install_test2 GLOBAL_TARGETS)
if(B::Thrust IN_LIST packages)
message(FATAL_ERROR "rapids_cpm_thrust incorrectly added B::Thrust to install GLOBAL_TARGETS")
endif()
63 changes: 63 additions & 0 deletions testing/cpm/cpm_thrust-verify-post-find-code/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#=============================================================================
# Copyright (c) 2021-2023, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file 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.
#=============================================================================
cmake_minimum_required(VERSION 3.23.1)
project(rapids-test-project LANGUAGES CXX)

include(${rapids-cmake-dir}/cpm/init.cmake)
include(${rapids-cmake-dir}/cpm/thrust.cmake)
include(${rapids-cmake-dir}/export/export.cmake)

set(CMAKE_INSTALL_LIBDIR "lib")

rapids_cpm_init()

rapids_cpm_thrust(NAMESPACE RapidsTest
GLOBAL_TARGETS RapidsTest::Thrust
INSTALL_EXPORT_SET example_export_set)

add_library(fakeLib INTERFACE)
install(TARGETS fakeLib EXPORT example_export_set)
target_link_libraries(fakeLib INTERFACE RapidsTest::Thrust)

rapids_export(INSTALL fake
EXPORT_SET example_export_set
NAMESPACE test::
)

# Install our project so we can verify `thrust_create_target` is called
# automatically in the export-set
add_custom_target(install_project ALL
COMMAND ${CMAKE_COMMAND} --install "${CMAKE_BINARY_DIR}" --prefix install/fake/
)

# Add a custom command that verifies that the expect files have
# been installed for each component
file(WRITE "${CMAKE_BINARY_DIR}/install/CMakeLists.txt" [=[
cmake_minimum_required(VERSION 3.20)
project(verify_install_targets LANGUAGES CXX)

set(computed_path "${CMAKE_CURRENT_SOURCE_DIR}/fake/lib/cmake/fake/")
find_package(fake REQUIRED NO_DEFAULT_PATH HINTS ${computed_path})
if(NOT TARGET RapidsTest::Thrust)
message(FATAL_ERROR "Failed to construct RapidsTest::Thrust target")
endif()
]=])

add_custom_target(verify_install_thrust_works ALL
COMMAND ${CMAKE_COMMAND} -E rm -rf "${CMAKE_BINARY_DIR}/install/build"
COMMAND ${CMAKE_COMMAND} -S="${CMAKE_BINARY_DIR}/install" -B="${CMAKE_BINARY_DIR}/install/build"
)
add_dependencies(verify_install_thrust_works install_project)
8 changes: 5 additions & 3 deletions testing/export/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,18 @@ add_cmake_config_test( export-verify-version.cmake )
add_cmake_config_test( export_component-build )

add_cmake_config_test( export_package-build-possible-dir.cmake )
add_cmake_config_test( export_package-build-with-components.cmake )
add_cmake_config_test( export_package-build-post-find-code.cmake )
add_cmake_config_test( export_package-build-with-components-and-version.cmake )
add_cmake_config_test( export_package-build-with-components.cmake )
add_cmake_config_test( export_package-build-with-empty-components.cmake )
add_cmake_config_test( export_package-build-with-version.cmake )
add_cmake_config_test( export_package-build.cmake )
add_cmake_config_test( export_package-install-possible-dir.cmake )
add_cmake_config_test( export_package-install.cmake )
add_cmake_config_test( export_package-install-with-components.cmake )
add_cmake_config_test( export_package-install-post-find-code.cmake )
add_cmake_config_test( export_package-install-with-components-and-version.cmake )
add_cmake_config_test( export_package-install-with-components.cmake )
add_cmake_config_test( export_package-install-with-version.cmake )
add_cmake_config_test( export_package-install.cmake )
add_cmake_config_test( export_package-multiple-export_sets.cmake )

add_cmake_config_test( write_dependencies-cpm-preserve-options.cmake )
Expand Down
50 changes: 50 additions & 0 deletions testing/export/export_package-build-post-find-code.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#=============================================================================
# Copyright (c) 2023, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file 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.
#=============================================================================
include(${rapids-cmake-dir}/export/package.cmake)
include(${rapids-cmake-dir}/export/detail/post_find_package_code.cmake)

rapids_export_package( BUILD FAKE_PACKAGE test_export_set VERSION 22.08)
rapids_export_post_find_package_code( BUILD FAKE_PACKAGE "set(a ON)" test_export_set)
rapids_export_post_find_package_code( bUILd FAKE_PACKAGE
[=[
set(b ON)
set(c ON)]=] test_export_set)
rapids_export_post_find_package_code( build FAKE_PACKAGE "set(d ON);set(e ON)" test_export_set)

get_target_property(install_code rapids_export_build_test_export_set FAKE_PACKAGE_POST_FIND_CODE)
cmake_language(EVAL CODE "${install_code}")
if(NOT a)
message(FATAL_ERROR "rapids_export_post_find_package_code failed to record first call")
endif()
if(NOT (b AND c))
message(FATAL_ERROR "rapids_export_post_find_package_code failed to record second call")
endif()
if(NOT (d AND e))
message(FATAL_ERROR "rapids_export_post_find_package_code failed to record third call")
endif()

include(${rapids-cmake-dir}/export/write_dependencies.cmake)
rapids_export_write_dependencies(BUILD test_export_set "${CMAKE_CURRENT_BINARY_DIR}/install_export_set.cmake")

set(to_match [=[if(FAKE_PACKAGE_FOUND)_set(a ON)_set(b ON)_set(c ON)_set(d ON)_set(e ON)__endif()]=])

file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/install_export_set.cmake" contents NEWLINE_CONSUME)
string(REPLACE "\n" "_" contents "${contents}")

string(FIND "${contents}" "${to_match}" is_found)
if(is_found EQUAL -1)
message(FATAL_ERROR "rapids_export_write_dependencies(BUILD) failed to record rapids_export_post_find_package_code")
endif()
39 changes: 39 additions & 0 deletions testing/export/export_package-install-post-find-code.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#=============================================================================
# Copyright (c) 2023, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file 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.
#=============================================================================
include(${rapids-cmake-dir}/export/package.cmake)
include(${rapids-cmake-dir}/export/detail/post_find_package_code.cmake)

rapids_export_package( INSTALL FAKE_PACKAGE test_export_set VERSION 22.08)
rapids_export_post_find_package_code(INSTALL FAKE_PACKAGE "set(a ON)" test_export_set)

get_target_property(install_code rapids_export_install_test_export_set FAKE_PACKAGE_POST_FIND_CODE)
cmake_language(EVAL CODE "${install_code}")
if(NOT a)
message(FATAL_ERROR "rapids_export_post_find_package_code failed to record first call")
endif()

include(${rapids-cmake-dir}/export/write_dependencies.cmake)
rapids_export_write_dependencies(INSTALL test_export_set "${CMAKE_CURRENT_BINARY_DIR}/install_export_set.cmake")

set(to_match [=[if(FAKE_PACKAGE_FOUND)_set(a ON)__endif()]=])

file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/install_export_set.cmake" contents NEWLINE_CONSUME)
string(REPLACE "\n" "_" contents "${contents}")

string(FIND "${contents}" "${to_match}" is_found)
if(is_found EQUAL -1)
message(FATAL_ERROR "rapids_export_write_dependencies(INSTALL) failed to record rapids_export_post_find_package_code")
endif()

0 comments on commit 21db3d8

Please sign in to comment.