CMakeDetermineCUDACompiler.cmake 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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") ) )
  7. message(FATAL_ERROR "CUDA language not currently supported by \"${CMAKE_GENERATOR}\" generator")
  8. endif()
  9. if(NOT CMAKE_CUDA_COMPILER)
  10. set(CMAKE_CUDA_COMPILER_INIT NOTFOUND)
  11. # prefer the environment variable CUDACXX
  12. if(NOT $ENV{CUDACXX} STREQUAL "")
  13. get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT)
  14. if(CMAKE_CUDA_FLAGS_ENV_INIT)
  15. set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler")
  16. endif()
  17. if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT})
  18. message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}")
  19. endif()
  20. endif()
  21. # finally list compilers to try
  22. if(NOT CMAKE_CUDA_COMPILER_INIT)
  23. set(CMAKE_CUDA_COMPILER_LIST nvcc)
  24. endif()
  25. _cmake_find_compiler(CUDA)
  26. else()
  27. _cmake_find_compiler_path(CUDA)
  28. endif()
  29. mark_as_advanced(CMAKE_CUDA_COMPILER)
  30. #Allow the user to specify a host compiler
  31. set(CMAKE_CUDA_HOST_COMPILER "" CACHE FILEPATH "Host compiler to be used by nvcc")
  32. if(NOT $ENV{CUDAHOSTCXX} STREQUAL "")
  33. get_filename_component(CMAKE_CUDA_HOST_COMPILER $ENV{CUDAHOSTCXX} PROGRAM)
  34. if(NOT EXISTS ${CMAKE_CUDA_HOST_COMPILER})
  35. message(FATAL_ERROR "Could not find compiler set in environment variable CUDAHOSTCXX:\n$ENV{CUDAHOSTCXX}.\n${CMAKE_CUDA_HOST_COMPILER}")
  36. endif()
  37. endif()
  38. # Build a small source file to identify the compiler.
  39. if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
  40. set(CMAKE_CUDA_COMPILER_ID_RUN 1)
  41. # Try to identify the compiler.
  42. set(CMAKE_CUDA_COMPILER_ID)
  43. set(CMAKE_CUDA_PLATFORM_ID)
  44. file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
  45. CMAKE_CUDA_COMPILER_ID_PLATFORM_CONTENT)
  46. list(APPEND CMAKE_CUDA_COMPILER_ID_MATCH_VENDORS NVIDIA)
  47. set(CMAKE_CUDA_COMPILER_ID_MATCH_VENDOR_REGEX_NVIDIA "nvcc: NVIDIA \(R\) Cuda compiler driver")
  48. 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\\\"]")
  49. set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_INDEX 2)
  50. set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS -v --keep --keep-dir tmp)
  51. if(CMAKE_CUDA_HOST_COMPILER)
  52. list(APPEND CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-ccbin=${CMAKE_CUDA_HOST_COMPILER}")
  53. endif()
  54. include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
  55. CMAKE_DETERMINE_COMPILER_ID(CUDA CUDAFLAGS CMakeCUDACompilerId.cu)
  56. endif()
  57. include(CMakeFindBinUtils)
  58. if(MSVC_CUDA_ARCHITECTURE_ID)
  59. set(SET_MSVC_CUDA_ARCHITECTURE_ID
  60. "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})")
  61. endif()
  62. if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA)
  63. set(_nvcc_log "")
  64. string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}")
  65. if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n")
  66. set(_nvcc_libraries "${CMAKE_MATCH_1}")
  67. string(APPEND _nvcc_log " found 'LIBRARIES=' string: [${_nvcc_libraries}]\n")
  68. else()
  69. set(_nvcc_libraries "")
  70. string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}")
  71. string(APPEND _nvcc_log " no 'LIBRARIES=' string found in nvcc output:${_nvcc_output_log}\n")
  72. endif()
  73. set(_nvcc_link_line "")
  74. if(_nvcc_libraries)
  75. # Remove variable assignments.
  76. string(REGEX REPLACE "#\\\$ *[^= ]+=[^\n]*\n" "" _nvcc_output "${_nvcc_output_orig}")
  77. # Split lines.
  78. string(REGEX REPLACE "\n+(#\\\$ )?" ";" _nvcc_output "${_nvcc_output}")
  79. foreach(line IN LISTS _nvcc_output)
  80. set(_nvcc_output_line "${line}")
  81. string(APPEND _nvcc_log " considering line: [${_nvcc_output_line}]\n")
  82. if("${_nvcc_output_line}" MATCHES "^ *nvlink")
  83. string(APPEND _nvcc_log " ignoring nvlink line\n")
  84. elseif(_nvcc_libraries)
  85. if("${_nvcc_output_line}" MATCHES "(@\"?tmp/a\\.exe\\.res\"?)")
  86. set(_nvcc_link_res_arg "${CMAKE_MATCH_1}")
  87. set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/tmp/a.exe.res")
  88. if(EXISTS "${_nvcc_link_res}")
  89. file(READ "${_nvcc_link_res}" _nvcc_link_res_content)
  90. string(REPLACE "${_nvcc_link_res_arg}" "${_nvcc_link_res_content}" _nvcc_output_line "${_nvcc_output_line}")
  91. endif()
  92. endif()
  93. string(FIND "${_nvcc_output_line}" "${_nvcc_libraries}" _nvcc_libraries_pos)
  94. if(NOT _nvcc_libraries_pos EQUAL -1)
  95. set(_nvcc_link_line "${_nvcc_output_line}")
  96. string(APPEND _nvcc_log " extracted link line: [${_nvcc_link_line}]\n")
  97. endif()
  98. endif()
  99. endforeach()
  100. endif()
  101. if(_nvcc_link_line)
  102. if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
  103. set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")
  104. else()
  105. #extract the compiler that is being used for linking
  106. separate_arguments(_nvcc_link_line_args UNIX_COMMAND "${_nvcc_link_line}")
  107. list(GET _nvcc_link_line_args 0 CMAKE_CUDA_HOST_LINK_LAUNCHER)
  108. endif()
  109. #prefix the line with cuda-fake-ld so that implicit link info believes it is
  110. #a link line
  111. set(_nvcc_link_line "cuda-fake-ld ${_nvcc_link_line}")
  112. CMAKE_PARSE_IMPLICIT_LINK_INFO("${_nvcc_link_line}"
  113. CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES
  114. CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES
  115. CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
  116. log
  117. "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}")
  118. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  119. "Parsed CUDA nvcc implicit link information from above output:\n${_nvcc_log}\n${log}\n\n")
  120. else()
  121. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  122. "Failed to parsed CUDA nvcc implicit link information:\n${_nvcc_log}\n\n")
  123. message(FATAL_ERROR "Failed to extract nvcc implicit link line.")
  124. endif()
  125. set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES )
  126. if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n")
  127. set(_nvcc_includes "${CMAKE_MATCH_1}")
  128. string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n")
  129. else()
  130. set(_nvcc_includes "")
  131. string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}")
  132. string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n")
  133. endif()
  134. if(_nvcc_includes)
  135. # across all operating system each include directory is prefixed with -I
  136. separate_arguments(_nvcc_output UNIX_COMMAND "${_nvcc_includes}")
  137. foreach(line IN LISTS _nvcc_output)
  138. string(REGEX REPLACE "^-I" "" line "${line}")
  139. get_filename_component(line "${line}" ABSOLUTE)
  140. list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}")
  141. endforeach()
  142. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  143. "Parsed CUDA nvcc include information from above output:\n${_nvcc_log}\n${log}\n\n")
  144. else()
  145. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  146. "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n")
  147. endif()
  148. endif()
  149. # configure all variables set in this file
  150. configure_file(${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in
  151. ${CMAKE_PLATFORM_INFO_DIR}/CMakeCUDACompiler.cmake
  152. @ONLY
  153. )
  154. set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX")
  155. set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX")