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)