diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt index 5c66cad9fe..59f4a4586c 100644 --- a/c/CMakeLists.txt +++ b/c/CMakeLists.txt @@ -33,7 +33,11 @@ option(CUVSC_STATIC_CUVS_LIBRARY "Link against statical version of libcuvs" OFF) # Check if cuVS is already available. If so, it is the user's responsibility to ensure that the # CMake package is also available at build time of the Python cuvs package. if(NOT TARGET cuvs::cuvs) - find_package(cuvs "${RAPIDS_VERSION}" REQUIRED) + if(CUVSC_STATIC_CUVS_LIBRARY) + find_package(cuvs "${RAPIDS_VERSION}" REQUIRED COMPONENTS cuvs_static) + else() + find_package(cuvs "${RAPIDS_VERSION}" REQUIRED COMPONENTS cuvs_shared) + endif() else() set(BUILDING_FROM_CUVS ON) endif() @@ -167,40 +171,29 @@ if(PROJECT_IS_TOP_LEVEL) include(CPack) # Add CUDAToolkit as an export dependency - rapids_export_package(INSTALL CUDAToolkit cuvs-c-exports) - rapids_export_package(BUILD CUDAToolkit cuvs-c-exports) + rapids_export_package(INSTALL CUDAToolkit cuvs-exports) + rapids_export_package(BUILD CUDAToolkit cuvs-exports) install( TARGETS cuvs_c DESTINATION ${lib_dir} - COMPONENT cuvs_c + COMPONENT c_api EXPORT cuvs-c-exports ) - - rapids_export( - INSTALL cuvs_c - VERSION "${RAPIDS_VERSION}" - EXPORT_SET cuvs-c-exports - GLOBAL_TARGETS cuvs_c - NAMESPACE cuvs:: - ) - rapids_export( - BUILD cuvs_c - VERSION "${RAPIDS_VERSION}" - EXPORT_SET cuvs-c-exports - GLOBAL_TARGETS cuvs_c - NAMESPACE cuvs:: - ) install( DIRECTORY include/cuvs - COMPONENT cuvs_c + COMPONENT c_api DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/include/cuvs/core/c_config.h - COMPONENT cuvs_c + COMPONENT c_api DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cuvs/core/ ) + + include(../cpp/cmake/modules/generate_cuvs_export.cmake) + generate_cuvs_export(CLIB COMPONENTS c_api EXPORT_SETS cuvs-c-exports) + endif() # ################################################################################################## diff --git a/conda/recipes/libcuvs/recipe.yaml b/conda/recipes/libcuvs/recipe.yaml index 8b4516dc36..45630be48d 100644 --- a/conda/recipes/libcuvs/recipe.yaml +++ b/conda/recipes/libcuvs/recipe.yaml @@ -78,6 +78,61 @@ cache: - mkl-devel =2023 outputs: + - package: + name: libcuvs-headers + version: ${{ version }} + build: + string: cuda${{ cuda_major }}_${{ date_string }}_${{ head_rev }} + dynamic_linking: + overlinking_behavior: "error" + prefix_detection: + ignore_binary_files: True + script: + content: | + cmake --install cpp/build --component cuvs_cpp_headers + requirements: + build: + - cmake ${{ cmake_version }} + - ${{ stdlib("c") }} + host: + - librmm =${{ minor_version }} + - libraft-headers =${{ minor_version }} + - nccl ${{ nccl_version }} + - cuda-version =${{ cuda_version }} + - cuda-cudart-dev + - cuda-profiler-api + - libcublas-dev + - libcurand-dev + - libcusolver-dev + - libcusparse-dev + run: + - ${{ pin_compatible("cuda-version", upper_bound="x", lower_bound="x") }} + - libraft-headers =${{ minor_version }} + - librmm =${{ minor_version }} + - nccl + - cuda-cudart + - libcublas + - libcurand + - libcusolver + - libcusparse + ignore_run_exports: + by_name: + - cuda-cudart + - cuda-version + - libaio + - libboost + - libcublas + - libcurand + - libcusolver + - libcusparse + - librmm + - mkl + - nccl + about: + homepage: ${{ load_from_file("python/libcuvs/pyproject.toml").project.urls.Homepage }} + license: ${{ load_from_file("python/libcuvs/pyproject.toml").project.license.text }} + summary: ${{ load_from_file("python/libcuvs/pyproject.toml").project.description }} + - package: name: libcuvs version: ${{ version }} @@ -90,6 +145,7 @@ outputs: script: content: | cmake --install cpp/build --component cuvs + cmake --install cpp/build --component cuvs_shared cmake --install cpp/build --component c_api cmake --install cpp/build --component hnswlib requirements: @@ -97,6 +153,65 @@ outputs: - cmake ${{ cmake_version }} - ${{ stdlib("c") }} host: + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} + - librmm =${{ minor_version }} + - libraft-headers =${{ minor_version }} + - nccl ${{ nccl_version }} + - cuda-version =${{ cuda_version }} + - cuda-cudart-dev + - cuda-profiler-api + - libcublas-dev + - libcurand-dev + - libcusolver-dev + - libcusparse-dev + run: + - ${{ pin_compatible("cuda-version", upper_bound="x", lower_bound="x") }} + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} + - libraft-headers =${{ minor_version }} + - librmm =${{ minor_version }} + - nccl + - cuda-cudart + - libcublas + - libcurand + - libcusolver + - libcusparse + ignore_run_exports: + by_name: + - cuda-cudart + - cuda-version + - libaio + - libboost + - libcublas + - libcurand + - libcusolver + - libcusparse + - librmm + - mkl + - nccl + about: + homepage: ${{ load_from_file("python/libcuvs/pyproject.toml").project.urls.Homepage }} + license: ${{ load_from_file("python/libcuvs/pyproject.toml").project.license.text }} + summary: ${{ load_from_file("python/libcuvs/pyproject.toml").project.description }} + + - package: + name: libcuvs-static + version: ${{ version }} + build: + string: cuda${{ cuda_major }}_${{ date_string }}_${{ head_rev }} + dynamic_linking: + overlinking_behavior: "error" + prefix_detection: + ignore_binary_files: True + script: + content: | + cmake --install cpp/build --component cuvs_static + cmake --install cpp/build --component hnswlib + requirements: + build: + - cmake ${{ cmake_version }} + - ${{ stdlib("c") }} + host: + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} - librmm =${{ minor_version }} - libraft-headers =${{ minor_version }} - nccl ${{ nccl_version }} @@ -109,7 +224,9 @@ outputs: - libcusparse-dev run: - ${{ pin_compatible("cuda-version", upper_bound="x", lower_bound="x") }} + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} - libraft-headers =${{ minor_version }} + - librmm =${{ minor_version }} - nccl - cuda-cudart - libcublas @@ -152,6 +269,7 @@ outputs: - librmm =${{ minor_version }} - libraft-headers =${{ minor_version }} - nccl ${{ nccl_version }} + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} - ${{ pin_subpackage("libcuvs", exact=True) }} - cuda-version =${{ cuda_version }} - openblas # required by some CPU algos in benchmarks @@ -162,6 +280,7 @@ outputs: - libcusolver-dev - libcusparse-dev run: + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} - ${{ pin_subpackage("libcuvs", exact=True) }} - ${{ pin_compatible("cuda-version", upper_bound="x", lower_bound="x") }} - libraft-headers =${{ minor_version }} @@ -237,6 +356,7 @@ outputs: - ninja - ${{ stdlib("c") }} host: + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} - ${{ pin_subpackage("libcuvs", exact=True) }} - cuda-version =${{ cuda_version }} - libraft-headers =${{ minor_version }} @@ -249,6 +369,7 @@ outputs: - libcusolver-dev - libcusparse-dev run: + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} - ${{ pin_subpackage("libcuvs", exact=True) }} - ${{ pin_compatible("cuda-version", upper_bound="x", lower_bound="x") }} - nccl @@ -298,6 +419,7 @@ outputs: - cmake ${{ cmake_version }} - ${{ stdlib("c") }} host: + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} - ${{ pin_subpackage("libcuvs", exact=True) }} - cuda-cudart-dev - cuda-profiler-api @@ -317,6 +439,7 @@ outputs: - libboost-devel =1.87 - mkl-devel =2023 run: + - ${{ pin_subpackage("libcuvs-headers", exact=True) }} - ${{ pin_subpackage("libcuvs", exact=True) }} - ${{ pin_compatible("cuda-version", upper_bound="x", lower_bound="x") }} - cuda-cudart diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index af15e4a399..61a62649b5 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -70,6 +70,7 @@ if(BUILD_CPU_ONLY) set(BUILD_TESTS OFF) set(BUILD_C_LIBRARY OFF) set(BUILD_CAGRA_HNSWLIB OFF) + set(INSTALL_CPP_HEADERS OFF) elseif(NOT BUILD_SHARED_LIBS) set(BUILD_TESTS OFF) set(BUILD_C_LIBRARY OFF) @@ -207,6 +208,17 @@ endif() # ################################################################################################## # * cuvs --------------------------------------------------------------------- if(NOT BUILD_CPU_ONLY) + + add_library(cuvs_cpp_headers INTERFACE) + add_library(cuvs::cuvs_cpp_headers ALIAS cuvs_cpp_headers) + target_include_directories( + cuvs_cpp_headers + INTERFACE "$" + "$" + "$" + ) + target_link_libraries(cuvs_cpp_headers INTERFACE raft::raft rmm::rmm) + add_library( cuvs-cagra-search OBJECT src/neighbors/cagra_search_float.cu @@ -300,10 +312,7 @@ if(NOT BUILD_CPU_ONLY) CUDA_SEPARABLE_COMPILATION ON POSITION_INDEPENDENT_CODE ON ) - target_link_libraries(cuvs-cagra-search PRIVATE raft::raft) - target_include_directories( - cuvs-cagra-search PRIVATE "$" - ) + target_link_libraries(cuvs-cagra-search PRIVATE cuvs::cuvs_cpp_headers) target_compile_options( cuvs-cagra-search PRIVATE "$<$:${CUVS_CXX_FLAGS}>" "$<$:${CUVS_CUDA_FLAGS}>" @@ -552,16 +561,10 @@ if(NOT BUILD_CPU_ONLY) target_link_libraries( cuvs_objs - PRIVATE raft::raft rmm::rmm ${CUVS_CTK_MATH_DEPENDENCIES} + PRIVATE cuvs::cuvs_cpp_headers ${CUVS_CTK_MATH_DEPENDENCIES} $ $ ) - target_include_directories( - cuvs_objs - PUBLIC "$" - INTERFACE "$" - ) - # Endian detection include(TestBigEndian) test_big_endian(BIG_ENDIAN) @@ -620,17 +623,11 @@ if(NOT BUILD_CPU_ONLY) $<$:NVTX_ENABLED> ) - target_include_directories( - cuvs - PUBLIC "$" - "$" - "$" - ) - target_link_libraries( cuvs PUBLIC rmm::rmm raft::raft + cuvs::cuvs_cpp_headers ${CUVS_CTK_MATH_DEPENDENCIES} $> $> @@ -682,16 +679,11 @@ SECTIONS # ensure CUDA symbols aren't relocated to the middle of the debug build binaries target_link_options(cuvs_static PRIVATE $) - target_include_directories( - cuvs_static - PUBLIC "$" - "$" - "$" - ) target_link_libraries( cuvs_static PUBLIC rmm::rmm raft::raft + cuvs::cuvs_cpp_headers ${CUVS_CTK_MATH_DEPENDENCIES} $ # needs to be public for DT_NEEDED $> # header only @@ -737,72 +729,52 @@ target_compile_definitions(cuvs::cuvs INTERFACE $<$:NVTX_ENAB include(GNUInstallDirs) include(CPack) - install( - TARGETS ${_cuvs_lib_targets} - DESTINATION ${lib_dir} - COMPONENT cuvs - EXPORT cuvs-exports - ) - - install( - DIRECTORY include/cuvs - COMPONENT cuvs - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) - - if(BUILD_C_LIBRARY) + set(target_names cuvs cuvs_static cuvs_cpp_headers cuvs_c) + set(component_names cuvs_shared cuvs_static cuvs_cpp_headers c_api) + set(export_names cuvs-shared-exports cuvs-static-exports cuvs-cpp-headers-exports cuvs-c-exports) + foreach(target component export IN ZIP_LISTS target_names component_names export_names) + if(TARGET ${target}) + install( + TARGETS ${target} + DESTINATION ${lib_dir} + COMPONENT ${component} + EXPORT ${export} + ) + + list(APPEND cuvs_components ${component}) + list(APPEND cuvs_export_sets ${export}) + endif() + endforeach() + + if(TARGET cuvs_cpp_headers) install( - TARGETS cuvs_c - DESTINATION ${lib_dir} - COMPONENT c_api - EXPORT cuvs-c-exports + DIRECTORY include/cuvs + COMPONENT cuvs_cpp_headers + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/include/cuvs/version_config.h + COMPONENT cuvs_cpp_headers + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cuvs + ) + endif() + if(TARGET cuvs_c) install( DIRECTORY ../c/include/cuvs/ COMPONENT c_api DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cuvs ) - install( FILES ${CUVS_C_BINARY_DIR}/include/cuvs/core/c_config.h - COMPONENT cuvs + COMPONENT c_api DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cuvs/core/ ) endif() - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/include/cuvs/version_config.h - COMPONENT cuvs - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cuvs - ) - - if(TARGET cuvs_c) - list(APPEND cuvs_components c_api) - list(APPEND cuvs_export_sets cuvs-c-exports) - set(CUVS_C_TARGET cuvs_c) - endif() + include(cmake/modules/generate_cuvs_export.cmake) + generate_cuvs_export(COMPONENTS ${cuvs_components} EXPORT_SETS ${cuvs_export_sets}) - # Use `rapids_export` for 22.04 as it will have COMPONENT support - rapids_export( - INSTALL cuvs - EXPORT_SET cuvs-exports - COMPONENTS ${cuvs_components} - COMPONENTS_EXPORT_SET ${cuvs_export_sets} - GLOBAL_TARGETS cuvs ${CUVS_C_TARGET} - NAMESPACE cuvs:: - ) - - # ################################################################################################ - # * build export ------------------------------------------------------------- - rapids_export( - BUILD cuvs - EXPORT_SET cuvs-exports - COMPONENTS ${cuvs_components} - COMPONENTS_EXPORT_SET ${cuvs_export_sets} - GLOBAL_TARGETS cuvs ${CUVS_C_TARGET} - NAMESPACE cuvs:: - ) endif() # ################################################################################################## diff --git a/cpp/cmake/modules/generate_cuvs_export.cmake b/cpp/cmake/modules/generate_cuvs_export.cmake new file mode 100644 index 0000000000..c2748c25e1 --- /dev/null +++ b/cpp/cmake/modules/generate_cuvs_export.cmake @@ -0,0 +1,85 @@ +# ============================================================================= +# cmake-format: off +# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION. +# SPDX-License-Identifier: Apache-2.0 +# cmake-format: on +# ============================================================================= + +function(generate_cuvs_export) + set(options "CLIB") + set(one_value "") + set(multi_value EXPORT_SETS COMPONENTS) + cmake_parse_arguments(_CUVS_RAPIDS "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + set(placehold_name "cuvs_placeholder") + if(_CUVS_RAPIDS_CLIB) + string(APPEND placehold_name "_c") + endif() + + # We need a placeholder target in cuvs-exports so that we can generate an export set since all the + # real targets are conditional + # + if(NOT TARGET cuvs::${placehold_name}) + add_library(${placehold_name} INTERFACE) + add_library(cuvs::${placehold_name} ALIAS ${placehold_name}) + install(TARGETS ${placehold_name} EXPORT cuvs-exports) + endif() + + # tasks we need to add in dependencies file inclusion as well + + set(cuvs_final_code_block + [=[ + + set(_cuvs_implicit_comp_names cuvs_cpp_headers cuvs_shared cuvs_static) + set(_cuvs_implicit_target_names cuvs_cpp_headers cuvs cuvs_static) + foreach(_cuvs_comp _cuvs_target IN ZIP_LISTS _cuvs_implicit_comp_names _cuvs_implicit_target_names) + if(NOT TARGET cuvs::${_cuvs_target}) + file(GLOB cuvs_component_dep_files LIST_DIRECTORIES FALSE + "${CMAKE_CURRENT_LIST_DIR}/cuvs-${_cuvs_comp}*-dependencies.cmake") + foreach(f IN LISTS cuvs_component_dep_files) + include("${f}") + endforeach() + file(GLOB cuvs_component_target_files LIST_DIRECTORIES FALSE + "${CMAKE_CURRENT_LIST_DIR}/cuvs-${_cuvs_comp}*-targets.cmake") + foreach(f IN LISTS cuvs_component_target_files) + include("${f}") + endforeach() + endif() + endforeach() + + foreach(target IN LISTS rapids_namespaced_global_targets) + if(TARGET ${target}) + get_target_property(_is_imported ${target} IMPORTED) + get_target_property(_already_global ${target} IMPORTED_GLOBAL) + if(_is_imported AND NOT _already_global) + set_target_properties(${target} PROPERTIES IMPORTED_GLOBAL TRUE) + endif() + endif() + endforeach() + ]=] + ) + + rapids_export( + INSTALL cuvs + VERSION "${RAPIDS_VERSION}" + EXPORT_SET cuvs-exports + COMPONENTS ${_CUVS_RAPIDS_COMPONENTS} + COMPONENTS_EXPORT_SET ${_CUVS_RAPIDS_EXPORT_SETS} + GLOBAL_TARGETS cuvs cuvs_cpp_headers cuvs_static cuvs_c + NAMESPACE cuvs:: + FINAL_CODE_BLOCK cuvs_final_code_block + ) + + # ################################################################################################ + # * build export ------------------------------------------------------------- + rapids_export( + BUILD cuvs + VERSION "${RAPIDS_VERSION}" + EXPORT_SET cuvs-exports + COMPONENTS ${_CUVS_RAPIDS_COMPONENTS} + COMPONENTS_EXPORT_SET ${_CUVS_RAPIDS_EXPORT_SETS} + GLOBAL_TARGETS cuvs cuvs_cpp_headers cuvs_static cuvs_c + NAMESPACE cuvs:: + FINAL_CODE_BLOCK cuvs_final_code_block + ) +endfunction() diff --git a/cpp/cmake/thirdparty/get_hnswlib.cmake b/cpp/cmake/thirdparty/get_hnswlib.cmake index 07c099426a..220dc8df2c 100644 --- a/cpp/cmake/thirdparty/get_hnswlib.cmake +++ b/cpp/cmake/thirdparty/get_hnswlib.cmake @@ -19,8 +19,6 @@ function(find_and_configure_hnswlib) FIND_VAR find_args CPM_VAR cpm_args TO_INSTALL_VAR to_install - BUILD_EXPORT_SET cuvs-exports - INSTALL_EXPORT_SET cuvs-exports ) rapids_cpm_find(