This repository has been archived by the owner on May 7, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
FindCUDALibs.cmake
188 lines (162 loc) · 7.09 KB
/
FindCUDALibs.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# TODO: make this an actual find module...allow VERSION, QUIET, etc
# TODO: don't use find_package(CUDA)? But the thread specifically states that
# we should *NOT* require that enable_language(CUDA) has been done,
# meaning that e.g. CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES may not exist?
#
# Solution?
# include(CheckLanguage)
# check_language(CUDA)
# if (NOT CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES)
# --> then we cannot win?
find_package(CUDA REQUIRED)
# Populate the list of default locations to search for the CUDA libraries.
# TODO: allow user bypass of this?
list(APPEND CUDALibs_HINTS "${CUDA_TOOLKIT_ROOT_DIR}/lib64")
list(APPEND CUDALibs_HINTS "${CUDA_TOOLKIT_ROOT_DIR}/lib")
list(APPEND CUDALibs_HINTS "${CUDA_TOOLKIT_ROOT_DIR}")
function(find_and_add_cuda_import_lib lib_name)
string(TOUPPER ${lib_name} LIB_NAME)
find_library(CUDA_${LIB_NAME} ${lib_name} HINTS ${CUDALibs_HINTS})
if (NOT CUDA_${LIB_NAME} STREQUAL CUDA_${LIB_NAME}-NOTFOUND)
add_library(CUDA::${lib_name} IMPORTED INTERFACE)
set_target_properties(CUDA::${lib_name}
PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES
"${CUDA_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES
"${CUDA_${LIB_NAME}}"
)
endif()
endfunction()
# TODO: how to make sure `dependency` can actually be used
# TODO: if dependency cannot be used, is it possible to
# delete CUDA::${lib_name}?
function(add_cuda_link_dependency lib_name dependency)
set_property(
TARGET CUDA::${lib_name}
APPEND
PROPERTY
INTERFACE_LINK_LIBRARIES ${dependency}
)
endfunction()
# Find the main CUDA runtime dynamic and static libraries.
# These are a hard dependency for all other libraries, and
# must be found.
# TODO: right way to error out?
find_and_add_cuda_import_lib(cudart)
find_and_add_cuda_import_lib(cudart_static)
# TODO: what about windows???
if (UNIX)
foreach (lib dl pthread rt)
add_cuda_link_dependency(cudart_static ${lib})
endforeach()
endif()
# TODO: nvBLAS and example. Depends on cuBLAS, but not sure how it works.
# Testing executable may need to find_package(BLAS)? It seems like the idea is
# you write a standard BLAS level 3 operation, and at link time nvBLAS will take
# over somehow?
# cuBLAS treated specially, static library needs to link against a BLAS
# library for *gemm_ symbols. So both dynamic and static library are only added
# if BLAS can be found for consistency (missing dynamic case will be a library
# load error at runtime).
# Find dynamic blas for cusolver dynamic target
set(BLA_STATIC OFF)
find_package(BLAS)
if (BLAS_FOUND)
find_and_add_cuda_import_lib(cublas)
add_cuda_link_dependency(cublas CUDA::cudart)
add_cuda_link_dependency(cublas ${BLAS_LIBRARIES})
endif()
# Find static blas for cublas static target
set(BLAS_FOUND OFF)
set(BLA_STATIC ON)
find_package(BLAS)
if (BLAS_FOUND)
find_and_add_cuda_import_lib(cublas_static)
add_cuda_link_dependency(cublas_static CUDA::cudart_static)
add_cuda_link_dependency(cublas_static ${BLAS_LIBRARIES})
endif()
# TODO: (nppi* nvblas)
foreach (cuda_lib cufft cufftw curand cusolver cusparse nvgraph nvjpeg)
# find the dynamic library
find_and_add_cuda_import_lib(${cuda_lib})
add_cuda_link_dependency(${cuda_lib} CUDA::cudart)
# TODO: if UNIX and VERSION >= 6.5
# find the static library
find_and_add_cuda_import_lib(${cuda_lib}_static)
add_cuda_link_dependency(${cuda_lib}_static CUDA::cudart_static)
endforeach()
# NVRTC (Runtime Compilation) is a shared library only.
# TODO: nvrtc needs -lcuda (*NOT* cudart), but -lcuda (at least on this system)
# is going to point to /lib64/libcuda.so.
#
# Since this is not in the HINTS paths searched above, what is the right
# way to create the CUDA::cuda target?
find_and_add_cuda_import_lib(nvrtc)
add_cuda_link_dependency(nvrtc cuda)
# NVTX is a shared library only.
# TODO: is this even useful outside of NSight Eclipse?
find_and_add_cuda_import_lib(nvToolsExt)
add_cuda_link_dependency(nvToolsExt CUDA::cudart)
# cuLIBOS is a static only library, see
#
# https://devblogs.nvidia.com/10-ways-cuda-6-5-improves-performance-productivity
#
# > Static CUDA Libraries
# > CUDA 6.5 (on Linux and Mac OS) now includes static library versions of the
# > cuBLAS, cuSPARSE, cuFFT, cuRAND, and NPP libraries. This can reduce the
# > number of dynamic library dependencies you need to include with your
# > deployed applications. These new static libraries depend on a common thread
# > abstraction layer library cuLIBOS (libculibos.a) distributed as part of the
# > CUDA toolkit.
find_and_add_cuda_import_lib(culibos)
# foreach (cuda_lib cublas cusparse cufft) # curand npp
foreach (cuda_lib cublas cufft cusparse curand nvjpeg)# npp
add_cuda_link_dependency(${cuda_lib}_static CUDA::culibos)
endforeach()
# cuSOLVER depends on cuBLAS and cuSPARSE
# NOTE: nvGRAPH relies on this, make sure it happens before nvGRAPH dependencies.
foreach (dep cublas cusparse)
add_cuda_link_dependency(cusolver CUDA::${dep})
add_cuda_link_dependency(cusolver_static CUDA::${dep}_static)
endforeach()
# nvGRAPH depends on cuBLAS, cuRAND, cuSPARSE, and cuSOLVER.
# NOTE: rely on link dependencies of cuSOLVER, this must happen after cusolver target.
foreach (dep cusolver curand)
add_cuda_link_dependency(nvgraph CUDA::${dep})
add_cuda_link_dependency(nvgraph_static CUDA::${dep}_static)
endforeach()
# NPP libraries and dependencies. See: https://docs.nvidia.com/cuda/npp/index.html
# TODO: document what nppc is (seems to be the underlying implementation for most of NPP?)
find_and_add_cuda_import_lib(nppc)
find_and_add_cuda_import_lib(nppc_static)
# Process the majority of the NPP libraries.
foreach (cuda_lib nppial nppicc nppidei nppif nppig nppim nppist nppitc npps)
# Find the libraries.
find_and_add_cuda_import_lib(${cuda_lib})
find_and_add_cuda_import_lib(${cuda_lib}_static)
# Designate dynamic link dependencies.
add_cuda_link_dependency(${cuda_lib} CUDA::cudart)
# TODO: add this in since it is needed in static or rely on existing dynamic links?
# add_cuda_link_dependency(${cuda_lib} CUDA::nppc)
# Designate static link dependencies.
add_cuda_link_dependency(${cuda_lib}_static CUDA::cudart_static)
add_cuda_link_dependency(${cuda_lib}_static CUDA::nppc_static)
add_cuda_link_dependency(${cuda_lib}_static CUDA::culibos)
endforeach()
# nppicom: JPEG compression and decompression functions in nppi_compression_functions.h
find_and_add_cuda_import_lib(nppicom)
find_and_add_cuda_import_lib(nppicom_static)
# nppisu: memory support functions in nppi_support_functions.h
find_and_add_cuda_import_lib(nppisu)
find_and_add_cuda_import_lib(nppisu_static)
add_cuda_link_dependency(nppisu CUDA::cudart)
add_cuda_link_dependency(nppisu_static CUDA::cudart_static)
# TODO: mysterious extra static libraries...what are they for?
find_and_add_cuda_import_lib(cudadevrt)
find_and_add_cuda_import_lib(cublas_device)
# TODO: VERSION 9.2, search libcufft_static_nocallback.a
# https://docs.nvidia.com/cuda/cufft/index.html#oned-complex-to-complex-transforms
# Do not expose these functions externally.
unset(find_and_add_cuda_import_lib)
unset(add_cuda_link_dependency)