| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- # file Copyright.txt or https://cmake.org/licensing for details.
- #[=======================================================================[.rst:
- FindCUDAToolkit
- ---------------
- This script locates the NVIDIA CUDA toolkit, but does not require the ``CUDA``
- language be enabled for a given project. This module does not search for the
- NVIDIA CUDA Samples or any specific CUDA libraries. This module only searches
- for the CUDA Toolkit root directory.
- Search Behavior
- ^^^^^^^^^^^^^^^
- Finding the CUDA Toolkit requires finding the ``nvcc`` executable, which is
- searched for in the following order:
- 1. If the ``CUDAToolkit_ROOT`` cmake configuration variable (e.g.,
- ``-DCUDAToolkit_ROOT=/some/path``) *or* environment variable is defined, it
- will be searched first. If both an environment variable **and** a
- configuration variable are specified, the *configuration* variable takes
- precedence.
- The directory specified here must be such that the executable ``nvcc`` can be
- found underneath the directory specified by ``CUDAToolkit_ROOT``. If
- ``CUDAToolkit_ROOT`` is specified, but no ``nvcc`` is found underneath, this
- package is marked as **not** found. No subsequent search attempts are
- performed.
- 2. The user's path is searched for ``nvcc`` using :command:`find_program`. If
- this is found, no subsequent search attempts are performed. Users are
- responsible for ensuring that the first ``nvcc`` to show up in the path is
- the desired path in the event that multiple CUDA Toolkits are installed.
- 3. On Unix systems, if the symbolic link ``/usr/local/cuda`` exists, this is
- used. No subsequent search attempts are performed. No default symbolic link
- location exists for the Windows platform.
- 4. The platform specific default install locations are searched. If exactly one
- candidate is found, this is used. The default CUDA Toolkit install locations
- searched are:
- +-------------+-------------------------------------------------------------+
- | Platform | Search Pattern |
- +=============+=============================================================+
- | macOS | ``/Developer/NVIDIA/CUDA-X.Y`` |
- +-------------+-------------------------------------------------------------+
- | Other Unix | ``/usr/local/cuda-X.Y`` |
- +-------------+-------------------------------------------------------------+
- | Windows | ``C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y`` |
- +-------------+-------------------------------------------------------------+
- Where ``X.Y`` would be a specific version of the CUDA Toolkit, such as
- ``/usr/local/cuda-9.0`` or
- ``C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0``
- .. note::
- When multiple CUDA Toolkits are installed in the default location of a
- system (e.g., both ``/usr/local/cuda-9.0`` and ``/usr/local/cuda-10.0``
- exist but the ``/usr/local/cuda`` symbolic link does **not** exist), this
- package is marked as **not** found.
- There are too many factors involved in making an automatic decision in
- the presence of multiple CUDA Toolkits being installed. In this
- situation, users are encouraged to either (1) set ``CUDAToolkit_ROOT`` or
- (2) ensure that the correct ``nvcc`` executable shows up in ``$PATH`` for
- :command:`find_program` to find.
- Options
- ^^^^^^^
- ``VERSION``
- If specified, describes the version of the CUDA Toolkit to search for.
- ``REQUIRED``
- If specified, configuration will error if a suitable CUDA Toolkit is not
- found.
- ``QUIET``
- If specified, the search for a suitable CUDA Toolkit will not produce any
- messages.
- ``EXACT``
- If specified, the CUDA Toolkit is considered found only if the exact
- ``VERSION`` specified is recovered.
- Output Variables
- ^^^^^^^^^^^^^^^^
- ``CUDAToolkit_FOUND``
- A boolean specifying whether or not the CUDA Toolkit was found.
- ``CUDAToolkit_VERSION``
- The exact version of the CUDA Toolkit found (as reported by
- ``nvcc --version``).
- ``CUDAToolkit_ROOT_DIR``
- The root directory of the CUDA Toolkit found. Note that this variable will
- be the same as ``CUDAToolkit_ROOT`` when specified *and* a suitable toolkit was
- found.
- ``CUDAToolkit_INCLUDE_DIRS``
- The path to the CUDA Toolkit ``include`` folder containing the header files
- required to compile a project linking against CUDA.
- ``CUDAToolkit_LIBRARY_DIR``
- The path to the CUDA Toolkit library directory that contains the CUDA
- Runtime library ``cudart``.
- ``CUDAToolkit_NVCC_EXECUTABLE``
- The path to the NVIDIA CUDA compiler ``nvcc``. Note that this path may not
- **not** be the same as
- :variable:`CMAKE_CUDA_COMPILER <CMAKE_<LANG>_COMPILER>`. ``nvcc`` must be
- found to determine the CUDA Toolkit version as well as determining other
- features of the Toolkit. This variable is set for the convenience of
- modules that depend on this one.
- #]=======================================================================]
- # NOTE: much of this was simply extracted from FindCUDA.cmake.
- # James Bigler, NVIDIA Corp (nvidia.com - jbigler)
- # Abe Stephens, SCI Institute -- http://www.sci.utah.edu/~abe/FindCuda.html
- #
- # Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved.
- #
- # Copyright (c) 2007-2009
- # Scientific Computing and Imaging Institute, University of Utah
- #
- # This code is licensed under the MIT License. See the FindCUDA.cmake script
- # for the text of the license.
- # The MIT License
- #
- # License for the specific language governing rights and limitations under
- # Permission is hereby granted, free of charge, to any person obtaining a
- # copy of this software and associated documentation files (the "Software"),
- # to deal in the Software without restriction, including without limitation
- # the rights to use, copy, modify, merge, publish, distribute, sublicense,
- # and/or sell copies of the Software, and to permit persons to whom the
- # Software is furnished to do so, subject to the following conditions:
- #
- # The above copyright notice and this permission notice shall be included
- # in all copies or substantial portions of the Software.
- #
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- # DEALINGS IN THE SOFTWARE.
- #
- ###############################################################################
- # Attempt 1: try user provided paths first.
- find_path(CUDAToolkit_ROOT_DIR
- NAMES nvcc nvcc.exe
- PATHS
- ${CUDAToolkit_ROOT}
- ENV CUDAToolkit_ROOT
- PATH_SUFFIXES bin bin64
- NO_DEFAULT_PATH
- )
- message(FATAL_ERROR "CUDAToolkit_ROOT_DIR: ${CUDAToolkit_ROOT_DIR}")
- # If the user specified CUDAToolkit_ROOT but nvcc could not be found, this is an error.
- if (NOT CUDAToolkit_ROOT_DIR AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT}))
- # Declare error messages now, print later depending on find_package args.
- set(fail_base "Could not find nvcc executable in path specified by")
- set(cuda_root_fail "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}")
- set(env_cuda_root_fail "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}")
- if (CUDAToolkit_FIND_REQUIRED)
- if (DEFINED CUDAToolkit_ROOT)
- message(FATAL_ERROR ${cuda_root_fail})
- elseif (DEFINED ENV{CUDAToolkit_ROOT})
- message(FATAL_ERROR ${env_cuda_root_fail})
- endif()
- else()
- if (NOT CUDAToolkit_FIND_QUIETLY)
- if (DEFINED CUDAToolkit_ROOT)
- message(STATUS ${cuda_root_fail})
- elseif (DEFINED ENV{CUDAToolkit_ROOT})
- message(STATUS ${env_cuda_root_fail})
- endif()
- endif()
- set(CUDAToolkit_FOUND FALSE)
- unset(fail_base)
- unset(cuda_root_fail)
- unset(env_cuda_root_fail)
- return()
- endif()
- endif()
- # CUDAToolkit_ROOT cmake / env variable not specified, try platform defaults.
- #
- # - Linux: /usr/local/cuda-X.Y
- # - macOS: /Developer/NVIDIA/CUDA-X.Y
- # - Windows: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y
- #
- # We will also search the default symlink location /usr/local/cuda first since
- # if CUDAToolkit_ROOT is not specified, it is assumed that the symlinked
- # directory is the desired location.
- if (NOT CUDAToolkit_ROOT_DIR)
- if (UNIX)
- if (NOT APPLE)
- set(platform_base "/usr/local/cuda-")
- else()
- set(platform_base "/Developer/NVIDIA/CUDA-")
- endif()
- else()
- set(platform_base "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v")
- endif()
- # Build out a descending list of possible cuda installations, e.g.
- file(GLOB possible_paths "${platform_base}*")
- # Iterate the glob results and create a descending list.
- set(possible_versions)
- foreach (p ${possible_paths})
- # Extract version number from end of string
- string(REGEX MATCH "[0-9][0-9]?\\.[0-9]$" p_version ${p})
- if (IS_DIRECTORY ${p} AND p_version)
- list(APPEND possible_versions ${p_version})
- endif()
- endforeach()
- # Cannot use list(SORT) because that is alphabetical, we need numerical.
- # NOTE: this is not an efficient sorting strategy. But even if a user had
- # every possible version of CUDA installed, this wouldn't create any
- # significant overhead.
- set(versions)
- foreach (v ${possible_versions})
- list(LENGTH versions num_versions)
- # First version, nothing to compare with so just append.
- if (num_versions EQUAL 0)
- list(APPEND versions ${v})
- else()
- # Loop through list. Insert at an index when comparison is
- # VERSION_GREATER since we want a descending list. Duplicates will not
- # happen since this came from a glob list of directories.
- set(i 0)
- set(early_terminate FALSE)
- while (i LESS num_versions)
- list(GET versions ${i} curr)
- if (v VERSION_GREATER curr)
- list(INSERT versions ${i} ${v})
- set(early_terminate TRUE)
- break()
- endif()
- math(EXPR i "${i} + 1")
- endwhile()
- # If it did not get inserted, place it at the end.
- if (NOT early_terminate)
- list(APPEND versions ${v})
- endif()
- endif()
- endforeach()
- # With a descending list of versions, populate possible paths to search.
- set(search_paths)
- foreach (v ${versions})
- list(APPEND search_paths "${platform_base}${v}")
- endforeach()
- # Force the global default /usr/local/cuda to the front on Unix.
- if (UNIX)
- list(INSERT search_paths 0 "/usr/local/cuda")
- endif()
- # Now search for nvcc again using the platform default search paths.
- find_path(CUDAToolkit_ROOT_DIR
- NAMES nvcc nvcc.exe
- PATHS ${search_paths}
- PATH_SUFFIXES bin bin64
- NO_DEFAULT_PATH
- )
- # We are done with these variables now, cleanup for caller.
- unset(platform_base)
- unset(possible_paths)
- unset(possible_versions)
- unset(versions)
- unset(i)
- unset(early_terminate)
- unset(search_paths)
- if (NOT CUDAToolkit_ROOT_DIR)
- if (CUDAToolkit_FIND_REQUIRED)
- message(FATAL_ERROR "Could not find nvcc, please set CUDAToolkit_ROOT.")
- elseif(NOT CUDAToolkit_FIND_QUIETLY)
- message(STATUS "Could not find nvcc, please set CUDAToolkit_ROOT.")
- endif()
- set(CUDAToolkit_FOUND FALSE)
- return()
- endif()
- endif()
- # TODO: why does FindCUDA.cmake go through effor tof `cuda_find_host_program`
- # when CMAKE_CROSSCOMPILING // is that still relevant?
- # https://gitlab.kitware.com/cmake/cmake/issues/16509
- # NOTE: search before trimming bin / bin64 from CUDAToolkit_ROOT_DIR
- find_program(CUDAToolkit_NVCC_EXECUTABLE
- NAMES nvcc nvcc.exe
- PATHS ${CUDAToolkit_ROOT_DIR}
- NO_DEFAULT_PATH
- )
- # Compute the version.
- execute_process(
- COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "--version"
- OUTPUT_VARIABLE NVCC_OUT
- )
- string(
- REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1"
- CUDAToolkit_VERSION_MAJOR ${NVCC_OUT}
- )
- string(
- REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2"
- CUDAToolkit_VERSION_MINOR ${NVCC_OUT}
- )
- set(
- CUDAToolkit_VERSION "${CUDAToolkit_VERSION_MAJOR}.${CUDAToolkit_VERSION_MINOR}"
- CACHE STRING "Version of CUDA as computed from nvcc."
- )
- unset(NVCC_OUT)
- # CUDAToolkit_ROOT_DIR should have the path to the bin or bin64 folder from the
- # find_path calls above. Failure to find nvcc should have had an early return.
- # So now we need to remove bin / bin64, as well as reset the cache entry that
- # find_path creates.
- string(REGEX REPLACE "[/\\\\]?bin[64]*[/\\\\]?$" "" CUDAToolkit_ROOT_DIR ${CUDAToolkit_ROOT_DIR})
- set(CUDAToolkit_ROOT_DIR ${CUDAToolkit_ROOT_DIR} CACHE PATH "Toolkit location." FORCE)
- # Now that we have the real ROOT_DIR, find the include/ directory
- find_path(CUDAToolkit_INCLUDE_DIRS
- cuda_runtime.h
- # TODO: FindCUDA.cmake has special TARGET_DIR for cross compiling, is that needed?
- PATHS ${CUDAToolkit_ROOT_DIR}
- PATH_SUFFIXES include
- NO_DEFAULT_PATH
- )
- # And find the CUDA Runtime Library libcudart
- find_library(libcudart
- cudart
- PATHS ${CUDAToolkit_ROOT_DIR}
- PATH_SUFFIXES lib lib64
- NO_DEFAULT_PATH
- )
- if (libcudart)
- get_filename_component(CUDAToolkit_LIBRARY_DIR ${libcudart} DIRECTORY ABSOLUTE)
- else()
- if (NOT CUDAToolkit_FIND_QUIETLY)
- message(STATUS "Unable to find cudart library under ${CUDAToolkit_ROOT_DIR}/lib[64].")
- endif()
- set(CUDAToolkit_LIBRARY_DIR CUDAToolkit_LIBRARY_DIR-NOTFOUND)
- endif()
- unset(libcudart)
- # Perform version comparison and validate all required variables are set.
- include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
- find_package_handle_standard_args(CUDAToolkit
- REQUIRED_VARS
- CUDAToolkit_ROOT_DIR
- CUDAToolkit_INCLUDE_DIRS
- CUDAToolkit_LIBRARY_DIR
- CUDAToolkit_NVCC_EXECUTABLE
- VERSION_VAR
- CUDAToolkit_VERSION
- )
|