CMakeDetermineCUDACompiler.cmake 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file Copyright.txt or https://cmake.org/licensing for details.
  3. include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
  4. include(${CMAKE_ROOT}/Modules//CMakeParseImplicitLinkInfo.cmake)
  5. if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR
  6. ("${CMAKE_GENERATOR}" MATCHES "Ninja") OR
  7. ("${CMAKE_GENERATOR}" MATCHES "Visual Studio (1|[9][0-9])") ) )
  8. message(FATAL_ERROR "CUDA language not currently supported by \"${CMAKE_GENERATOR}\" generator")
  9. endif()
  10. if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
  11. else()
  12. if(NOT CMAKE_CUDA_COMPILER)
  13. set(CMAKE_CUDA_COMPILER_INIT NOTFOUND)
  14. # prefer the environment variable CUDACXX
  15. if(NOT $ENV{CUDACXX} STREQUAL "")
  16. get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT)
  17. if(CMAKE_CUDA_FLAGS_ENV_INIT)
  18. set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler")
  19. endif()
  20. if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT})
  21. message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}")
  22. endif()
  23. endif()
  24. # finally list compilers to try
  25. if(NOT CMAKE_CUDA_COMPILER_INIT)
  26. set(CMAKE_CUDA_COMPILER_LIST nvcc)
  27. endif()
  28. _cmake_find_compiler(CUDA)
  29. else()
  30. _cmake_find_compiler_path(CUDA)
  31. endif()
  32. mark_as_advanced(CMAKE_CUDA_COMPILER)
  33. endif()
  34. #Allow the user to specify a host compiler
  35. if(NOT $ENV{CUDAHOSTCXX} STREQUAL "")
  36. get_filename_component(CMAKE_CUDA_HOST_COMPILER $ENV{CUDAHOSTCXX} PROGRAM)
  37. if(NOT EXISTS ${CMAKE_CUDA_HOST_COMPILER})
  38. message(FATAL_ERROR "Could not find compiler set in environment variable CUDAHOSTCXX:\n$ENV{CUDAHOSTCXX}.\n${CMAKE_CUDA_HOST_COMPILER}")
  39. endif()
  40. endif()
  41. # Build a small source file to identify the compiler.
  42. if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
  43. set(CMAKE_CUDA_COMPILER_ID_RUN 1)
  44. # Try to identify the compiler.
  45. set(CMAKE_CUDA_COMPILER_ID)
  46. set(CMAKE_CUDA_PLATFORM_ID)
  47. file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
  48. CMAKE_CUDA_COMPILER_ID_PLATFORM_CONTENT)
  49. list(APPEND CMAKE_CUDA_COMPILER_ID_MATCH_VENDORS NVIDIA)
  50. set(CMAKE_CUDA_COMPILER_ID_MATCH_VENDOR_REGEX_NVIDIA "nvcc: NVIDIA \(R\) Cuda compiler driver")
  51. set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdCUDA/(\\./)?(CompilerIdCUDA.xctest/)?CompilerIdCUDA[ \t\n\\\"]")
  52. set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_INDEX 2)
  53. set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS -v --keep --keep-dir tmp)
  54. if(CMAKE_CUDA_HOST_COMPILER)
  55. list(APPEND CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-ccbin=${CMAKE_CUDA_HOST_COMPILER}")
  56. endif()
  57. include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
  58. CMAKE_DETERMINE_COMPILER_ID(CUDA CUDAFLAGS CMakeCUDACompilerId.cu)
  59. endif()
  60. set(_CMAKE_PROCESSING_LANGUAGE "CUDA")
  61. include(CMakeFindBinUtils)
  62. include(Compiler/${CMAKE_CUDA_COMPILER_ID}-FindBinUtils OPTIONAL)
  63. unset(_CMAKE_PROCESSING_LANGUAGE)
  64. if(MSVC_CUDA_ARCHITECTURE_ID)
  65. set(SET_MSVC_CUDA_ARCHITECTURE_ID
  66. "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})")
  67. endif()
  68. if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
  69. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")
  70. set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "")
  71. set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "")
  72. set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
  73. elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
  74. set(_nvcc_log "")
  75. string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}")
  76. if(_nvcc_output_orig MATCHES "#\\\$ +PATH= *([^\n]*)\n")
  77. set(_nvcc_path "${CMAKE_MATCH_1}")
  78. string(APPEND _nvcc_log " found 'PATH=' string: [${_nvcc_path}]\n")
  79. string(REPLACE ":" ";" _nvcc_path "${_nvcc_path}")
  80. else()
  81. set(_nvcc_path "")
  82. string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}")
  83. string(APPEND _nvcc_log " no 'PATH=' string found in nvcc output:${_nvcc_output_log}\n")
  84. endif()
  85. if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n")
  86. set(_nvcc_libraries "${CMAKE_MATCH_1}")
  87. string(APPEND _nvcc_log " found 'LIBRARIES=' string: [${_nvcc_libraries}]\n")
  88. else()
  89. set(_nvcc_libraries "")
  90. string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}")
  91. string(APPEND _nvcc_log " no 'LIBRARIES=' string found in nvcc output:${_nvcc_output_log}\n")
  92. endif()
  93. set(_nvcc_link_line "")
  94. if(_nvcc_libraries)
  95. # Remove variable assignments.
  96. string(REGEX REPLACE "#\\\$ *[^= ]+=[^\n]*\n" "" _nvcc_output "${_nvcc_output_orig}")
  97. # Encode [] characters that break list expansion.
  98. string(REPLACE "[" "{==={" _nvcc_output "${_nvcc_output}")
  99. string(REPLACE "]" "}===}" _nvcc_output "${_nvcc_output}")
  100. # Split lines.
  101. string(REGEX REPLACE "\n+(#\\\$ )?" ";" _nvcc_output "${_nvcc_output}")
  102. foreach(line IN LISTS _nvcc_output)
  103. set(_nvcc_output_line "${line}")
  104. string(REPLACE "{==={" "[" _nvcc_output_line "${_nvcc_output_line}")
  105. string(REPLACE "}===}" "]" _nvcc_output_line "${_nvcc_output_line}")
  106. string(APPEND _nvcc_log " considering line: [${_nvcc_output_line}]\n")
  107. if("${_nvcc_output_line}" MATCHES "^ *nvlink")
  108. string(APPEND _nvcc_log " ignoring nvlink line\n")
  109. elseif(_nvcc_libraries)
  110. if("${_nvcc_output_line}" MATCHES "(@\"?tmp/a\\.exe\\.res\"?)")
  111. set(_nvcc_link_res_arg "${CMAKE_MATCH_1}")
  112. set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/tmp/a.exe.res")
  113. if(EXISTS "${_nvcc_link_res}")
  114. file(READ "${_nvcc_link_res}" _nvcc_link_res_content)
  115. string(REPLACE "${_nvcc_link_res_arg}" "${_nvcc_link_res_content}" _nvcc_output_line "${_nvcc_output_line}")
  116. endif()
  117. endif()
  118. string(FIND "${_nvcc_output_line}" "${_nvcc_libraries}" _nvcc_libraries_pos)
  119. if(NOT _nvcc_libraries_pos EQUAL -1)
  120. set(_nvcc_link_line "${_nvcc_output_line}")
  121. string(APPEND _nvcc_log " extracted link line: [${_nvcc_link_line}]\n")
  122. endif()
  123. endif()
  124. endforeach()
  125. endif()
  126. if(_nvcc_link_line)
  127. if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
  128. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")
  129. else()
  130. #extract the compiler that is being used for linking
  131. separate_arguments(_nvcc_link_line_args UNIX_COMMAND "${_nvcc_link_line}")
  132. list(GET _nvcc_link_line_args 0 _nvcc_host_link_launcher)
  133. if(IS_ABSOLUTE "${_nvcc_host_link_launcher}")
  134. string(APPEND _nvcc_log " extracted link launcher absolute path: [${_nvcc_host_link_launcher}]\n")
  135. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}")
  136. else()
  137. string(APPEND _nvcc_log " extracted link launcher name: [${_nvcc_host_link_launcher}]\n")
  138. find_program(_nvcc_find_host_link_launcher
  139. NAMES ${_nvcc_host_link_launcher}
  140. PATHS ${_nvcc_path} NO_DEFAULT_PATH)
  141. find_program(_nvcc_find_host_link_launcher
  142. NAMES ${_nvcc_host_link_launcher})
  143. if(_nvcc_find_host_link_launcher)
  144. string(APPEND _nvcc_log " found link launcher absolute path: [${_nvcc_find_host_link_launcher}]\n")
  145. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_find_host_link_launcher}")
  146. else()
  147. string(APPEND _nvcc_log " could not find link launcher absolute path\n")
  148. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}")
  149. endif()
  150. unset(_nvcc_find_host_link_launcher CACHE)
  151. endif()
  152. endif()
  153. #prefix the line with cuda-fake-ld so that implicit link info believes it is
  154. #a link line
  155. set(_nvcc_link_line "cuda-fake-ld ${_nvcc_link_line}")
  156. CMAKE_PARSE_IMPLICIT_LINK_INFO("${_nvcc_link_line}"
  157. CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES
  158. CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES
  159. CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
  160. log
  161. "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}")
  162. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  163. "Parsed CUDA nvcc implicit link information from above output:\n${_nvcc_log}\n${log}\n\n")
  164. else()
  165. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  166. "Failed to parsed CUDA nvcc implicit link information:\n${_nvcc_log}\n\n")
  167. message(FATAL_ERROR "Failed to extract nvcc implicit link line.")
  168. endif()
  169. endif()
  170. # Determine CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES
  171. if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
  172. set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES)
  173. string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}")
  174. if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n")
  175. set(_nvcc_includes "${CMAKE_MATCH_1}")
  176. string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n")
  177. else()
  178. set(_nvcc_includes "")
  179. string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}")
  180. string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n")
  181. endif()
  182. if(_nvcc_includes)
  183. # across all operating system each include directory is prefixed with -I
  184. separate_arguments(_nvcc_output NATIVE_COMMAND "${_nvcc_includes}")
  185. foreach(line IN LISTS _nvcc_output)
  186. string(REGEX REPLACE "^-I" "" line "${line}")
  187. get_filename_component(line "${line}" ABSOLUTE)
  188. list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}")
  189. endforeach()
  190. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  191. "Parsed CUDA nvcc include information from above output:\n${_nvcc_log}\n${log}\n\n")
  192. else()
  193. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  194. "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n")
  195. endif()
  196. endif()
  197. # configure all variables set in this file
  198. configure_file(${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in
  199. ${CMAKE_PLATFORM_INFO_DIR}/CMakeCUDACompiler.cmake
  200. @ONLY
  201. )
  202. set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX")
  203. set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX")