Skip to content

Commit

Permalink
support_conda_env support host and build CTK 12 locations (#428)
Browse files Browse the repository at this point in the history
For cuda 12+ the conda layout has CTK components in both host and build. Update the CMAKE_PREFIX search locations and rpath-link entries for this new layout.

Authors:
  - Robert Maynard (https://github.com/robertmaynard)
  - Vyas Ramasubramani (https://github.com/vyasr)

Approvers:
  - Bradley Dice (https://github.com/bdice)
  - Vyas Ramasubramani (https://github.com/vyasr)

URL: #428
  • Loading branch information
robertmaynard authored Jun 13, 2023
1 parent 707f9ad commit 207d126
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 5 deletions.
39 changes: 35 additions & 4 deletions rapids-cmake/cmake/support_conda_env.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,20 @@ Creates a global interface target called `target_name` that holds
the CONDA include and link directories, when executed.

Also offers the ability to modify :cmake:variable:`CMAKE_PREFIX_PATH <cmake:variable:CMAKE_PREFIX_PATH>` to
include the paths in environment variables `PREFIX`, `BUILD_PREFIX`,
and `CONDA_PREFIX` based on the current CONDA environment.
include the following paths based on the current conda environment:

- `PREFIX`
- `BUILD_PREFIX`
- `CONDA_PREFIX`

.. versionadded:: v23.08.00

- `PREFIX`/targets/<cuda_target_platform>/

``MODIFY_PREFIX_PATH``
When in a conda build environment the contents of `$ENV{PREFIX}` and `$ENV{BUILD_PREFIX}`
will be inserted to the front of :cmake:variable:`CMAKE_PREFIX_PATH <cmake:variable:CMAKE_PREFIX_PATH>`.
When in a conda build environment the contents of `$ENV{PREFIX}`,
`$ENV{PREFIX}`/targets/<cuda_target_platform>/`, and `$ENV{BUILD_PREFIX}` will be inserted to the
front of :cmake:variable:`CMAKE_PREFIX_PATH <cmake:variable:CMAKE_PREFIX_PATH>`.

When in a conda environment the contents of `$ENV{CONDA_PREFIX}` will be inserted to
the front of :cmake:variable:`CMAKE_PREFIX_PATH <cmake:variable:CMAKE_PREFIX_PATH>`.
Expand All @@ -51,6 +59,7 @@ Result Targets
`target_name` target will be created only if called from a conda environment.

#]=======================================================================]
# cmake-lint: disable=R0912,R0915
function(rapids_cmake_support_conda_env target)
list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.cmake.support_conda_env")

Expand All @@ -75,12 +84,31 @@ function(rapids_cmake_support_conda_env target)
set(prefix_paths)

if(in_conda_build)
# For conda-build we add the host conda environment prefix to the cmake search paths so that
# raw `find_file` or `find_library` calls will find CUDA components in the host environment
set(target_platform $ENV{cross_target_platform}) # when target != cross_target
if(NOT target_platform)
set(target_platform $ENV{target_platform})
endif()
if("${target_platform}" STREQUAL "linux-64")
set(targetsDir "targets/x86_64-linux")
elseif("${target_platform}" STREQUAL "linux-ppc64le")
set(targetsDir "targets/ppc64le-linux")
elseif("${target_platform}" STREQUAL "linux-aarch64")
set(targetsDir "targets/sbsa-linux")
endif()

target_include_directories(${target} INTERFACE "$ENV{PREFIX}/include"
"$ENV{BUILD_PREFIX}/include")
target_link_directories(${target} INTERFACE "$ENV{PREFIX}/lib" "$ENV{BUILD_PREFIX}/lib")

if(DEFINED CMAKE_SHARED_LIBRARY_RPATH_LINK_CUDA_FLAG
OR DEFINED CMAKE_SHARED_LIBRARY_RPATH_LINK_CXX_FLAG)
if(DEFINED targetsDir)
target_link_options(${target} INTERFACE
"$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{PREFIX}/${targetsDir}/lib>"
)
endif()
target_link_options(${target} INTERFACE
"$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{PREFIX}/lib>")
target_link_options(${target} INTERFACE
Expand All @@ -89,6 +117,9 @@ function(rapids_cmake_support_conda_env target)

if(modify_prefix_path)
list(PREPEND CMAKE_PREFIX_PATH "$ENV{PREFIX}" "$ENV{BUILD_PREFIX}")
if(DEFINED targetsDir)
list(PREPEND CMAKE_PREFIX_PATH "$ENV{PREFIX}/${targetsDir}")
endif()
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}" PARENT_SCOPE)
message(VERBOSE "Conda build detected, CMAKE_PREFIX_PATH set to: ${CMAKE_PREFIX_PATH}")
endif()
Expand Down
4 changes: 3 additions & 1 deletion testing/cmake/CMakeLists.txt
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 All @@ -21,6 +21,8 @@ add_cmake_config_test( build_type-multiple.cmake )
add_cmake_config_test( build_type-user-specified.cmake)

add_cmake_config_test( conda_env-build.cmake )
add_cmake_config_test( conda_env-cross-build-arm.cmake )
add_cmake_config_test( conda_env-cross-build-x86.cmake )
add_cmake_config_test( conda_env-invalid.cmake )
add_cmake_config_test( conda_env-prefix.cmake )

Expand Down
98 changes: 98 additions & 0 deletions testing/cmake/conda_env-cross-build-arm.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#=============================================================================
# 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}/cmake/support_conda_env.cmake)


set(ENV{CONDA_BUILD} "1")
set(ENV{BUILD_PREFIX} "/usr/local/build_prefix")
set(ENV{cross_target_platform} "linux-aarch64")
set(ENV{PREFIX} "/opt/local/prefix")
set(ENV{CONDA_PREFIX} "/opt/conda/prefix")

rapids_cmake_support_conda_env(conda_env)
if(NOT TARGET conda_env)
message(FATAL_ERROR "Expected target conda_env to exist")
endif()

get_target_property(include_dirs conda_env INTERFACE_INCLUDE_DIRECTORIES)
if( NOT "$ENV{BUILD_PREFIX}/include" IN_LIST include_dirs)
message(FATAL_ERROR "Expected env{BUILD_PREFIX} to be in the include dirs of `conda_env`")
endif()
if( NOT "$ENV{PREFIX}/include" IN_LIST include_dirs)
message(FATAL_ERROR "Expected env{PREFIX} to be in the include dirs of `conda_env`")
endif()
if("$ENV{CONDA_PREFIX}/include" IN_LIST include_dirs)
message(FATAL_ERROR "Not expected for env{CONDA_PREFIX} to be in the include dirs of `conda_env`")
endif()

get_target_property(link_dirs conda_env INTERFACE_LINK_DIRECTORIES)
if( NOT "$ENV{BUILD_PREFIX}/lib" IN_LIST link_dirs)
message(FATAL_ERROR "Expected env{BUILD_PREFIX} to be in the link dirs of `conda_env`")
endif()
if( NOT "$ENV{PREFIX}/lib" IN_LIST link_dirs)
message(FATAL_ERROR "Expected env{PREFIX} to be in the link dirs of `conda_env`")
endif()
if("$ENV{CONDA_PREFIX}/lib" IN_LIST link_dirs)
message(FATAL_ERROR "Not expected for env{CONDA_PREFIX} to be in the link dirs of `conda_env`")
endif()

get_target_property(link_options conda_env INTERFACE_LINK_OPTIONS)
message(STATUS "link_options: ${link_options}")
if( NOT "$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{BUILD_PREFIX}/lib>" IN_LIST link_options)
message(FATAL_ERROR "Expected rpath-link=env{BUILD_PREFIX} to be in the link options of `conda_env`")
endif()
if( NOT "$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{PREFIX}/lib>" IN_LIST link_options)
message(FATAL_ERROR "Expected rpath-link=env{PREFIX} to be in the link options of `conda_env`")
endif()
if( NOT "$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{PREFIX}/targets/sbsa-linux/lib>" IN_LIST link_options)
message(FATAL_ERROR "Expected rpath-link=env{PREFIX}/targets/sbsa-linux/ to be in the link options of `conda_env`")
endif()
if("$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{CONDA_PREFIX}/lib>" IN_LIST link_options)
message(FATAL_ERROR "Not expected for rpath-link=env{CONDA_PREFIX} to be in the link options of `conda_env`")
endif()

# No effect as the target already exists
set(before_call_value "${CMAKE_PREFIX_PATH}" )
rapids_cmake_support_conda_env(conda_env MODIFY_PREFIX_PATH)
if(NOT ("${before_call_value}" STREQUAL "${CMAKE_PREFIX_PATH}") )
message(FATAL_ERROR "Expected rapids_cmake_support_conda_env not to change CMAKE_PREFIX_PATH")
endif()

# New target being used, so this should modify CMAKE_PREFIX_PATH
set(CMAKE_PREFIX_PATH "placeholder" )
rapids_cmake_support_conda_env(conda_env_modify MODIFY_PREFIX_PATH)
if(NOT TARGET conda_env_modify)
message(FATAL_ERROR "Expected target conda_env_modify to exist")
endif()

list(LENGTH CMAKE_PREFIX_PATH len)
if( len GREATER 4)
message(FATAL_ERROR "CMAKE_PREFIX_PATH length is wrong after MODIFY_PREFIX_PATH")
endif()

list(GET CMAKE_PREFIX_PATH 0 first_value)
list(GET CMAKE_PREFIX_PATH 1 second_value)
list(GET CMAKE_PREFIX_PATH 2 third_value)
list(GET CMAKE_PREFIX_PATH 3 fourth_value)
set(correct_list "$ENV{PREFIX}/targets/sbsa-linux" "$ENV{PREFIX}" "$ENV{BUILD_PREFIX}" "placeholder")
set(actual_list "${first_value}" "${second_value}" "${third_value}" "${fourth_value}")
foreach(correct actual IN ZIP_LISTS correct_list actual_list)
if(NOT correct STREQUAL actual)
message(STATUS "correct: ${correct}")
message(STATUS "actual: ${actual}")
message(FATAL_ERROR "MODIFY_PREFIX_PATH failed")
endif()
endforeach()
99 changes: 99 additions & 0 deletions testing/cmake/conda_env-cross-build-x86.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#=============================================================================
# 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}/cmake/support_conda_env.cmake)


set(ENV{CONDA_BUILD} "1")
set(ENV{BUILD_PREFIX} "/usr/local/build_prefix")
set(ENV{target_platform} "linux-64")
set(ENV{PREFIX} "/opt/local/prefix")
set(ENV{CONDA_PREFIX} "/opt/conda/prefix")

rapids_cmake_support_conda_env(conda_env)
if(NOT TARGET conda_env)
message(FATAL_ERROR "Expected target conda_env to exist")
endif()

get_target_property(include_dirs conda_env INTERFACE_INCLUDE_DIRECTORIES)
if( NOT "$ENV{BUILD_PREFIX}/include" IN_LIST include_dirs)
message(FATAL_ERROR "Expected env{BUILD_PREFIX} to be in the include dirs of `conda_env`")
endif()
if( NOT "$ENV{PREFIX}/include" IN_LIST include_dirs)
message(FATAL_ERROR "Expected env{PREFIX} to be in the include dirs of `conda_env`")
endif()
if("$ENV{CONDA_PREFIX}/include" IN_LIST include_dirs)
message(FATAL_ERROR "Not expected for env{CONDA_PREFIX} to be in the include dirs of `conda_env`")
endif()

get_target_property(link_dirs conda_env INTERFACE_LINK_DIRECTORIES)
if( NOT "$ENV{BUILD_PREFIX}/lib" IN_LIST link_dirs)
message(FATAL_ERROR "Expected env{BUILD_PREFIX} to be in the link dirs of `conda_env`")
endif()
if( NOT "$ENV{PREFIX}/lib" IN_LIST link_dirs)
message(FATAL_ERROR "Expected env{PREFIX} to be in the link dirs of `conda_env`")
endif()
if("$ENV{CONDA_PREFIX}/lib" IN_LIST link_dirs)
message(FATAL_ERROR "Not expected for env{CONDA_PREFIX} to be in the link dirs of `conda_env`")
endif()

get_target_property(link_options conda_env INTERFACE_LINK_OPTIONS)
message(STATUS "link_options: ${link_options}")
if( NOT "$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{BUILD_PREFIX}/lib>" IN_LIST link_options)
message(FATAL_ERROR "Expected rpath-link=env{BUILD_PREFIX} to be in the link options of `conda_env`")
endif()
if( NOT "$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{PREFIX}/lib>" IN_LIST link_options)
message(FATAL_ERROR "Expected rpath-link=env{PREFIX} to be in the link options of `conda_env`")
endif()
if( NOT "$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{PREFIX}/targets/x86_64-linux/lib>" IN_LIST link_options)
message(FATAL_ERROR "Expected rpath-link=env{PREFIX}/targets/x86_64-linux/ to be in the link options of `conda_env`")
endif()
if("$<HOST_LINK:SHELL:LINKER:-rpath-link=$ENV{CONDA_PREFIX}/lib>" IN_LIST link_options)
message(FATAL_ERROR "Not expected for rpath-link=env{CONDA_PREFIX} to be in the link options of `conda_env`")
endif()

# No effect as the target already exists
set(before_call_value "${CMAKE_PREFIX_PATH}" )
rapids_cmake_support_conda_env(conda_env MODIFY_PREFIX_PATH)
if(NOT ("${before_call_value}" STREQUAL "${CMAKE_PREFIX_PATH}") )
message(FATAL_ERROR "Expected rapids_cmake_support_conda_env not to change CMAKE_PREFIX_PATH")
endif()

# New target being used, so this should modify CMAKE_PREFIX_PATH
set(CMAKE_PREFIX_PATH "placeholder" )
rapids_cmake_support_conda_env(conda_env_modify MODIFY_PREFIX_PATH)
if(NOT TARGET conda_env_modify)
message(FATAL_ERROR "Expected target conda_env_modify to exist")
endif()

list(LENGTH CMAKE_PREFIX_PATH len)
if( len GREATER 4)
message(FATAL_ERROR "CMAKE_PREFIX_PATH length is wrong after MODIFY_PREFIX_PATH")
endif()

list(GET CMAKE_PREFIX_PATH 0 first_value)
list(GET CMAKE_PREFIX_PATH 1 second_value)
list(GET CMAKE_PREFIX_PATH 2 third_value)
list(GET CMAKE_PREFIX_PATH 3 fourth_value)
set(correct_list "$ENV{PREFIX}/targets/x86_64-linux" "$ENV{PREFIX}" "$ENV{BUILD_PREFIX}" "placeholder")
set(actual_list "${first_value}" "${second_value}" "${third_value}" "${fourth_value}")

foreach(correct actual IN ZIP_LISTS correct_list actual_list)
if(NOT correct STREQUAL actual)
message(STATUS "correct: ${correct}")
message(STATUS "actual: ${actual}")
message(FATAL_ERROR "MODIFY_PREFIX_PATH failed")
endif()
endforeach()

0 comments on commit 207d126

Please sign in to comment.