Use FindCUDAToolkit for CMake >= 3.17 - Enables relocatable installs if the CUDA libraries are not installed in a location on the LD_LIBRARY_PATH. - Also bump the minimum CMake version to 3.11 to reflect the issue reported in #903. Change-Id: I333882b7238c76104d739c7054f29cc35cc4e919
diff --git a/CMakeLists.txt b/CMakeLists.txt index b5d0efe..01f47b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -29,7 +29,7 @@ # Authors: keir@google.com (Keir Mierle) # alexs.mac@gmail.com (Alex Stewart) -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.11) if (POLICY CMP0074) # Added in CMake 3.12 # FindTBB.cmake uses TBB_ROOT in a way that is historical, but also compliant @@ -231,27 +231,69 @@ endif (Eigen3_FOUND) if (USE_CUDA) - find_package(CUDA QUIET) - if (CUDA_FOUND) - message("-- Found CUDA version ${CUDA_VERSION}: " - "${CUDA_LIBRARIES};" - "${CUDA_cusolver_LIBRARY};" - "${CUDA_cusparse_LIBRARY}") - if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.18") - # Support Maxwell, Pascal, Volta, Turing, and Ampere GPUs. - set(CMAKE_CUDA_ARCHITECTURES "50;60;70;80") - message("-- Setting CUDA Architecture to ${CMAKE_CUDA_ARCHITECTURES}") - endif() - enable_language(CUDA) - else (CUDA_FOUND) - message("-- Did not find CUDA library, disabling CUDA support.") - update_cache_variable(USE_CUDA OFF) - list(APPEND CERES_COMPILE_OPTIONS CERES_NO_CUDA) - endif (CUDA_FOUND) -else (USE_CUDA) + if (CMAKE_VERSION VERSION_LESS 3.17) + # On older versions of CMake (20.04 default is 3.16) FindCUDAToolkit was + # not available, but FindCUDA was deprecated. To avoid special-case handling + # elsewhere, emulate the effects of FindCUDAToolkit locally in terms of the + # expected CMake imported targets and defined variables. This can be removed + # from as soon as the min CMake version is >= 3.17. + find_package(CUDA QUIET) + if (CUDA_FOUND) + message("-- Found CUDA version ${CUDA_VERSION} installed in: " + "${CUDA_TOOLKIT_ROOT_DIR} via legacy (< 3.17) CMake module. " + "Using the legacy CMake module means that any installation of " + "Ceres will require that the CUDA libraries be installed in a " + "location included in the LD_LIBRARY_PATH.") + enable_language(CUDA) + + macro(DECLARE_IMPORTED_CUDA_TARGET COMPONENT) + add_library(CUDA::${COMPONENT} INTERFACE IMPORTED) + target_include_directories( + CUDA::${COMPONENT} INTERFACE ${CUDA_INCLUDE_DIRS}) + target_link_libraries( + CUDA::${COMPONENT} INTERFACE ${CUDA_${COMPONENT}_LIBRARY} ${ARGN}) + endmacro() + + declare_imported_cuda_target(cublas) + declare_imported_cuda_target(cusolver) + declare_imported_cuda_target(cusparse) + declare_imported_cuda_target(cudart ${CUDA_LIBRARIES}) + + set(CUDAToolkit_BIN_DIR ${CUDA_TOOLKIT_ROOT_DIR}/bin) + + else (CUDA_FOUND) + message("-- Did not find CUDA, disabling CUDA support.") + update_cache_variable(USE_CUDA OFF) + endif (CUDA_FOUND) + else (CMAKE_VERSION VERSION_LESS 3.17) + find_package(CUDAToolkit QUIET) + if (CUDAToolkit_FOUND) + message("-- Found CUDA version ${CUDAToolkit_VERSION} installed in: " + "${CUDAToolkit_TARGET_DIR}") + set(CUDAToolkit_DEPENDENCY + "find_dependency(CUDAToolkit ${CUDAToolkit_VERSION})") + enable_language(CUDA) + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.18") + # Support Maxwell, Pascal, Volta, Turing, and Ampere GPUs. + set(CMAKE_CUDA_ARCHITECTURES "50;60;70;80") + message("-- Setting CUDA Architecture to ${CMAKE_CUDA_ARCHITECTURES}") + endif() + list(APPEND CERES_CUDA_LIBRARIES + CUDA::cublas + CUDA::cudart + CUDA::cusolver + CUDA::cusparse) + else (CUDAToolkit_FOUND) + message("-- Did not find CUDA, disabling CUDA support.") + update_cache_variable(USE_CUDA OFF) + endif (CUDAToolkit_FOUND) + endif (CMAKE_VERSION VERSION_LESS 3.17) +endif (USE_CUDA) +if (NOT USE_CUDA) message("-- Building without CUDA.") list(APPEND CERES_COMPILE_OPTIONS CERES_NO_CUDA) -endif (USE_CUDA) +endif (NOT USE_CUDA) + if (LAPACK) find_package(LAPACK QUIET) if (LAPACK_FOUND)
diff --git a/cmake/CeresConfig.cmake.in b/cmake/CeresConfig.cmake.in index 33d8078..bb6cc43 100644 --- a/cmake/CeresConfig.cmake.in +++ b/cmake/CeresConfig.cmake.in
@@ -181,6 +181,7 @@ @OpenMP_DEPENDENCY@ @SuiteSparse_DEPENDENCY@ @Threads_DEPENDENCY@ +@CUDAToolkit_DEPENDENCY@ # As imported CMake targets are not re-exported when a dependent target is # exported, we must invoke find_package(XXX) here to reload the definition
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index 21caa8d..4a85e8b 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -140,20 +140,19 @@ endif() if (USE_CUDA) - list(APPEND - CERES_LIBRARY_PRIVATE_DEPENDENCIES - ${CUDA_LIBRARIES} - ${CUDA_cublas_LIBRARY} - ${CUDA_cusolver_LIBRARY} - ${CUDA_cusparse_LIBRARY}) + list(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES + CUDA::cublas + CUDA::cudart + CUDA::cusolver + CUDA::cusparse) if (BUILD_TESTING AND GFLAGS) add_test( NAME cuda_memcheck_dense_qr_test - COMMAND ${CUDA_TOOLKIT_ROOT_DIR}/bin/cuda-memcheck --leak-check full + COMMAND ${CUDAToolkit_BIN_DIR}/cuda-memcheck --leak-check full $<TARGET_FILE:cuda_dense_qr_test>) add_test( NAME cuda_memcheck_dense_cholesky_test - COMMAND ${CUDA_TOOLKIT_ROOT_DIR}/bin/cuda-memcheck --leak-check full + COMMAND ${CUDAToolkit_BIN_DIR}/cuda-memcheck --leak-check full $<TARGET_FILE:cuda_dense_cholesky_test>) endif (BUILD_TESTING AND GFLAGS) set_source_files_properties(cuda_kernels.cu.cc PROPERTIES LANGUAGE CUDA) @@ -393,10 +392,6 @@ list(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES_INCLUDE_DIRS ${AccelerateSparse_INCLUDE_DIRS}) endif() -if (USE_CUDA) - list(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES_INCLUDE_DIRS - ${CUDA_INCLUDE_DIRS}) -endif() # Add include locations for optional dependencies to the Ceres target without # duplication. list(REMOVE_DUPLICATES CERES_LIBRARY_PRIVATE_DEPENDENCIES_INCLUDE_DIRS) @@ -449,7 +444,11 @@ target_include_directories(${NAME}_test PRIVATE ${Ceres_SOURCE_DIR}/internal/ceres ${CERES_LIBRARY_PRIVATE_DEPENDENCIES_INCLUDE_DIRS}) - target_link_libraries(${NAME}_test PRIVATE gtest test_util ceres_static) + # Some tests include direct references/includes of private dependency + # headers which are not propagated via the ceres targets, so link them + # explicitly. + target_link_libraries(${NAME}_test PRIVATE gtest test_util ceres_static + ${CERES_LIBRARY_PRIVATE_DEPENDENCIES}) # covariance_test uses SuiteSparseQR.hpp. However, since SuiteSparse import # targets are private (link only) dependencies not propagated to consumers, @@ -572,8 +571,11 @@ target_include_directories(${BENCHMARK_TARGET} PRIVATE ${Ceres_SOURCE_DIR}/internal ${CERES_LIBRARY_PRIVATE_DEPENDENCIES_INCLUDE_DIRS}) + # Benchmarks include direct references/includes of private dependency headers + # which are not propagated via the ceres targets, so link them explicitly. target_link_libraries(${BENCHMARK_TARGET} - PRIVATE benchmark::benchmark ceres_static) + PRIVATE benchmark::benchmark ceres_static + ${CERES_LIBRARY_PRIVATE_DEPENDENCIES}) endmacro() if (BUILD_BENCHMARKS)