1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5FindCUDAToolkit
6---------------
7
8.. versionadded:: 3.17
9
10This script locates the NVIDIA CUDA toolkit and the associated libraries, but
11does not require the ``CUDA`` language be enabled for a given project. This
12module does not search for the NVIDIA CUDA Samples.
13
14.. versionadded:: 3.19
15  QNX support.
16
17Search Behavior
18^^^^^^^^^^^^^^^
19
20The CUDA Toolkit search behavior uses the following order:
21
221. If the ``CUDA`` language has been enabled we will use the directory
23   containing the compiler as the first search location for ``nvcc``.
24
252. If the ``CUDAToolkit_ROOT`` cmake configuration variable (e.g.,
26   ``-DCUDAToolkit_ROOT=/some/path``) *or* environment variable is defined, it
27   will be searched.  If both an environment variable **and** a
28   configuration variable are specified, the *configuration* variable takes
29   precedence.
30
31   The directory specified here must be such that the executable ``nvcc`` or
32   the appropriate ``version.txt`` file can be found underneath the specified
33   directory.
34
353. If the CUDA_PATH environment variable is defined, it will be searched
36   for ``nvcc``.
37
384. The user's path is searched for ``nvcc`` using :command:`find_program`.  If
39   this is found, no subsequent search attempts are performed.  Users are
40   responsible for ensuring that the first ``nvcc`` to show up in the path is
41   the desired path in the event that multiple CUDA Toolkits are installed.
42
435. On Unix systems, if the symbolic link ``/usr/local/cuda`` exists, this is
44   used.  No subsequent search attempts are performed.  No default symbolic link
45   location exists for the Windows platform.
46
476. The platform specific default install locations are searched.  If exactly one
48   candidate is found, this is used.  The default CUDA Toolkit install locations
49   searched are:
50
51   +-------------+-------------------------------------------------------------+
52   | Platform    | Search Pattern                                              |
53   +=============+=============================================================+
54   | macOS       | ``/Developer/NVIDIA/CUDA-X.Y``                              |
55   +-------------+-------------------------------------------------------------+
56   | Other Unix  | ``/usr/local/cuda-X.Y``                                     |
57   +-------------+-------------------------------------------------------------+
58   | Windows     | ``C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y`` |
59   +-------------+-------------------------------------------------------------+
60
61   Where ``X.Y`` would be a specific version of the CUDA Toolkit, such as
62   ``/usr/local/cuda-9.0`` or
63   ``C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0``
64
65   .. note::
66
67       When multiple CUDA Toolkits are installed in the default location of a
68       system (e.g., both ``/usr/local/cuda-9.0`` and ``/usr/local/cuda-10.0``
69       exist but the ``/usr/local/cuda`` symbolic link does **not** exist), this
70       package is marked as **not** found.
71
72       There are too many factors involved in making an automatic decision in
73       the presence of multiple CUDA Toolkits being installed.  In this
74       situation, users are encouraged to either (1) set ``CUDAToolkit_ROOT`` or
75       (2) ensure that the correct ``nvcc`` executable shows up in ``$PATH`` for
76       :command:`find_program` to find.
77
78Arguments
79^^^^^^^^^
80
81``[<version>]``
82    The ``[<version>]`` argument requests a version with which the package found
83    should be compatible. See :ref:`find_package version format <FIND_PACKAGE_VERSION_FORMAT>`
84    for more details.
85
86Options
87^^^^^^^
88
89``REQUIRED``
90    If specified, configuration will error if a suitable CUDA Toolkit is not
91    found.
92
93``QUIET``
94    If specified, the search for a suitable CUDA Toolkit will not produce any
95    messages.
96
97``EXACT``
98    If specified, the CUDA Toolkit is considered found only if the exact
99    ``VERSION`` specified is recovered.
100
101Imported targets
102^^^^^^^^^^^^^^^^
103
104An :ref:`imported target <Imported targets>` named ``CUDA::toolkit`` is provided.
105
106This module defines :prop_tgt:`IMPORTED` targets for each
107of the following libraries that are part of the CUDAToolkit:
108
109- :ref:`CUDA Runtime Library<cuda_toolkit_rt_lib>`
110- :ref:`CUDA Driver Library<cuda_toolkit_driver_lib>`
111- :ref:`cuBLAS<cuda_toolkit_cuBLAS>`
112- :ref:`cuFFT<cuda_toolkit_cuFFT>`
113- :ref:`cuRAND<cuda_toolkit_cuRAND>`
114- :ref:`cuSOLVER<cuda_toolkit_cuSOLVER>`
115- :ref:`cuSPARSE<cuda_toolkit_cuSPARSE>`
116- :ref:`cuPTI<cuda_toolkit_cupti>`
117- :ref:`NPP<cuda_toolkit_NPP>`
118- :ref:`nvBLAS<cuda_toolkit_nvBLAS>`
119- :ref:`nvGRAPH<cuda_toolkit_nvGRAPH>`
120- :ref:`nvJPEG<cuda_toolkit_nvJPEG>`
121- :ref:`nvidia-ML<cuda_toolkit_nvML>`
122- :ref:`nvRTC<cuda_toolkit_nvRTC>`
123- :ref:`nvToolsExt<cuda_toolkit_nvToolsExt>`
124- :ref:`OpenCL<cuda_toolkit_opencl>`
125- :ref:`cuLIBOS<cuda_toolkit_cuLIBOS>`
126
127.. _`cuda_toolkit_rt_lib`:
128
129CUDA Runtime Library
130""""""""""""""""""""
131
132The CUDA Runtime library (cudart) are what most applications will typically
133need to link against to make any calls such as `cudaMalloc`, and `cudaFree`.
134
135Targets Created:
136
137- ``CUDA::cudart``
138- ``CUDA::cudart_static``
139
140.. _`cuda_toolkit_driver_lib`:
141
142CUDA Driver Library
143""""""""""""""""""""
144
145The CUDA Driver library (cuda) are used by applications that use calls
146such as `cuMemAlloc`, and `cuMemFree`. This is generally used by advanced
147
148
149Targets Created:
150
151- ``CUDA::cuda_driver``
152- ``CUDA::cuda_driver``
153
154.. _`cuda_toolkit_cuBLAS`:
155
156cuBLAS
157""""""
158
159The `cuBLAS <https://docs.nvidia.com/cuda/cublas/index.html>`_ library.
160
161Targets Created:
162
163- ``CUDA::cublas``
164- ``CUDA::cublas_static``
165- ``CUDA::cublasLt`` starting in CUDA 10.1
166- ``CUDA::cublasLt_static`` starting in CUDA 10.1
167
168.. _`cuda_toolkit_cuFFT`:
169
170cuFFT
171"""""
172
173The `cuFFT <https://docs.nvidia.com/cuda/cufft/index.html>`_ library.
174
175Targets Created:
176
177- ``CUDA::cufft``
178- ``CUDA::cufftw``
179- ``CUDA::cufft_static``
180- ``CUDA::cufftw_static``
181
182cuRAND
183""""""
184
185The `cuRAND <https://docs.nvidia.com/cuda/curand/index.html>`_ library.
186
187Targets Created:
188
189- ``CUDA::curand``
190- ``CUDA::curand_static``
191
192.. _`cuda_toolkit_cuSOLVER`:
193
194cuSOLVER
195""""""""
196
197The `cuSOLVER <https://docs.nvidia.com/cuda/cusolver/index.html>`_ library.
198
199Targets Created:
200
201- ``CUDA::cusolver``
202- ``CUDA::cusolver_static``
203
204.. _`cuda_toolkit_cuSPARSE`:
205
206cuSPARSE
207""""""""
208
209The `cuSPARSE <https://docs.nvidia.com/cuda/cusparse/index.html>`_ library.
210
211Targets Created:
212
213- ``CUDA::cusparse``
214- ``CUDA::cusparse_static``
215
216.. _`cuda_toolkit_cupti`:
217
218cupti
219"""""
220
221The `NVIDIA CUDA Profiling Tools Interface <https://developer.nvidia.com/CUPTI>`_.
222
223Targets Created:
224
225- ``CUDA::cupti``
226- ``CUDA::cupti_static``
227
228.. _`cuda_toolkit_NPP`:
229
230NPP
231"""
232
233The `NPP <https://docs.nvidia.com/cuda/npp/index.html>`_ libraries.
234
235Targets Created:
236
237- `nppc`:
238
239  - ``CUDA::nppc``
240  - ``CUDA::nppc_static``
241
242- `nppial`: Arithmetic and logical operation functions in `nppi_arithmetic_and_logical_operations.h`
243
244  - ``CUDA::nppial``
245  - ``CUDA::nppial_static``
246
247- `nppicc`: Color conversion and sampling functions in `nppi_color_conversion.h`
248
249  - ``CUDA::nppicc``
250  - ``CUDA::nppicc_static``
251
252- `nppicom`: JPEG compression and decompression functions in `nppi_compression_functions.h`
253  Removed starting in CUDA 11.0, use :ref:`nvJPEG<cuda_toolkit_nvJPEG>` instead.
254
255  - ``CUDA::nppicom``
256  - ``CUDA::nppicom_static``
257
258- `nppidei`: Data exchange and initialization functions in `nppi_data_exchange_and_initialization.h`
259
260  - ``CUDA::nppidei``
261  - ``CUDA::nppidei_static``
262
263- `nppif`: Filtering and computer vision functions in `nppi_filter_functions.h`
264
265  - ``CUDA::nppif``
266  - ``CUDA::nppif_static``
267
268- `nppig`: Geometry transformation functions found in `nppi_geometry_transforms.h`
269
270  - ``CUDA::nppig``
271  - ``CUDA::nppig_static``
272
273- `nppim`: Morphological operation functions found in `nppi_morphological_operations.h`
274
275  - ``CUDA::nppim``
276  - ``CUDA::nppim_static``
277
278- `nppist`: Statistics and linear transform in `nppi_statistics_functions.h` and `nppi_linear_transforms.h`
279
280  - ``CUDA::nppist``
281  - ``CUDA::nppist_static``
282
283- `nppisu`: Memory support functions in `nppi_support_functions.h`
284
285  - ``CUDA::nppisu``
286  - ``CUDA::nppisu_static``
287
288- `nppitc`: Threshold and compare operation functions in `nppi_threshold_and_compare_operations.h`
289
290  - ``CUDA::nppitc``
291  - ``CUDA::nppitc_static``
292
293- `npps`:
294
295  - ``CUDA::npps``
296  - ``CUDA::npps_static``
297
298.. _`cuda_toolkit_nvBLAS`:
299
300nvBLAS
301""""""
302
303The `nvBLAS <https://docs.nvidia.com/cuda/nvblas/index.html>`_ libraries.
304This is a shared library only.
305
306Targets Created:
307
308- ``CUDA::nvblas``
309
310.. _`cuda_toolkit_nvGRAPH`:
311
312nvGRAPH
313"""""""
314
315The `nvGRAPH <https://docs.nvidia.com/cuda/nvgraph/index.html>`_ library.
316Removed starting in CUDA 11.0
317
318Targets Created:
319
320- ``CUDA::nvgraph``
321- ``CUDA::nvgraph_static``
322
323
324.. _`cuda_toolkit_nvJPEG`:
325
326nvJPEG
327""""""
328
329The `nvJPEG <https://docs.nvidia.com/cuda/nvjpeg/index.html>`_ library.
330Introduced in CUDA 10.
331
332Targets Created:
333
334- ``CUDA::nvjpeg``
335- ``CUDA::nvjpeg_static``
336
337.. _`cuda_toolkit_nvRTC`:
338
339nvRTC
340"""""
341
342The `nvRTC <https://docs.nvidia.com/cuda/nvrtc/index.html>`_ (Runtime Compilation) library.
343This is a shared library only.
344
345Targets Created:
346
347- ``CUDA::nvrtc``
348
349.. _`cuda_toolkit_nvml`:
350
351nvidia-ML
352"""""""""
353
354The `NVIDIA Management Library <https://developer.nvidia.com/nvidia-management-library-nvml>`_.
355This is a shared library only.
356
357Targets Created:
358
359- ``CUDA::nvml``
360
361.. _`cuda_toolkit_nvToolsExt`:
362
363nvToolsExt
364""""""""""
365
366The `NVIDIA Tools Extension <https://docs.nvidia.com/gameworks/content/gameworkslibrary/nvtx/nvidia_tools_extension_library_nvtx.htm>`_.
367This is a shared library only.
368
369Targets Created:
370
371- ``CUDA::nvToolsExt``
372
373.. _`cuda_toolkit_opencl`:
374
375OpenCL
376""""""
377
378The `NVIDIA OpenCL Library <https://developer.nvidia.com/opencl>`_.
379This is a shared library only.
380
381Targets Created:
382
383- ``CUDA::OpenCL``
384
385.. _`cuda_toolkit_cuLIBOS`:
386
387cuLIBOS
388"""""""
389
390The cuLIBOS library is a backend thread abstraction layer library which is
391static only.  The ``CUDA::cublas_static``, ``CUDA::cusparse_static``,
392``CUDA::cufft_static``, ``CUDA::curand_static``, and (when implemented) NPP
393libraries all automatically have this dependency linked.
394
395Target Created:
396
397- ``CUDA::culibos``
398
399**Note**: direct usage of this target by consumers should not be necessary.
400
401.. _`cuda_toolkit_cuRAND`:
402
403
404
405Result variables
406^^^^^^^^^^^^^^^^
407
408``CUDAToolkit_FOUND``
409    A boolean specifying whether or not the CUDA Toolkit was found.
410
411``CUDAToolkit_VERSION``
412    The exact version of the CUDA Toolkit found (as reported by
413    ``nvcc --version`` or ``version.txt``).
414
415``CUDAToolkit_VERSION_MAJOR``
416    The major version of the CUDA Toolkit.
417
418``CUDAToolkit_VERSION_MINOR``
419    The minor version of the CUDA Toolkit.
420
421``CUDAToolkit_VERSION_PATCH``
422    The patch version of the CUDA Toolkit.
423
424``CUDAToolkit_BIN_DIR``
425    The path to the CUDA Toolkit library directory that contains the CUDA
426    executable ``nvcc``.
427
428``CUDAToolkit_INCLUDE_DIRS``
429    The path to the CUDA Toolkit ``include`` folder containing the header files
430    required to compile a project linking against CUDA.
431
432``CUDAToolkit_LIBRARY_DIR``
433    The path to the CUDA Toolkit library directory that contains the CUDA
434    Runtime library ``cudart``.
435
436``CUDAToolkit_LIBRARY_ROOT``
437    .. versionadded:: 3.18
438
439    The path to the CUDA Toolkit directory containing the nvvm directory and
440    version.txt.
441
442``CUDAToolkit_TARGET_DIR``
443    The path to the CUDA Toolkit directory including the target architecture
444    when cross-compiling. When not cross-compiling this will be equivalent to
445    the parent directory of ``CUDAToolkit_BIN_DIR``.
446
447``CUDAToolkit_NVCC_EXECUTABLE``
448    The path to the NVIDIA CUDA compiler ``nvcc``.  Note that this path may
449    **not** be the same as
450    :variable:`CMAKE_CUDA_COMPILER <CMAKE_<LANG>_COMPILER>`.  ``nvcc`` must be
451    found to determine the CUDA Toolkit version as well as determining other
452    features of the Toolkit.  This variable is set for the convenience of
453    modules that depend on this one.
454
455
456#]=======================================================================]
457
458# NOTE: much of this was simply extracted from FindCUDA.cmake.
459
460#   James Bigler, NVIDIA Corp (nvidia.com - jbigler)
461#   Abe Stephens, SCI Institute -- http://www.sci.utah.edu/~abe/FindCuda.html
462#
463#   Copyright (c) 2008 - 2009 NVIDIA Corporation.  All rights reserved.
464#
465#   Copyright (c) 2007-2009
466#   Scientific Computing and Imaging Institute, University of Utah
467#
468#   This code is licensed under the MIT License.  See the FindCUDA.cmake script
469#   for the text of the license.
470
471# The MIT License
472#
473# License for the specific language governing rights and limitations under
474# Permission is hereby granted, free of charge, to any person obtaining a
475# copy of this software and associated documentation files (the "Software"),
476# to deal in the Software without restriction, including without limitation
477# the rights to use, copy, modify, merge, publish, distribute, sublicense,
478# and/or sell copies of the Software, and to permit persons to whom the
479# Software is furnished to do so, subject to the following conditions:
480#
481# The above copyright notice and this permission notice shall be included
482# in all copies or substantial portions of the Software.
483#
484# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
485# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
486# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
487# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
488# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
489# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
490# DEALINGS IN THE SOFTWARE.
491#
492###############################################################################
493
494# The toolkit is located during compiler detection for CUDA and stored in CMakeCUDACompiler.cmake as
495# CMAKE_CUDA_COMPILER_TOOLKIT_ROOT and CMAKE_CUDA_COMPILER_LIBRARY_ROOT.
496# We compute the rest based on those here to avoid re-searching and to avoid finding a possibly
497# different installation.
498if(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT)
499  set(CUDAToolkit_ROOT_DIR "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}")
500  set(CUDAToolkit_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_LIBRARY_ROOT}")
501  set(CUDAToolkit_BIN_DIR "${CUDAToolkit_ROOT_DIR}/bin")
502  set(CUDAToolkit_NVCC_EXECUTABLE "${CUDAToolkit_BIN_DIR}/nvcc${CMAKE_EXECUTABLE_SUFFIX}")
503else()
504
505  function(_CUDAToolkit_find_root_dir )
506    cmake_parse_arguments(arg "" "" "SEARCH_PATHS;FIND_FLAGS" ${ARGN})
507
508
509    if(NOT CUDAToolkit_BIN_DIR)
510      if(NOT CUDAToolkit_SENTINEL_FILE)
511        find_program(CUDAToolkit_NVCC_EXECUTABLE
512          NAMES nvcc nvcc.exe
513          PATHS ${arg_SEARCH_PATHS}
514          ${arg_FIND_FLAGS}
515        )
516      endif()
517
518      if(NOT CUDAToolkit_NVCC_EXECUTABLE)
519        find_file(CUDAToolkit_SENTINEL_FILE
520          NAMES version.txt
521          PATHS ${arg_SEARCH_PATHS}
522          NO_DEFAULT_PATH
523        )
524      endif()
525
526      if(EXISTS "${CUDAToolkit_NVCC_EXECUTABLE}")
527        # If NVCC exists  then invoke it to find the toolkit location.
528        # This allows us to support wrapper scripts (e.g. ccache or colornvcc), CUDA Toolkit,
529        # NVIDIA HPC SDK, and distro's splayed layouts
530        execute_process(COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "-v" "__cmake_determine_cuda"
531          OUTPUT_VARIABLE _CUDA_NVCC_OUT ERROR_VARIABLE _CUDA_NVCC_OUT)
532        if(_CUDA_NVCC_OUT MATCHES "\\#\\$ TOP=([^\r\n]*)")
533          get_filename_component(CUDAToolkit_BIN_DIR "${CMAKE_MATCH_1}/bin" ABSOLUTE)
534        else()
535          get_filename_component(CUDAToolkit_BIN_DIR "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY)
536        endif()
537        unset(_CUDA_NVCC_OUT)
538
539        mark_as_advanced(CUDAToolkit_BIN_DIR)
540        set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}" CACHE PATH "" FORCE)
541      endif()
542
543      if(CUDAToolkit_SENTINEL_FILE)
544        get_filename_component(CUDAToolkit_BIN_DIR ${CUDAToolkit_SENTINEL_FILE} DIRECTORY ABSOLUTE)
545        set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}/bin")
546
547        set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}" CACHE PATH "" FORCE)
548        mark_as_advanced(CUDAToolkit_BIN_DIR)
549      endif()
550    endif()
551
552    if(CUDAToolkit_BIN_DIR)
553      get_filename_component(CUDAToolkit_ROOT_DIR ${CUDAToolkit_BIN_DIR} DIRECTORY ABSOLUTE)
554      set(CUDAToolkit_ROOT_DIR "${CUDAToolkit_ROOT_DIR}" PARENT_SCOPE)
555    endif()
556
557  endfunction()
558
559  function(_CUDAToolkit_find_version_file result_variable)
560    # We first check for a non-scattered installation to prefer it over a scattered installation.
561    if(CUDAToolkit_ROOT AND EXISTS "${CUDAToolkit_ROOT}/version.txt")
562      set(${result_variable} "${CUDAToolkit_ROOT}/version.txt" PARENT_SCOPE)
563    elseif(CUDAToolkit_ROOT_DIR AND EXISTS "${CUDAToolkit_ROOT_DIR}/version.txt")
564      set(${result_variable} "${CUDAToolkit_ROOT_DIR}/version.txt" PARENT_SCOPE)
565    elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/version.txt")
566      set(${result_variable} "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/version.txt" PARENT_SCOPE)
567    elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/cuda/version.txt")
568      set(${result_variable} "${CMAKE_SYSROOT}/usr/lib/cuda/version.txt" PARENT_SCOPE)
569    endif()
570  endfunction()
571
572  # For NVCC we can easily deduce the SDK binary directory from the compiler path.
573  if(CMAKE_CUDA_COMPILER_LOADED AND NOT CUDAToolkit_BIN_DIR AND CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
574    get_filename_component(CUDAToolkit_BIN_DIR "${CMAKE_CUDA_COMPILER}" DIRECTORY)
575    set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}" CACHE PATH "")
576    # Try language provided path first.
577    _CUDAToolkit_find_root_dir(SEARCH_PATHS "${CUDAToolkit_BIN_DIR}" FIND_FLAGS NO_DEFAULT_PATH)
578    mark_as_advanced(CUDAToolkit_BIN_DIR)
579  endif()
580
581  # Try user provided path
582  if(NOT CUDAToolkit_ROOT_DIR AND CUDAToolkit_ROOT)
583    _CUDAToolkit_find_root_dir(SEARCH_PATHS "${CUDAToolkit_ROOT}" FIND_FLAGS PATH_SUFFIXES bin NO_DEFAULT_PATH)
584  endif()
585  if(NOT CUDAToolkit_ROOT_DIR)
586    _CUDAToolkit_find_root_dir(FIND_FLAGS PATHS ENV CUDA_PATH PATH_SUFFIXES bin)
587  endif()
588
589  # If the user specified CUDAToolkit_ROOT but the toolkit could not be found, this is an error.
590  if(NOT CUDAToolkit_ROOT_DIR AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT}))
591    # Declare error messages now, print later depending on find_package args.
592    set(fail_base "Could not find nvcc executable in path specified by")
593    set(cuda_root_fail "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}")
594    set(env_cuda_root_fail "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}")
595
596    if(CUDAToolkit_FIND_REQUIRED)
597      if(DEFINED CUDAToolkit_ROOT)
598        message(FATAL_ERROR ${cuda_root_fail})
599      elseif(DEFINED ENV{CUDAToolkit_ROOT})
600        message(FATAL_ERROR ${env_cuda_root_fail})
601      endif()
602    else()
603      if(NOT CUDAToolkit_FIND_QUIETLY)
604        if(DEFINED CUDAToolkit_ROOT)
605          message(STATUS ${cuda_root_fail})
606        elseif(DEFINED ENV{CUDAToolkit_ROOT})
607          message(STATUS ${env_cuda_root_fail})
608        endif()
609      endif()
610      set(CUDAToolkit_FOUND FALSE)
611      unset(fail_base)
612      unset(cuda_root_fail)
613      unset(env_cuda_root_fail)
614      return()
615    endif()
616  endif()
617
618  # CUDAToolkit_ROOT cmake / env variable not specified, try platform defaults.
619  #
620  # - Linux: /usr/local/cuda-X.Y
621  # - macOS: /Developer/NVIDIA/CUDA-X.Y
622  # - Windows: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y
623  #
624  # We will also search the default symlink location /usr/local/cuda first since
625  # if CUDAToolkit_ROOT is not specified, it is assumed that the symlinked
626  # directory is the desired location.
627  if(NOT CUDAToolkit_ROOT_DIR)
628    if(UNIX)
629      if(NOT APPLE)
630        set(platform_base "/usr/local/cuda-")
631      else()
632        set(platform_base "/Developer/NVIDIA/CUDA-")
633      endif()
634    else()
635      set(platform_base "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v")
636    endif()
637
638    # Build out a descending list of possible cuda installations, e.g.
639    file(GLOB possible_paths "${platform_base}*")
640    # Iterate the glob results and create a descending list.
641    set(versions)
642    foreach(p ${possible_paths})
643      # Extract version number from end of string
644      string(REGEX MATCH "[0-9][0-9]?\\.[0-9]$" p_version ${p})
645      if(IS_DIRECTORY ${p} AND p_version)
646        list(APPEND versions ${p_version})
647      endif()
648    endforeach()
649
650    # Sort numerically in descending order, so we try the newest versions first.
651    list(SORT versions COMPARE NATURAL ORDER DESCENDING)
652
653    # With a descending list of versions, populate possible paths to search.
654    set(search_paths)
655    foreach(v ${versions})
656      list(APPEND search_paths "${platform_base}${v}")
657    endforeach()
658
659    # Force the global default /usr/local/cuda to the front on Unix.
660    if(UNIX)
661      list(INSERT search_paths 0 "/usr/local/cuda")
662    endif()
663
664    # Now search for the toolkit again using the platform default search paths.
665    _CUDAToolkit_find_root_dir(SEARCH_PATHS "${search_paths}" FIND_FLAGS PATH_SUFFIXES bin)
666
667    # We are done with these variables now, cleanup for caller.
668    unset(platform_base)
669    unset(possible_paths)
670    unset(versions)
671    unset(search_paths)
672
673    if(NOT CUDAToolkit_ROOT_DIR)
674      if(CUDAToolkit_FIND_REQUIRED)
675        message(FATAL_ERROR "Could not find nvcc, please set CUDAToolkit_ROOT.")
676      elseif(NOT CUDAToolkit_FIND_QUIETLY)
677        message(STATUS "Could not find nvcc, please set CUDAToolkit_ROOT.")
678      endif()
679
680      set(CUDAToolkit_FOUND FALSE)
681      return()
682    endif()
683  endif()
684
685  _CUDAToolkit_find_version_file( _CUDAToolkit_version_file )
686  if(_CUDAToolkit_version_file)
687    # CUDAToolkit_LIBRARY_ROOT contains the device library and version file.
688    get_filename_component(CUDAToolkit_LIBRARY_ROOT "${_CUDAToolkit_version_file}" DIRECTORY ABSOLUTE)
689  endif()
690  unset(_CUDAToolkit_version_file)
691endif()
692
693# Find target directory when crosscompiling.
694if(CMAKE_CROSSCOMPILING)
695  if(CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7-a")
696    # Support for NVPACK
697    set(CUDAToolkit_TARGET_NAME "armv7-linux-androideabi")
698  elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
699    set(CUDAToolkit_TARGET_NAME "armv7-linux-gnueabihf")
700  elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
701    if(ANDROID_ARCH_NAME STREQUAL "arm64")
702      set(CUDAToolkit_TARGET_NAME "aarch64-linux-androideabi")
703    elseif (CMAKE_SYSTEM_NAME STREQUAL "QNX")
704      set(CUDAToolkit_TARGET_NAME "aarch64-qnx")
705    else()
706      set(CUDAToolkit_TARGET_NAME "aarch64-linux")
707    endif(ANDROID_ARCH_NAME STREQUAL "arm64")
708  elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
709    set(CUDAToolkit_TARGET_NAME "x86_64-linux")
710  endif()
711
712  if(EXISTS "${CUDAToolkit_ROOT_DIR}/targets/${CUDAToolkit_TARGET_NAME}")
713    set(CUDAToolkit_TARGET_DIR "${CUDAToolkit_ROOT_DIR}/targets/${CUDAToolkit_TARGET_NAME}")
714    # add known CUDA target root path to the set of directories we search for programs, libraries and headers
715    list(PREPEND CMAKE_FIND_ROOT_PATH "${CUDAToolkit_TARGET_DIR}")
716
717    # Mark that we need to pop the root search path changes after we have
718    # found all cuda libraries so that searches for our cross-compilation
719    # libraries work when another cuda sdk is in CMAKE_PREFIX_PATH or
720    # PATh
721    set(_CUDAToolkit_Pop_ROOT_PATH True)
722  endif()
723endif()
724
725# If not already set we can simply use the toolkit root or it's a scattered installation.
726if(NOT CUDAToolkit_TARGET_DIR)
727  # Not cross compiling
728  set(CUDAToolkit_TARGET_DIR "${CUDAToolkit_ROOT_DIR}")
729  # Now that we have the real ROOT_DIR, find components inside it.
730  list(APPEND CMAKE_PREFIX_PATH ${CUDAToolkit_ROOT_DIR})
731
732  # Mark that we need to pop the prefix path changes after we have
733  # found the cudart library.
734  set(_CUDAToolkit_Pop_Prefix True)
735endif()
736
737# CUDAToolkit_TARGET_DIR always points to the directory containing the include directory.
738# On a scattered installation /usr, on a non-scattered something like /usr/local/cuda or /usr/local/cuda-10.2/targets/aarch64-linux.
739if(EXISTS "${CUDAToolkit_TARGET_DIR}/include/cuda_runtime.h")
740  set(CUDAToolkit_INCLUDE_DIR "${CUDAToolkit_TARGET_DIR}/include")
741elseif(NOT CUDAToolkit_FIND_QUIETLY)
742  message(STATUS "Unable to find cuda_runtime.h in \"${CUDAToolkit_TARGET_DIR}/include\" for CUDAToolkit_INCLUDE_DIR.")
743endif()
744
745# The NVHPC layout moves math library headers and libraries to a sibling directory.
746# Create a separate variable so this directory can be selectively added to math targets.
747if(NOT EXISTS "${CUDAToolkit_INCLUDE_DIR}/cublas_v2.h")
748  set(CUDAToolkit_MATH_INCLUDE_DIR "${CUDAToolkit_TARGET_DIR}/../../math_libs/include")
749  cmake_path(NORMAL_PATH CUDAToolkit_MATH_INCLUDE_DIR)
750  if(NOT EXISTS "${CUDAToolkit_MATH_INCLUDE_DIR}/cublas_v2.h")
751    if(NOT CUDAToolkit_FIND_QUIETLY)
752      message(STATUS "Unable to find cublas_v2.h in either \"${CUDAToolkit_INCLUDE_DIR}\" or \"${CUDAToolkit_MATH_INCLUDE_DIR}\"")
753    endif()
754    unset(CUDAToolkit_MATH_INCLUDE_DIR)
755  endif()
756endif()
757
758if(CUDAToolkit_NVCC_EXECUTABLE AND
759   CMAKE_CUDA_COMPILER_VERSION AND
760   CUDAToolkit_NVCC_EXECUTABLE STREQUAL CMAKE_CUDA_COMPILER)
761  # Need to set these based off the already computed CMAKE_CUDA_COMPILER_VERSION value
762  # This if statement will always match, but is used to provide variables for MATCH 1,2,3...
763  if(CMAKE_CUDA_COMPILER_VERSION MATCHES [=[([0-9]+)\.([0-9]+)\.([0-9]+)]=])
764    set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}")
765    set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}")
766    set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}")
767    set(CUDAToolkit_VERSION "${CMAKE_CUDA_COMPILER_VERSION}")
768  endif()
769elseif(CUDAToolkit_NVCC_EXECUTABLE)
770  # Compute the version by invoking nvcc
771  execute_process(COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT)
772  if(NVCC_OUT MATCHES [=[ V([0-9]+)\.([0-9]+)\.([0-9]+)]=])
773    set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}")
774    set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}")
775    set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}")
776    set(CUDAToolkit_VERSION  "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
777  endif()
778  unset(NVCC_OUT)
779else()
780  _CUDAToolkit_find_version_file(version_file)
781  if(version_file)
782    file(READ "${version_file}" VERSION_INFO)
783    if(VERSION_INFO MATCHES [=[CUDA Version ([0-9]+)\.([0-9]+)\.([0-9]+)]=])
784      set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}")
785      set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}")
786      set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}")
787      set(CUDAToolkit_VERSION  "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
788    endif()
789  endif()
790endif()
791
792# Find the CUDA Runtime Library libcudart
793find_library(CUDA_CUDART
794  NAMES cudart
795  PATH_SUFFIXES lib64 lib/x64
796)
797find_library(CUDA_CUDART
798  NAMES cudart
799  PATH_SUFFIXES lib64/stubs lib/x64/stubs
800)
801
802if(NOT CUDA_CUDART AND NOT CUDAToolkit_FIND_QUIETLY)
803  message(STATUS "Unable to find cudart library.")
804endif()
805
806if(_CUDAToolkit_Pop_Prefix)
807  list(REMOVE_AT CMAKE_PREFIX_PATH -1)
808  unset(_CUDAToolkit_Pop_Prefix)
809endif()
810
811#-----------------------------------------------------------------------------
812# Perform version comparison and validate all required variables are set.
813include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
814find_package_handle_standard_args(CUDAToolkit
815  REQUIRED_VARS
816    CUDAToolkit_INCLUDE_DIR
817    CUDA_CUDART
818    CUDAToolkit_BIN_DIR
819  VERSION_VAR
820    CUDAToolkit_VERSION
821)
822
823unset(CUDAToolkit_ROOT_DIR)
824mark_as_advanced(CUDA_CUDART
825                 CUDAToolkit_INCLUDE_DIR
826                 CUDAToolkit_NVCC_EXECUTABLE
827                 CUDAToolkit_SENTINEL_FILE
828                 )
829
830#-----------------------------------------------------------------------------
831# Construct result variables
832if(CUDAToolkit_FOUND)
833  set(CUDAToolkit_INCLUDE_DIRS ${CUDAToolkit_INCLUDE_DIR})
834  get_filename_component(CUDAToolkit_LIBRARY_DIR ${CUDA_CUDART} DIRECTORY ABSOLUTE)
835endif()
836
837#-----------------------------------------------------------------------------
838# Construct import targets
839if(CUDAToolkit_FOUND)
840
841  function(_CUDAToolkit_find_and_add_import_lib lib_name)
842    cmake_parse_arguments(arg "" "" "ALT;DEPS;EXTRA_PATH_SUFFIXES" ${ARGN})
843
844    set(search_names ${lib_name} ${arg_ALT})
845
846    find_library(CUDA_${lib_name}_LIBRARY
847      NAMES ${search_names}
848      HINTS ${CUDAToolkit_LIBRARY_DIR}
849            ENV CUDA_PATH
850      PATH_SUFFIXES nvidia/current lib64 lib/x64 lib
851                    ${arg_EXTRA_PATH_SUFFIXES}
852    )
853    # Don't try any stub directories until we have exhausted all other
854    # search locations.
855    find_library(CUDA_${lib_name}_LIBRARY
856      NAMES ${search_names}
857      HINTS ${CUDAToolkit_LIBRARY_DIR}
858            ENV CUDA_PATH
859      PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs
860                    # Support NVHPC splayed math library layout
861                    ../../math_libs/${CUDAToolkit_VERSION_MAJOR}.${CUDAToolkit_VERSION_MINOR}/lib64
862                    ../../math_libs/lib64
863    )
864
865    mark_as_advanced(CUDA_${lib_name}_LIBRARY)
866
867    if (NOT TARGET CUDA::${lib_name} AND CUDA_${lib_name}_LIBRARY)
868      add_library(CUDA::${lib_name} UNKNOWN IMPORTED)
869      target_include_directories(CUDA::${lib_name} SYSTEM INTERFACE "${CUDAToolkit_INCLUDE_DIRS}")
870      if(DEFINED CUDAToolkit_MATH_INCLUDE_DIR)
871        string(FIND ${CUDA_${lib_name}_LIBRARY} "math_libs" math_libs)
872        if(NOT ${math_libs} EQUAL -1)
873          target_include_directories(CUDA::${lib_name} SYSTEM INTERFACE "${CUDAToolkit_MATH_INCLUDE_DIR}")
874        endif()
875      endif()
876      set_property(TARGET CUDA::${lib_name} PROPERTY IMPORTED_LOCATION "${CUDA_${lib_name}_LIBRARY}")
877      foreach(dep ${arg_DEPS})
878        if(TARGET CUDA::${dep})
879          target_link_libraries(CUDA::${lib_name} INTERFACE CUDA::${dep})
880        endif()
881      endforeach()
882    endif()
883  endfunction()
884
885  if(NOT TARGET CUDA::toolkit)
886    add_library(CUDA::toolkit IMPORTED INTERFACE)
887    target_include_directories(CUDA::toolkit SYSTEM INTERFACE "${CUDAToolkit_INCLUDE_DIRS}")
888    target_link_directories(CUDA::toolkit INTERFACE "${CUDAToolkit_LIBRARY_DIR}")
889  endif()
890
891  _CUDAToolkit_find_and_add_import_lib(cuda_driver ALT cuda)
892
893  _CUDAToolkit_find_and_add_import_lib(cudart)
894  _CUDAToolkit_find_and_add_import_lib(cudart_static)
895
896  # setup dependencies that are required for cudart_static when building
897  # on linux. These are generally only required when using the CUDA toolkit
898  # when CUDA language is disabled
899  if(NOT TARGET CUDA::cudart_static_deps
900     AND TARGET CUDA::cudart_static)
901
902    add_library(CUDA::cudart_static_deps IMPORTED INTERFACE)
903    target_link_libraries(CUDA::cudart_static INTERFACE CUDA::cudart_static_deps)
904
905    if(UNIX AND (CMAKE_C_COMPILER OR CMAKE_CXX_COMPILER))
906      find_package(Threads REQUIRED)
907      target_link_libraries(CUDA::cudart_static_deps INTERFACE Threads::Threads ${CMAKE_DL_LIBS})
908    endif()
909
910    if(UNIX AND NOT APPLE AND NOT (CMAKE_SYSTEM_NAME STREQUAL "QNX"))
911      # On Linux, you must link against librt when using the static cuda runtime.
912      find_library(CUDAToolkit_rt_LIBRARY rt)
913      mark_as_advanced(CUDAToolkit_rt_LIBRARY)
914      if(NOT CUDAToolkit_rt_LIBRARY)
915        message(WARNING "Could not find librt library, needed by CUDA::cudart_static")
916      else()
917        target_link_libraries(CUDA::cudart_static_deps INTERFACE ${CUDAToolkit_rt_LIBRARY})
918      endif()
919    endif()
920  endif()
921
922  _CUDAToolkit_find_and_add_import_lib(culibos) # it's a static library
923  foreach (cuda_lib cublasLt cublas cufft curand cusparse nppc nvjpeg)
924    _CUDAToolkit_find_and_add_import_lib(${cuda_lib})
925    _CUDAToolkit_find_and_add_import_lib(${cuda_lib}_static DEPS culibos)
926  endforeach()
927
928  # cuFFTW depends on cuFFT
929  _CUDAToolkit_find_and_add_import_lib(cufftw DEPS cufft)
930  _CUDAToolkit_find_and_add_import_lib(cufftw DEPS cufft_static)
931
932  # cuSOLVER depends on cuBLAS, and cuSPARSE
933  _CUDAToolkit_find_and_add_import_lib(cusolver DEPS cublas cusparse)
934  _CUDAToolkit_find_and_add_import_lib(cusolver_static DEPS cublas_static cusparse_static culibos)
935
936  # nvGRAPH depends on cuRAND, and cuSOLVER.
937  _CUDAToolkit_find_and_add_import_lib(nvgraph DEPS curand cusolver)
938  _CUDAToolkit_find_and_add_import_lib(nvgraph_static DEPS curand_static cusolver_static)
939
940  # Process the majority of the NPP libraries.
941  foreach (cuda_lib nppial nppicc nppidei nppif nppig nppim nppist nppitc npps nppicom nppisu)
942    _CUDAToolkit_find_and_add_import_lib(${cuda_lib} DEPS nppc)
943    _CUDAToolkit_find_and_add_import_lib(${cuda_lib}_static DEPS nppc_static)
944  endforeach()
945
946  _CUDAToolkit_find_and_add_import_lib(cupti
947                                       EXTRA_PATH_SUFFIXES ../extras/CUPTI/lib64/
948                                                           ../extras/CUPTI/lib/)
949  _CUDAToolkit_find_and_add_import_lib(cupti_static
950                                       EXTRA_PATH_SUFFIXES ../extras/CUPTI/lib64/
951                                                           ../extras/CUPTI/lib/)
952
953  _CUDAToolkit_find_and_add_import_lib(nvrtc DEPS cuda_driver)
954
955  _CUDAToolkit_find_and_add_import_lib(nvml ALT nvidia-ml nvml)
956
957  if(WIN32)
958    # nvtools can be installed outside the CUDA toolkit directory
959    # so prefer the NVTOOLSEXT_PATH windows only environment variable
960    # In addition on windows the most common name is nvToolsExt64_1
961    find_library(CUDA_nvToolsExt_LIBRARY
962      NAMES nvToolsExt64_1 nvToolsExt64 nvToolsExt
963      PATHS ENV NVTOOLSEXT_PATH
964            ENV CUDA_PATH
965      PATH_SUFFIXES lib/x64 lib
966    )
967  endif()
968  _CUDAToolkit_find_and_add_import_lib(nvToolsExt ALT nvToolsExt64)
969
970  _CUDAToolkit_find_and_add_import_lib(OpenCL)
971endif()
972
973if(_CUDAToolkit_Pop_ROOT_PATH)
974  list(REMOVE_AT CMAKE_FIND_ROOT_PATH 0)
975  unset(_CUDAToolkit_Pop_ROOT_PATH)
976endif()
977