CMakeDetermineCUDACompiler.cmake 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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|[89][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. set(CMAKE_CUDA_HOST_COMPILER "" CACHE FILEPATH "Host compiler to be used by nvcc")
  36. if(NOT $ENV{CUDAHOSTCXX} STREQUAL "")
  37. get_filename_component(CMAKE_CUDA_HOST_COMPILER $ENV{CUDAHOSTCXX} PROGRAM)
  38. if(NOT EXISTS ${CMAKE_CUDA_HOST_COMPILER})
  39. message(FATAL_ERROR "Could not find compiler set in environment variable CUDAHOSTCXX:\n$ENV{CUDAHOSTCXX}.\n${CMAKE_CUDA_HOST_COMPILER}")
  40. endif()
  41. endif()
  42. # Build a small source file to identify the compiler.
  43. if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
  44. set(CMAKE_CUDA_COMPILER_ID_RUN 1)
  45. # Try to identify the compiler.
  46. set(CMAKE_CUDA_COMPILER_ID)
  47. set(CMAKE_CUDA_PLATFORM_ID)
  48. file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
  49. CMAKE_CUDA_COMPILER_ID_PLATFORM_CONTENT)
  50. list(APPEND CMAKE_CUDA_COMPILER_ID_MATCH_VENDORS NVIDIA)
  51. set(CMAKE_CUDA_COMPILER_ID_MATCH_VENDOR_REGEX_NVIDIA "nvcc: NVIDIA \(R\) Cuda compiler driver")
  52. 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\\\"]")
  53. set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_INDEX 2)
  54. set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS -v --keep --keep-dir tmp)
  55. if(CMAKE_CUDA_HOST_COMPILER)
  56. list(APPEND CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-ccbin=${CMAKE_CUDA_HOST_COMPILER}")
  57. endif()
  58. include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
  59. CMAKE_DETERMINE_COMPILER_ID(CUDA CUDAFLAGS CMakeCUDACompilerId.cu)
  60. endif()
  61. set(_CMAKE_PROCESSING_LANGUAGE "CUDA")
  62. include(CMakeFindBinUtils)
  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. # Split lines.
  98. string(REGEX REPLACE "\n+(#\\\$ )?" ";" _nvcc_output "${_nvcc_output}")
  99. foreach(line IN LISTS _nvcc_output)
  100. set(_nvcc_output_line "${line}")
  101. string(APPEND _nvcc_log " considering line: [${_nvcc_output_line}]\n")
  102. if("${_nvcc_output_line}" MATCHES "^ *nvlink")
  103. string(APPEND _nvcc_log " ignoring nvlink line\n")
  104. elseif(_nvcc_libraries)
  105. if("${_nvcc_output_line}" MATCHES "(@\"?tmp/a\\.exe\\.res\"?)")
  106. set(_nvcc_link_res_arg "${CMAKE_MATCH_1}")
  107. set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/tmp/a.exe.res")
  108. if(EXISTS "${_nvcc_link_res}")
  109. file(READ "${_nvcc_link_res}" _nvcc_link_res_content)
  110. string(REPLACE "${_nvcc_link_res_arg}" "${_nvcc_link_res_content}" _nvcc_output_line "${_nvcc_output_line}")
  111. endif()
  112. endif()
  113. string(FIND "${_nvcc_output_line}" "${_nvcc_libraries}" _nvcc_libraries_pos)
  114. if(NOT _nvcc_libraries_pos EQUAL -1)
  115. set(_nvcc_link_line "${_nvcc_output_line}")
  116. string(APPEND _nvcc_log " extracted link line: [${_nvcc_link_line}]\n")
  117. endif()
  118. endif()
  119. endforeach()
  120. endif()
  121. if(_nvcc_link_line)
  122. if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
  123. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")
  124. else()
  125. #extract the compiler that is being used for linking
  126. separate_arguments(_nvcc_link_line_args UNIX_COMMAND "${_nvcc_link_line}")
  127. list(GET _nvcc_link_line_args 0 _nvcc_host_link_launcher)
  128. if(IS_ABSOLUTE "${_nvcc_host_link_launcher}")
  129. string(APPEND _nvcc_log " extracted link launcher absolute path: [${_nvcc_host_link_launcher}]\n")
  130. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}")
  131. else()
  132. string(APPEND _nvcc_log " extracted link launcher name: [${_nvcc_host_link_launcher}]\n")
  133. find_program(_nvcc_find_host_link_launcher
  134. NAMES ${_nvcc_host_link_launcher}
  135. PATHS ${_nvcc_path} NO_DEFAULT_PATH)
  136. find_program(_nvcc_find_host_link_launcher
  137. NAMES ${_nvcc_host_link_launcher})
  138. if(_nvcc_find_host_link_launcher)
  139. string(APPEND _nvcc_log " found link launcher absolute path: [${_nvcc_find_host_link_launcher}]\n")
  140. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_find_host_link_launcher}")
  141. else()
  142. string(APPEND _nvcc_log " could not find link launcher absolute path\n")
  143. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}")
  144. endif()
  145. unset(_nvcc_find_host_link_launcher CACHE)
  146. endif()
  147. endif()
  148. #prefix the line with cuda-fake-ld so that implicit link info believes it is
  149. #a link line
  150. set(_nvcc_link_line "cuda-fake-ld ${_nvcc_link_line}")
  151. CMAKE_PARSE_IMPLICIT_LINK_INFO("${_nvcc_link_line}"
  152. CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES
  153. CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES
  154. CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
  155. log
  156. "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}")
  157. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  158. "Parsed CUDA nvcc implicit link information from above output:\n${_nvcc_log}\n${log}\n\n")
  159. else()
  160. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  161. "Failed to parsed CUDA nvcc implicit link information:\n${_nvcc_log}\n\n")
  162. message(FATAL_ERROR "Failed to extract nvcc implicit link line.")
  163. endif()
  164. set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES )
  165. if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n")
  166. set(_nvcc_includes "${CMAKE_MATCH_1}")
  167. string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n")
  168. else()
  169. set(_nvcc_includes "")
  170. string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}")
  171. string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n")
  172. endif()
  173. if(_nvcc_includes)
  174. # across all operating system each include directory is prefixed with -I
  175. separate_arguments(_nvcc_output UNIX_COMMAND "${_nvcc_includes}")
  176. foreach(line IN LISTS _nvcc_output)
  177. string(REGEX REPLACE "^-I" "" line "${line}")
  178. get_filename_component(line "${line}" ABSOLUTE)
  179. list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}")
  180. endforeach()
  181. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  182. "Parsed CUDA nvcc include information from above output:\n${_nvcc_log}\n${log}\n\n")
  183. else()
  184. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  185. "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n")
  186. endif()
  187. endif()
  188. # configure all variables set in this file
  189. configure_file(${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in
  190. ${CMAKE_PLATFORM_INFO_DIR}/CMakeCUDACompiler.cmake
  191. @ONLY
  192. )
  193. set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX")
  194. set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX")