Browse Source

CUDA: Implement nvcc implicit link line extraction more robustly

Do not assume that the implicit link line is the last line of the output
from `nvcc -v`.  Instead first find the `LIBRARIES=` line, and then look
for that content on a later line.  It appears twice.  First on a call to
`nvlink`, which we ignore.  Later it appears on the implicit link line.
Extract the latter line.  On failure, abort with a `FATAL_ERROR` so that
the user does not try to build without proper link information.

Once we have the line, parse it with `separate_arguments` using the
`UNIX_COMMAND` option just like `CMakeParseImplicitLinkInfo` already
does.  This robustly parses the command line and removes quoting.
Then extract the first argument as the host link launcher.
Brad King 9 years ago
parent
commit
e3f404fe29
1 changed files with 54 additions and 23 deletions
  1. 54 23
      Modules/CMakeDetermineCUDACompiler.cmake

+ 54 - 23
Modules/CMakeDetermineCUDACompiler.cmake

@@ -79,29 +79,60 @@ include(CMakeFindBinUtils)
 #We also need to find the implicit link lines. Which can be done by replacing
 #the compiler with cuda-fake-ld  and pass too CMAKE_PARSE_IMPLICIT_LINK_INFO
 if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA)
-  #grab the last line of the output which holds the link line
-  string(REPLACE "#\$ " ";" nvcc_output "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}")
-  list(GET nvcc_output -1 nvcc_output)
-
-  #extract the compiler that is being used for linking
-  string(REPLACE " " ";" nvcc_output_to_find_launcher "${nvcc_output}")
-  list(GET nvcc_output_to_find_launcher 0 CMAKE_CUDA_HOST_LINK_LAUNCHER)
-  #we need to remove the quotes that nvcc adds around the directory section
-  #of the path
-  string(REPLACE "\"" "" CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_CUDA_HOST_LINK_LAUNCHER}")
-
-  #prefix the line with cuda-fake-ld so that implicit link info believes it is
-  #a link line
-  set(nvcc_output "cuda-fake-ld ${nvcc_output}")
-  CMAKE_PARSE_IMPLICIT_LINK_INFO("${nvcc_output}"
-                                 CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES
-                                 CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES
-                                 CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
-                                 log
-                                 "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}")
-
-  file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
-          "Parsed CUDA nvcc implicit link information from above output:\n${log}\n\n")
+  set(_nvcc_log "")
+  string(REPLACE "\r" "" _nvcc_output "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}")
+  if(_nvcc_output MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n")
+    set(_nvcc_libraries "${CMAKE_MATCH_1}")
+    string(APPEND _nvcc_log "  found 'LIBRARIES=' string: [${_nvcc_libraries}]\n")
+  else()
+    set(_nvcc_libraries "")
+    string(REPLACE "\n" "\n    " _nvcc_output_log "\n${_nvcc_output}")
+    string(APPEND _nvcc_log "  no 'LIBRARIES=' string found in nvcc output:${_nvcc_output_log}\n")
+  endif()
+
+  set(_nvcc_link_line "")
+  if(_nvcc_libraries)
+    # Remove variable assignments.
+    string(REGEX REPLACE "#\\\$ *[^= ]+=[^\n]*\n" "" _nvcc_output "${_nvcc_output}")
+    # Split lines.
+    string(REGEX REPLACE "\n+(#\\\$ )?" ";" _nvcc_output "${_nvcc_output}")
+    foreach(line IN LISTS _nvcc_output)
+      set(_nvcc_output_line "${line}")
+      string(APPEND _nvcc_log "  considering line: [${_nvcc_output_line}]\n")
+      if("${_nvcc_output_line}" MATCHES "^ *nvlink")
+        string(APPEND _nvcc_log "    ignoring nvlink line\n")
+      elseif(_nvcc_libraries)
+        string(FIND "${_nvcc_output_line}" "${_nvcc_libraries}" _nvcc_libraries_pos)
+        if(NOT _nvcc_libraries_pos EQUAL -1)
+          set(_nvcc_link_line "${_nvcc_output_line}")
+          string(APPEND _nvcc_log "    extracted link line: [${_nvcc_link_line}]\n")
+        endif()
+      endif()
+    endforeach()
+  endif()
+
+  if(_nvcc_link_line)
+    #extract the compiler that is being used for linking
+    separate_arguments(_nvcc_link_line_args UNIX_COMMAND "${_nvcc_link_line}")
+    list(GET _nvcc_link_line_args 0 CMAKE_CUDA_HOST_LINK_LAUNCHER)
+
+    #prefix the line with cuda-fake-ld so that implicit link info believes it is
+    #a link line
+    set(_nvcc_link_line "cuda-fake-ld ${_nvcc_link_line}")
+    CMAKE_PARSE_IMPLICIT_LINK_INFO("${_nvcc_link_line}"
+                                   CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES
+                                   CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES
+                                   CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+                                   log
+                                   "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}")
+
+    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+      "Parsed CUDA nvcc implicit link information from above output:\n${_nvcc_log}\n${log}\n\n")
+  else()
+    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+      "Failed to parsed CUDA nvcc implicit link information:\n${_nvcc_log}\n\n")
+    message(FATAL_ERROR "Failed to extract nvcc implicit link line.")
+  endif()
 
 endif()