Reland On Demand Downloading of CUDA Dependencies for non CI Builds (#9519)
* Revert "Revert "Implement On Demand Downloading of CUDA Dependencies for non CI Builds" (#9514)"
This reverts commit f40d66a5aa2ad221ec43032be1c67b3a647c0ab3.
* Update CMakeLists.txt
Co-authored-by: Geoffrey Martin-Noble <gcmn@google.com>
Co-authored-by: Geoffrey Martin-Noble <gcmn@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index db5e928..7384a69 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -433,13 +433,21 @@
if(IREE_TARGET_BACKEND_CUDA OR IREE_HAL_DRIVER_CUDA)
find_package(CUDAToolkit)
- # We define the magic IREE_CUDA_DEPS_DIR env var in our CI docker images if we
- # have a stripped down CUDA toolkit suitable for compiling available. We
- # trigger on this below as a fallback for locating headers and libdevice
- # files.
- if(NOT CUDAToolkit_FOUND AND DEFINED ENV{IREE_CUDA_DEPS_DIR})
- set(CUDAToolkit_ROOT "$ENV{IREE_CUDA_DEPS_DIR}")
- message(STATUS "CUDA SDK not found by CMake but using IREE_CUDA_DEPS = ${CUDAToolkit_ROOT}")
+ if(NOT CUDAToolkit_FOUND)
+ if(DEFINED ENV{IREE_CUDA_DEPS_DIR})
+ # We define the magic IREE_CUDA_DEPS_DIR env var in our CI docker images if we
+ # have a stripped down CUDA toolkit suitable for compiling available. We
+ # trigger on this below as a fallback for locating headers and libdevice
+ # files.
+ set(CUDAToolkit_ROOT "$ENV{IREE_CUDA_DEPS_DIR}")
+ message(STATUS "CUDA SDK not found by CMake but using IREE_CUDA_DEPS = ${CUDAToolkit_ROOT}")
+ else()
+ # If we haven't found CUDA deps, download at least enough to build for CUDA.
+ # This will define IREE_CUDA_DOWNLOAD_LIBDEVICE_PATH & IREE_CUDA_DOWNLOAD_INCLUDE_PATH
+ # vars with the target deps.
+ message(STATUS "CUDA SDK not found by CMake but downloading dependencies")
+ add_subdirectory(build_tools/third_party/cuda EXCLUDE_FROM_ALL)
+ endif()
endif()
endif()
@@ -461,6 +469,9 @@
# are hard and such. In this case, if the user went to the trouble to
# tell us where it is, we have enough information.
set(IREE_CUDA_LIBDEVICE_PATH "${CUDAToolkit_ROOT}/nvvm/libdevice/libdevice.10.bc")
+ elseif(IREE_CUDA_DOWNLOAD_LIBDEVICE_PATH)
+ message(STATUS "Using downloaded CUDA libdevice")
+ set(IREE_CUDA_LIBDEVICE_PATH "${IREE_CUDA_DOWNLOAD_LIBDEVICE_PATH}")
else()
message(FATAL_ERROR "Building with IREE_TARGET_BACKEND_CUDA requires either a CUDA SDK (consult CMake docs for your version: https://cmake.org/cmake/help/latest/module/FindCUDAToolkit.html) or an explicit path to libdevice (set with -DIREE_CUDA_LIBDEVICE_PATH=/path/to/libdevice.10.bc)")
endif()
@@ -485,6 +496,9 @@
else()
message(SEND_ERROR "Using explicitly specified CUDAToolkit_ROOT, could not find cuda.h at: ${CUDAToolkit_INCLUDE_DIRS}")
endif()
+ elseif(IREE_CUDA_DOWNLOAD_INCLUDE_PATH)
+ message(STATUS "Using downloaded CUDA includes")
+ set(CUDAToolkit_INCLUDE_DIRS "${IREE_CUDA_DOWNLOAD_INCLUDE_PATH}")
else()
message(SEND_ERROR "Cannot build IREE runtime CUDA components (-DIREE_HAL_DRIVER_CUDA=ON) because a CUDA SDK was not found. Consult CMake docs for your version: https://cmake.org/cmake/help/latest/module/FindCUDAToolkit.html")
endif()
diff --git a/build_tools/third_party/cuda/CMakeLists.txt b/build_tools/third_party/cuda/CMakeLists.txt
new file mode 100644
index 0000000..12bffec
--- /dev/null
+++ b/build_tools/third_party/cuda/CMakeLists.txt
@@ -0,0 +1,78 @@
+# Copyright 2022 The IREE Authors
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set(_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR})
+set(_DOWNLOAD_SCRIPT_URL "https://raw.githubusercontent.com/NVIDIA/build-system-archive-import-examples/44dfb51fad75a8a2f1044a4fe221aba70571b86f/parse_redist.py")
+set(_DOWNLOAD_DIR ${_TARGET_DIR}/download)
+set(_DOWNLOAD_SCRIPT_PATH ${_DOWNLOAD_DIR}/parse_redist.py)
+
+# Parameters to the download script.
+# Look for an appropriate redistrib_*.json here to verify:
+# https://developer.download.nvidia.com/compute/cuda/redist/
+set(_VERSION "11.6.2")
+set(_PRODUCT "cuda")
+if(UNIX)
+ set(_OS "linux")
+elseif(WIN32)
+ set(_OS "windows")
+else()
+ message(SEND_ERROR "Unsupported OS environment. Must be Windows or Linux.")
+ return()
+endif()
+# CUDA is only supported on Linux/Windows where x64 is the only arch for now.
+set(_ARCH "x86_64")
+
+# Components that we need to fetch.
+set(_COMPONENTS_FO_FETCH "")
+list(APPEND _COMPONENTS_FO_FETCH "cuda_nvcc")
+list(APPEND _COMPONENTS_FO_FETCH "cuda_cudart")
+
+# Paths within the arch specific installation that we want to retain.
+set(_RETAIN_PATHS "")
+list(APPEND _RETAIN_PATHS "LICENSE")
+list(APPEND _RETAIN_PATHS "nvvm/libdevice/libdevice.10.bc")
+list(APPEND _RETAIN_PATHS "include/cuda.h")
+
+message(STATUS "Extracting to ${_TARGET_DIR}")
+file(MAKE_DIRECTORY ${_DOWNLOAD_DIR})
+
+# First fetch the download script to the tmp dir.
+file(DOWNLOAD ${_DOWNLOAD_SCRIPT_URL} ${_DOWNLOAD_SCRIPT_PATH})
+
+# Then use the download script to fetch and flatten each component we want
+# into the tmp dir.
+# This will produce a unified directory tree under:
+# flat/$OS-$ARCH
+set(SRC_DIR "${_DOWNLOAD_DIR}/${_OS}-${_ARCH}")
+foreach(COMPONENT ${_COMPONENTS_FO_FETCH})
+ message(STATUS "Downloading component ${COMPONENT}")
+ execute_process(COMMAND ${Python3_EXECUTABLE} "${_DOWNLOAD_SCRIPT_PATH}"
+ --label "${_VERSION}"
+ --product "${_PRODUCT}"
+ --os "${_OS}"
+ --arch "${_ARCH}"
+ --component "${COMPONENT}"
+ --output "${_DOWNLOAD_DIR}")
+endforeach()
+
+if(NOT EXISTS "${SRC_DIR}")
+ message(FATAL_ERROR "Download did not produce expected source dir: ${SRC_DIR}")
+ return()
+endif()
+
+foreach(REL_PATH ${_RETAIN_PATHS})
+ set(SRC_FILE "${SRC_DIR}/${REL_PATH}")
+ set(TARGET_FILE "${_TARGET_DIR}/${REL_PATH}")
+ message(STATUS "Copy ${SRC_FILE} -> ${TARGET_FILE}")
+ file(COPY ${SRC_FILE} DESTINATION ${TARGET_FILE})
+endforeach()
+
+# Delete tmp directory.
+file(REMOVE_RECURSE ${_DOWNLOAD_DIR})
+
+# Set vars for downloaded cuda deps
+set(IREE_CUDA_DOWNLOAD_LIBDEVICE_PATH "${_TARGET_DIR}/nvvm/libdevice/libdevice.10.bc" PARENT_SCOPE)
+set(IREE_CUDA_DOWNLOAD_INCLUDE_PATH "${_TARGET_DIR}/include" PARENT_SCOPE)