CUDAToolkit.cmake 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file Copyright.txt or https://cmake.org/licensing for details.
  3. # This file is for sharing code for finding basic CUDA toolkit information between
  4. # CMakeDetermineCUDACompiler.cmake and FindCUDAToolkit.cmake.
  5. # For NVCC we can easily deduce the SDK binary directory from the compiler path.
  6. if(CMAKE_CUDA_COMPILER_LOADED AND NOT CUDAToolkit_BIN_DIR AND CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
  7. get_filename_component(cuda_dir "${CMAKE_CUDA_COMPILER}" DIRECTORY)
  8. set(CUDAToolkit_BIN_DIR "${cuda_dir}" CACHE PATH "")
  9. mark_as_advanced(CUDAToolkit_BIN_DIR)
  10. unset(cuda_dir)
  11. endif()
  12. # Try language- or user-provided path first.
  13. if(CUDAToolkit_BIN_DIR)
  14. find_program(CUDAToolkit_NVCC_EXECUTABLE
  15. NAMES nvcc nvcc.exe
  16. PATHS ${CUDAToolkit_BIN_DIR}
  17. NO_DEFAULT_PATH
  18. )
  19. endif()
  20. # Search using CUDAToolkit_ROOT
  21. find_program(CUDAToolkit_NVCC_EXECUTABLE
  22. NAMES nvcc nvcc.exe
  23. PATHS ENV CUDA_PATH
  24. PATH_SUFFIXES bin
  25. )
  26. # If the user specified CUDAToolkit_ROOT but nvcc could not be found, this is an error.
  27. if(NOT CUDAToolkit_NVCC_EXECUTABLE AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT}))
  28. # Declare error messages now, print later depending on find_package args.
  29. set(fail_base "Could not find nvcc executable in path specified by")
  30. set(cuda_root_fail "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}")
  31. set(env_cuda_root_fail "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}")
  32. if(CUDAToolkit_FIND_REQUIRED)
  33. if(DEFINED CUDAToolkit_ROOT)
  34. message(FATAL_ERROR ${cuda_root_fail})
  35. elseif(DEFINED ENV{CUDAToolkit_ROOT})
  36. message(FATAL_ERROR ${env_cuda_root_fail})
  37. endif()
  38. else()
  39. if(NOT CUDAToolkit_FIND_QUIETLY)
  40. if(DEFINED CUDAToolkit_ROOT)
  41. message(STATUS ${cuda_root_fail})
  42. elseif(DEFINED ENV{CUDAToolkit_ROOT})
  43. message(STATUS ${env_cuda_root_fail})
  44. endif()
  45. endif()
  46. set(CUDAToolkit_FOUND FALSE)
  47. unset(fail_base)
  48. unset(cuda_root_fail)
  49. unset(env_cuda_root_fail)
  50. return()
  51. endif()
  52. endif()
  53. # CUDAToolkit_ROOT cmake / env variable not specified, try platform defaults.
  54. #
  55. # - Linux: /usr/local/cuda-X.Y
  56. # - macOS: /Developer/NVIDIA/CUDA-X.Y
  57. # - Windows: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y
  58. #
  59. # We will also search the default symlink location /usr/local/cuda first since
  60. # if CUDAToolkit_ROOT is not specified, it is assumed that the symlinked
  61. # directory is the desired location.
  62. if(NOT CUDAToolkit_NVCC_EXECUTABLE)
  63. if(UNIX)
  64. if(NOT APPLE)
  65. set(platform_base "/usr/local/cuda-")
  66. else()
  67. set(platform_base "/Developer/NVIDIA/CUDA-")
  68. endif()
  69. else()
  70. set(platform_base "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v")
  71. endif()
  72. # Build out a descending list of possible cuda installations, e.g.
  73. file(GLOB possible_paths "${platform_base}*")
  74. # Iterate the glob results and create a descending list.
  75. set(possible_versions)
  76. foreach (p ${possible_paths})
  77. # Extract version number from end of string
  78. string(REGEX MATCH "[0-9][0-9]?\\.[0-9]$" p_version ${p})
  79. if(IS_DIRECTORY ${p} AND p_version)
  80. list(APPEND possible_versions ${p_version})
  81. endif()
  82. endforeach()
  83. # Cannot use list(SORT) because that is alphabetical, we need numerical.
  84. # NOTE: this is not an efficient sorting strategy. But even if a user had
  85. # every possible version of CUDA installed, this wouldn't create any
  86. # significant overhead.
  87. set(versions)
  88. foreach (v ${possible_versions})
  89. list(LENGTH versions num_versions)
  90. # First version, nothing to compare with so just append.
  91. if(num_versions EQUAL 0)
  92. list(APPEND versions ${v})
  93. else()
  94. # Loop through list. Insert at an index when comparison is
  95. # VERSION_GREATER since we want a descending list. Duplicates will not
  96. # happen since this came from a glob list of directories.
  97. set(i 0)
  98. set(early_terminate FALSE)
  99. while (i LESS num_versions)
  100. list(GET versions ${i} curr)
  101. if(v VERSION_GREATER curr)
  102. list(INSERT versions ${i} ${v})
  103. set(early_terminate TRUE)
  104. break()
  105. endif()
  106. math(EXPR i "${i} + 1")
  107. endwhile()
  108. # If it did not get inserted, place it at the end.
  109. if(NOT early_terminate)
  110. list(APPEND versions ${v})
  111. endif()
  112. endif()
  113. endforeach()
  114. # With a descending list of versions, populate possible paths to search.
  115. set(search_paths)
  116. foreach (v ${versions})
  117. list(APPEND search_paths "${platform_base}${v}")
  118. endforeach()
  119. # Force the global default /usr/local/cuda to the front on Unix.
  120. if(UNIX)
  121. list(INSERT search_paths 0 "/usr/local/cuda")
  122. endif()
  123. # Now search for nvcc again using the platform default search paths.
  124. find_program(CUDAToolkit_NVCC_EXECUTABLE
  125. NAMES nvcc nvcc.exe
  126. PATHS ${search_paths}
  127. PATH_SUFFIXES bin
  128. )
  129. # We are done with these variables now, cleanup for caller.
  130. unset(platform_base)
  131. unset(possible_paths)
  132. unset(possible_versions)
  133. unset(versions)
  134. unset(i)
  135. unset(early_terminate)
  136. unset(search_paths)
  137. if(NOT CUDAToolkit_NVCC_EXECUTABLE)
  138. if(CUDAToolkit_FIND_REQUIRED)
  139. message(FATAL_ERROR "Could not find nvcc, please set CUDAToolkit_ROOT.")
  140. elseif(NOT CUDAToolkit_FIND_QUIETLY)
  141. message(STATUS "Could not find nvcc, please set CUDAToolkit_ROOT.")
  142. endif()
  143. set(CUDAToolkit_FOUND FALSE)
  144. return()
  145. endif()
  146. endif()
  147. if(NOT CUDAToolkit_BIN_DIR AND CUDAToolkit_NVCC_EXECUTABLE)
  148. get_filename_component(cuda_dir "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY)
  149. set(CUDAToolkit_BIN_DIR "${cuda_dir}" CACHE PATH "" FORCE)
  150. mark_as_advanced(CUDAToolkit_BIN_DIR)
  151. unset(cuda_dir)
  152. endif()
  153. get_filename_component(CUDAToolkit_ROOT_DIR ${CUDAToolkit_BIN_DIR} DIRECTORY ABSOLUTE)
  154. # Handle cross compilation
  155. if(CMAKE_CROSSCOMPILING)
  156. if(CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7-a")
  157. # Support for NVPACK
  158. set(CUDAToolkit_TARGET_NAME "armv7-linux-androideabi")
  159. elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
  160. # Support for arm cross compilation
  161. set(CUDAToolkit_TARGET_NAME "armv7-linux-gnueabihf")
  162. elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
  163. # Support for aarch64 cross compilation
  164. if(ANDROID_ARCH_NAME STREQUAL "arm64")
  165. set(CUDAToolkit_TARGET_NAME "aarch64-linux-androideabi")
  166. else()
  167. set(CUDAToolkit_TARGET_NAME "aarch64-linux")
  168. endif(ANDROID_ARCH_NAME STREQUAL "arm64")
  169. elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
  170. set(CUDAToolkit_TARGET_NAME "x86_64-linux")
  171. endif()
  172. if(EXISTS "${CUDAToolkit_ROOT_DIR}/targets/${CUDAToolkit_TARGET_NAME}")
  173. set(CUDAToolkit_TARGET_DIR "${CUDAToolkit_ROOT_DIR}/targets/${CUDAToolkit_TARGET_NAME}")
  174. # add known CUDA target root path to the set of directories we search for programs, libraries and headers
  175. list(PREPEND CMAKE_FIND_ROOT_PATH "${CUDAToolkit_TARGET_DIR}")
  176. # Mark that we need to pop the root search path changes after we have
  177. # found all cuda libraries so that searches for our cross-compilation
  178. # libraries work when another cuda sdk is in CMAKE_PREFIX_PATH or
  179. # PATh
  180. set(_CUDAToolkit_Pop_ROOT_PATH True)
  181. endif()
  182. else()
  183. # Not cross compiling
  184. set(CUDAToolkit_TARGET_DIR "${CUDAToolkit_ROOT_DIR}")
  185. # Now that we have the real ROOT_DIR, find components inside it.
  186. list(APPEND CMAKE_PREFIX_PATH ${CUDAToolkit_ROOT_DIR})
  187. # Mark that we need to pop the prefix path changes after we have
  188. # found the cudart library.
  189. set(_CUDAToolkit_Pop_Prefix True)
  190. endif()
  191. # Find the include/ directory
  192. find_path(CUDAToolkit_INCLUDE_DIR
  193. NAMES cuda_runtime.h
  194. )
  195. # Find a tentative CUDAToolkit_LIBRARY_DIR. FindCUDAToolkit overrides it by searching for the CUDA runtime,
  196. # but we can't do that here, as CMakeDetermineCUDACompiler wants to use it before the variables necessary
  197. # for find_library() have been initialized.
  198. if(EXISTS "${CUDAToolkit_TARGET_DIR}/lib64")
  199. set(CUDAToolkit_LIBRARY_DIR "${CUDAToolkit_TARGET_DIR}/lib64")
  200. elseif(EXISTS "${CUDAToolkit_TARGET_DIR}/lib/x64")
  201. set(CUDAToolkit_LIBRARY_DIR "${CUDAToolkit_TARGET_DIR}/lib/x64")
  202. elseif(EXISTS "${CUDAToolkit_TARGET_DIR}/lib")
  203. set(CUDAToolkit_LIBRARY_DIR "${CUDAToolkit_TARGET_DIR}/lib")
  204. endif()