CMakeDetermineCUDACompiler.cmake 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. unset(_CMAKE_PROCESSING_LANGUAGE)
  63. if(MSVC_CUDA_ARCHITECTURE_ID)
  64. set(SET_MSVC_CUDA_ARCHITECTURE_ID
  65. "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})")
  66. endif()
  67. if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
  68. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")
  69. set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "")
  70. set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "")
  71. set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
  72. elseif(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA)
  73. set(_nvcc_log "")
  74. string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}")
  75. if(_nvcc_output_orig MATCHES "#\\\$ +PATH= *([^\n]*)\n")
  76. set(_nvcc_path "${CMAKE_MATCH_1}")
  77. string(APPEND _nvcc_log " found 'PATH=' string: [${_nvcc_path}]\n")
  78. string(REPLACE ":" ";" _nvcc_path "${_nvcc_path}")
  79. else()
  80. set(_nvcc_path "")
  81. string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}")
  82. string(APPEND _nvcc_log " no 'PATH=' string found in nvcc output:${_nvcc_output_log}\n")
  83. endif()
  84. if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n")
  85. set(_nvcc_libraries "${CMAKE_MATCH_1}")
  86. string(APPEND _nvcc_log " found 'LIBRARIES=' string: [${_nvcc_libraries}]\n")
  87. else()
  88. set(_nvcc_libraries "")
  89. string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}")
  90. string(APPEND _nvcc_log " no 'LIBRARIES=' string found in nvcc output:${_nvcc_output_log}\n")
  91. endif()
  92. set(_nvcc_link_line "")
  93. if(_nvcc_libraries)
  94. # Remove variable assignments.
  95. string(REGEX REPLACE "#\\\$ *[^= ]+=[^\n]*\n" "" _nvcc_output "${_nvcc_output_orig}")
  96. # Encode [] characters that break list expansion.
  97. string(REPLACE "[" "{==={" _nvcc_output "${_nvcc_output}")
  98. string(REPLACE "]" "}===}" _nvcc_output "${_nvcc_output}")
  99. # Split lines.
  100. string(REGEX REPLACE "\n+(#\\\$ )?" ";" _nvcc_output "${_nvcc_output}")
  101. foreach(line IN LISTS _nvcc_output)
  102. set(_nvcc_output_line "${line}")
  103. string(REPLACE "{==={" "[" _nvcc_output_line "${_nvcc_output_line}")
  104. string(REPLACE "}===}" "]" _nvcc_output_line "${_nvcc_output_line}")
  105. string(APPEND _nvcc_log " considering line: [${_nvcc_output_line}]\n")
  106. if("${_nvcc_output_line}" MATCHES "^ *nvlink")
  107. string(APPEND _nvcc_log " ignoring nvlink line\n")
  108. elseif(_nvcc_libraries)
  109. if("${_nvcc_output_line}" MATCHES "(@\"?tmp/a\\.exe\\.res\"?)")
  110. set(_nvcc_link_res_arg "${CMAKE_MATCH_1}")
  111. set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/tmp/a.exe.res")
  112. if(EXISTS "${_nvcc_link_res}")
  113. file(READ "${_nvcc_link_res}" _nvcc_link_res_content)
  114. string(REPLACE "${_nvcc_link_res_arg}" "${_nvcc_link_res_content}" _nvcc_output_line "${_nvcc_output_line}")
  115. endif()
  116. endif()
  117. string(FIND "${_nvcc_output_line}" "${_nvcc_libraries}" _nvcc_libraries_pos)
  118. if(NOT _nvcc_libraries_pos EQUAL -1)
  119. set(_nvcc_link_line "${_nvcc_output_line}")
  120. string(APPEND _nvcc_log " extracted link line: [${_nvcc_link_line}]\n")
  121. endif()
  122. endif()
  123. endforeach()
  124. endif()
  125. if(_nvcc_link_line)
  126. if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
  127. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")
  128. else()
  129. #extract the compiler that is being used for linking
  130. separate_arguments(_nvcc_link_line_args UNIX_COMMAND "${_nvcc_link_line}")
  131. list(GET _nvcc_link_line_args 0 _nvcc_host_link_launcher)
  132. if(IS_ABSOLUTE "${_nvcc_host_link_launcher}")
  133. string(APPEND _nvcc_log " extracted link launcher absolute path: [${_nvcc_host_link_launcher}]\n")
  134. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}")
  135. else()
  136. string(APPEND _nvcc_log " extracted link launcher name: [${_nvcc_host_link_launcher}]\n")
  137. find_program(_nvcc_find_host_link_launcher
  138. NAMES ${_nvcc_host_link_launcher}
  139. PATHS ${_nvcc_path} NO_DEFAULT_PATH)
  140. find_program(_nvcc_find_host_link_launcher
  141. NAMES ${_nvcc_host_link_launcher})
  142. if(_nvcc_find_host_link_launcher)
  143. string(APPEND _nvcc_log " found link launcher absolute path: [${_nvcc_find_host_link_launcher}]\n")
  144. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_find_host_link_launcher}")
  145. else()
  146. string(APPEND _nvcc_log " could not find link launcher absolute path\n")
  147. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}")
  148. endif()
  149. unset(_nvcc_find_host_link_launcher CACHE)
  150. endif()
  151. endif()
  152. #prefix the line with cuda-fake-ld so that implicit link info believes it is
  153. #a link line
  154. set(_nvcc_link_line "cuda-fake-ld ${_nvcc_link_line}")
  155. CMAKE_PARSE_IMPLICIT_LINK_INFO("${_nvcc_link_line}"
  156. CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES
  157. CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES
  158. CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
  159. log
  160. "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}")
  161. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  162. "Parsed CUDA nvcc implicit link information from above output:\n${_nvcc_log}\n${log}\n\n")
  163. else()
  164. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  165. "Failed to parsed CUDA nvcc implicit link information:\n${_nvcc_log}\n\n")
  166. message(FATAL_ERROR "Failed to extract nvcc implicit link line.")
  167. endif()
  168. set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES )
  169. if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n")
  170. set(_nvcc_includes "${CMAKE_MATCH_1}")
  171. string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n")
  172. else()
  173. set(_nvcc_includes "")
  174. string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}")
  175. string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n")
  176. endif()
  177. if(_nvcc_includes)
  178. # across all operating system each include directory is prefixed with -I
  179. separate_arguments(_nvcc_output UNIX_COMMAND "${_nvcc_includes}")
  180. foreach(line IN LISTS _nvcc_output)
  181. string(REGEX REPLACE "^-I" "" line "${line}")
  182. get_filename_component(line "${line}" ABSOLUTE)
  183. list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}")
  184. endforeach()
  185. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  186. "Parsed CUDA nvcc include information from above output:\n${_nvcc_log}\n${log}\n\n")
  187. else()
  188. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  189. "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n")
  190. endif()
  191. endif()
  192. # configure all variables set in this file
  193. configure_file(${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in
  194. ${CMAKE_PLATFORM_INFO_DIR}/CMakeCUDACompiler.cmake
  195. @ONLY
  196. )
  197. set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX")
  198. set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX")