1
###############################################################################
2
# For more information, please see: http://software.sci.utah.edu
6
# Copyright (c) 2007-2008
7
# Scientific Computing and Imaging Institute, University of Utah
9
# License for the specific language governing rights and limitations under
10
# Permission is hereby granted, free of charge, to any person obtaining a
11
# copy of this software and associated documentation files (the "Software"),
12
# to deal in the Software without restriction, including without limitation
13
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
14
# and/or sell copies of the Software, and to permit persons to whom the
15
# Software is furnished to do so, subject to the following conditions:
17
# The above copyright notice and this permission notice shall be included
18
# in all copies or substantial portions of the Software.
20
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
# DEALINGS IN THE SOFTWARE.
28
# This script locates the Nvidia Compute Unified Driver Architecture (CUDA)
29
# tools. It should work on linux, windows, and mac and should be reasonably
30
# up to date with cuda releases.
32
# The script will prompt the user to specify CUDA_INSTALL_PREFIX if the
33
# prefix cannot be determined by the location of nvcc in the system path. To
34
# use a different installed version of the toolkit set the environment variable
35
# CUDA_BIN_PATH before running cmake (e.g. CUDA_BIN_PATH=/usr/local/cuda1.0
36
# instead of the default /usr/local/cuda).
38
# Set MT_CUDA_BUILD_TYPE to "Device" or "Emulation" mode.
39
# _DEVICEEMU is defined in "Emulation" mode.
41
# Set CUDA_BUILD_CUBIN to "ON" or "OFF" to enable and extra compilation pass
42
# with the -cubin option in Device mode. The output is parsed and register,
43
# shared memory usage is printed during build. Default ON.
45
# The script creates the following macros:
46
# CUDA_INCLUDE_DIRECTORIES( path0 path1 ... )
47
# -- Sets the directories that should be passed to nvcc
48
# (e.g. nvcc -Ipath0 -Ipath1 ... ). These paths usually contain other .cu
51
# CUDA_ADD_LIBRARY( cuda_target file0 file1 ... )
52
# -- Creates a shared library "cuda_target" which contains all of the source
53
# (*.c, *.cc, etc.) specified and all of the nvcc'ed .cu files specified.
54
# All of the specified source files and generated .cpp files are compiled
55
# using the standard CMake compiler, so the normal INCLUDE_DIRECTORIES,
56
# LINK_DIRECTORIES, and TARGET_LINK_LIBRARIES can be used to affect their
59
# CUDA_ADD_EXECUTABLE( cuda_target file0 file1 ... )
60
# -- Same as CUDA_ADD_LIBRARY except that an exectuable is created.
62
# CUDA_COMPILE( cuda_files file0 file1 ... )
63
# -- Returns a list of build commands in the first argument to be used with
64
# ADD_LIBRARY or ADD_EXECUTABLE.
66
# The script defines the following variables:
68
# ( Note CUDA_ADD_* macros setup cuda/cut library dependencies automatically.
69
# These variables are only needed if a cuda API call must be made from code in
70
# a outside library or executable. )
72
# CUDA_INCLUDE -- Include directory for cuda headers.
73
# CUDA_TARGET_LINK -- Cuda RT library.
74
# CUDA_CUT_INCLUDE -- Include directory for cuda SDK headers (cutil.h).
75
# CUDA_CUT_TARGET_LINK -- SDK libraries.
76
# CUDA_NVCC_FLAGS -- Additional NVCC command line arguments. NOTE:
77
# multiple arguments must be semi-colon delimited
78
# e.g. --compiler-options;-Wall
79
# CUBLAS_TARGET_LINK-- cublas library name.
80
# CUFFT_TARGET_LINK -- cubfft library name.
82
# The nvcc flag "--host-compilation;c++" should be used if functions declared
83
# as __host__ contain C++ code.
85
# It might be necessary to set CUDA_INSTALL_PATH manually on certain platforms,
86
# or to use a cuda runtime not installed in the default location. In newer
87
# versions of the toolkit the cuda library is included with the graphics
88
# driver- be sure that the driver version matches what is needed by the cuda
91
# -- Abe Stephens SCI Institute -- http://www.sci.utah.edu/~abe/FindCuda.html
92
###############################################################################
95
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
97
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CudaDependency.cmake)
99
###############################################################################
100
###############################################################################
101
# Locate CUDA, Set Build Type, etc.
102
###############################################################################
103
###############################################################################
105
# Parse CUDA build type.
106
IF (NOT MT_CUDA_BUILD_TYPE)
107
SET(MT_CUDA_BUILD_TYPE "Device" CACHE STRING "Cuda build type: Emulation or Device")
108
ENDIF(NOT MT_CUDA_BUILD_TYPE)
110
# Emulation if the card isn't present.
111
IF (MT_CUDA_BUILD_TYPE MATCHES "Emulation")
113
SET(nvcc_flags --device-emulation -D_DEVICEEMU -g)
114
ELSE(MT_CUDA_BUILD_TYPE MATCHES "Emulation")
117
ENDIF(MT_CUDA_BUILD_TYPE MATCHES "Emulation")
119
SET(CUDA_BUILD_CUBIN TRUE CACHE BOOL "Generate and parse .cubin files in Device mode.")
120
SET(CUDA_NVCC_FLAGS "" CACHE STRING "Semi-colon delimit multiple arguments.")
122
# Search for the cuda distribution.
123
IF(NOT CUDA_INSTALL_PREFIX)
124
FIND_PATH(CUDA_INSTALL_PREFIX
126
PATHS /usr/local/cuda
129
DOC "Toolkit location."
131
IF (CUDA_INSTALL_PREFIX)
132
STRING(REGEX REPLACE "[/\\\\]?bin[/\\\\]?$" "" CUDA_INSTALL_PREFIX ${CUDA_INSTALL_PREFIX})
133
ENDIF(CUDA_INSTALL_PREFIX)
134
IF (NOT EXISTS ${CUDA_INSTALL_PREFIX})
135
MESSAGE(FATAL_ERROR "Specify CUDA_INSTALL_PREFIX")
136
ENDIF (NOT EXISTS ${CUDA_INSTALL_PREFIX})
137
ENDIF (NOT CUDA_INSTALL_PREFIX)
141
FIND_PROGRAM(CUDA_NVCC
143
PATHS ${CUDA_INSTALL_PREFIX}/bin $ENV{CUDA_BIN_PATH}
146
MESSAGE(FATAL_ERROR "Could not find nvcc")
148
MARK_AS_ADVANCED(CUDA_NVCC)
152
# CUDA_NVCC_INCLUDE_ARGS
153
# IF (NOT FOUND_CUDA_NVCC_INCLUDE)
154
FIND_PATH(FOUND_CUDA_NVCC_INCLUDE
155
device_functions.h # Header included in toolkit
156
PATHS ${CUDA_INSTALL_PREFIX}/include
160
IF(NOT FOUND_CUDA_NVCC_INCLUDE)
161
MESSAGE(FATAL_ERROR "Could not find Cuda headers")
162
ELSE(NOT FOUND_CUDA_NVCC_INCLUDE)
163
# Set the initial include dir.
164
SET (CUDA_NVCC_INCLUDE_ARGS "-I"${FOUND_CUDA_NVCC_INCLUDE})
165
SET (CUDA_INCLUDE ${FOUND_CUDA_NVCC_INCLUDE})
168
FOUND_CUDA_NVCC_INCLUDE
169
CUDA_NVCC_INCLUDE_ARGS
171
ENDIF(NOT FOUND_CUDA_NVCC_INCLUDE)
173
# ENDIF(NOT FOUND_CUDA_NVCC_INCLUDE)
177
IF (NOT CUDA_TARGET_LINK)
179
FIND_LIBRARY(FOUND_CUDART
181
PATHS ${CUDA_INSTALL_PREFIX}/lib $ENV{CUDA_LIB_PATH}
182
DOC "\"cudart\" library"
185
# Check to see if cudart library was found.
187
MESSAGE(FATAL_ERROR "Could not find cudart library (cudart)")
188
ENDIF(NOT FOUND_CUDART)
190
# 1.1 toolkit on linux doesn't appear to have a separate library on
192
FIND_LIBRARY(FOUND_CUDA
194
PATHS ${CUDA_INSTALL_PREFIX}/lib
195
DOC "\"cuda\" library (older versions only)."
197
NO_CMAKE_ENVIRONMENT_PATH
199
NO_SYSTEM_ENVIRONMENT_PATH
203
# Add cuda library to the link line only if it is found.
205
SET(CUDA_TARGET_LINK ${FOUND_CUDA})
208
# Always add cudart to the link line.
211
${CUDA_TARGET_LINK} ${FOUND_CUDART}
220
MESSAGE(FATAL_ERROR "Could not find cuda libraries.")
223
ENDIF(NOT CUDA_TARGET_LINK)
226
IF(NOT CUDA_CUT_INCLUDE)
227
FIND_PATH(FOUND_CUT_INCLUDE
229
PATHS ${CUDA_INSTALL_PREFIX}/local/NVSDK0.2/common/inc
230
${CUDA_INSTALL_PREFIX}/NVSDK0.2/common/inc
231
${CUDA_INSTALL_PREFIX}/NV_CUDA_SDK/common/inc
232
$ENV{HOME}/NVIDIA_CUDA_SDK/common/inc
233
$ENV{HOME}/NVIDIA_CUDA_SDK_MACOSX/common/inc
234
$ENV{NVSDKCUDA_ROOT}/common/inc
235
DOC "Location of cutil.h"
237
IF(FOUND_CUT_INCLUDE)
238
SET(CUDA_CUT_INCLUDE ${FOUND_CUT_INCLUDE})
242
ENDIF(FOUND_CUT_INCLUDE)
243
ENDIF(NOT CUDA_CUT_INCLUDE)
246
# CUDA_CUT_TARGET_LINK
247
IF(NOT CUDA_CUT_TARGET_LINK)
248
FIND_LIBRARY(FOUND_CUT
251
PATHS ${CUDA_INSTALL_PREFIX}/local/NVSDK0.2/lib
252
${CUDA_INSTALL_PREFIX}/NVSDK0.2/lib
253
${CUDA_INSTALL_PREFIX}/NV_CUDA_SDK/lib
254
$ENV{HOME}/NVIDIA_CUDA_SDK/lib
255
$ENV{HOME}/NVIDIA_CUDA_SDK_MACOSX/lib
256
$ENV{NVSDKCUDA_ROOT}/common/lib
258
NO_CMAKE_ENVIRONMENT_PATH
260
NO_SYSTEM_ENVIRONMENT_PATH
262
DOC "Location of cutil library"
265
SET(CUDA_CUT_TARGET_LINK ${FOUND_CUT})
271
# Add variables for cufft and cublas target link
272
FIND_LIBRARY(FOUND_CUFFTEMU
274
PATHS ${CUDA_INSTALL_PREFIX}/lib $ENV{CUDA_LIB_PATH}
275
DOC "\"cufftemu\" library"
277
FIND_LIBRARY(FOUND_CUBLASEMU
279
PATHS ${CUDA_INSTALL_PREFIX}/lib $ENV{CUDA_LIB_PATH}
280
DOC "\"cublasemu\" library"
282
FIND_LIBRARY(FOUND_CUFFT
284
PATHS ${CUDA_INSTALL_PREFIX}/lib $ENV{CUDA_LIB_PATH}
285
DOC "\"cufft\" library"
287
FIND_LIBRARY(FOUND_CUBLAS
289
PATHS ${CUDA_INSTALL_PREFIX}/lib $ENV{CUDA_LIB_PATH}
290
DOC "\"cublas\" library"
293
IF (MT_CUDA_BUILD_TYPE MATCHES "Emulation")
294
SET(CUFFT_TARGET_LINK ${FOUND_CUFFTEMU})
295
SET(CUBLAS_TARGET_LINK ${FOUND_CUBLASEMU})
296
ELSE(MT_CUDA_BUILD_TYPE MATCHES "Emulation")
297
SET(CUFFT_TARGET_LINK ${FOUND_CUFFT})
298
SET(CUBLAS_TARGET_LINK ${FOUND_CUBLAS})
299
ENDIF(MT_CUDA_BUILD_TYPE MATCHES "Emulation")
304
ENDIF(NOT CUDA_CUT_TARGET_LINK)
307
###############################################################################
308
# Add include directories to pass to the nvcc command.
309
MACRO(CUDA_INCLUDE_DIRECTORIES)
311
SET(CUDA_NVCC_INCLUDE_ARGS ${CUDA_NVCC_INCLUDE_ARGS} -I${dir})
312
ENDFOREACH(dir ${ARGN})
313
ENDMACRO(CUDA_INCLUDE_DIRECTORIES)
316
##############################################################################
317
##############################################################################
318
# This helper macro populates the following variables and setups up custom commands and targets to
319
# invoke the nvcc compiler. The compiler is invoked once with -M to generate a dependency file and
320
# a second time with -cuda to generate a .cpp file
323
##############################################################################
324
##############################################################################
326
MACRO(CUDA_add_custom_commands cuda_target)
329
SET(cuda_cu_sources "")
331
# Iterate over the macro arguments and create custom
332
# commands for all the .cu files.
333
FOREACH(file ${ARGN})
334
IF(${file} MATCHES ".*\\.cu$")
336
# Add a custom target to generate a c file.
337
SET(generated_file "${CMAKE_BINARY_DIR}/${file}_${cuda_target}_generated.cpp")
338
SET(generated_target "${file}_target")
340
FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR})
342
SET(source_file ${CMAKE_CURRENT_SOURCE_DIR}/${file})
344
# MESSAGE("${CUDA_NVCC} ${source_file} ${CUDA_NVCC_FLAGS} ${nvcc_flags} -cuda -o ${generated_file} ${CUDA_NVCC_INCLUDE_ARGS}")
346
# Bring in the dependencies. Creates a variable CUDA_NVCC_DEPEND
347
SET(cmake_dependency_file "${generated_file}.depend")
348
CUDA_INCLUDE_NVCC_DEPENDENCIES(${cmake_dependency_file})
349
SET(NVCC_generated_dependency_file "${generated_file}.NVCC-depend")
352
# Build the NVCC made dependency file
353
IF (MT_CUDA_BUILD_TYPE MATCHES "Device" AND CUDA_BUILD_CUBIN)
354
SET(NVCC_generated_cubin_file "${generated_file}.NVCC-cubin.txt")
357
# Generate the .cubin output.
358
OUTPUT ${NVCC_generated_cubin_file}
365
-o ${NVCC_generated_cubin_file}
366
${CUDA_NVCC_INCLUDE_ARGS}
368
# Execute the parser script.
369
COMMAND ${CMAKE_COMMAND}
371
-D input_file="${NVCC_generated_cubin_file}"
372
-P "${CMAKE_SOURCE_DIR}/cmake/parse_cubin.cmake"
375
# MAIN_DEPENDENCY ${source_file}
376
DEPENDS ${source_file}
377
DEPENDS ${CUDA_NVCC_DEPEND}
381
COMMENT "Building (${MT_CUDA_BUILD_TYPE}) NVCC -cubin File: ${NVCC_generated_cubin_file}\n"
383
ELSE (MT_CUDA_BUILD_TYPE MATCHES "Device" AND CUDA_BUILD_CUBIN)
384
# Depend on something that will exist.
385
SET(NVCC_generated_cubin_file "${source_file}")
386
ENDIF (MT_CUDA_BUILD_TYPE MATCHES "Device"AND CUDA_BUILD_CUBIN)
388
# Build the NVCC made dependency file
390
OUTPUT ${NVCC_generated_dependency_file}
397
-o ${NVCC_generated_dependency_file}
398
${CUDA_NVCC_INCLUDE_ARGS}
399
# MAIN_DEPENDENCY ${source_file}
400
DEPENDS ${source_file}
401
DEPENDS ${CUDA_NVCC_DEPEND}
402
COMMENT "Building (${MT_CUDA_BUILD_TYPE}) NVCC Dependency File: ${NVCC_generated_dependency_file}\n"
405
# Build the CMake readible dependency file
407
OUTPUT ${cmake_dependency_file}
408
COMMAND ${CMAKE_COMMAND}
410
-D input_file="${NVCC_generated_dependency_file}"
411
-D output_file="${cmake_dependency_file}"
412
-P "${CMAKE_SOURCE_DIR}/cmake/make2cmake.cmake"
413
MAIN_DEPENDENCY ${NVCC_generated_dependency_file}
414
COMMENT "Converting NVCC dependency to CMake (${cmake_dependency_file})"
418
OUTPUT ${generated_file}
419
MAIN_DEPENDENCY ${source_file}
420
DEPENDS ${CUDA_NVCC_DEPEND}
421
DEPENDS ${cmake_dependency_file}
422
DEPENDS ${NVCC_generated_cubin_file}
429
-cuda -o ${generated_file}
430
${CUDA_NVCC_INCLUDE_ARGS}
431
COMMENT "Building (${MT_CUDA_BUILD_TYPE}) NVCC ${source_file}: ${generated_file}\n"
434
SET(cuda_cu_sources ${cuda_cu_sources} ${source_file})
436
# Add the generated file name to the source list.
437
SET(target_srcs ${target_srcs} ${generated_file})
439
ELSE(${file} MATCHES ".*\\.cu$")
441
# Otherwise add the file name to the source list.
442
SET(target_srcs ${target_srcs} ${file})
444
ENDIF(${file} MATCHES ".*\\.cu$")
447
ENDMACRO(CUDA_add_custom_commands)
449
###############################################################################
450
###############################################################################
452
###############################################################################
453
###############################################################################
454
MACRO(CUDA_ADD_LIBRARY cuda_target)
456
# Create custom commands and targets for each file.
457
CUDA_add_custom_commands( ${cuda_target} ${ARGN} )
460
ADD_LIBRARY(${cuda_target}
465
TARGET_LINK_LIBRARIES(${cuda_target}
469
ENDMACRO(CUDA_ADD_LIBRARY cuda_target)
472
###############################################################################
473
###############################################################################
475
###############################################################################
476
###############################################################################
477
MACRO(CUDA_ADD_EXECUTABLE cuda_target)
479
# Create custom commands and targets for each file.
480
CUDA_add_custom_commands( ${cuda_target} ${ARGN} )
483
ADD_EXECUTABLE(${cuda_target}
488
TARGET_LINK_LIBRARIES(${cuda_target}
493
ENDMACRO(CUDA_ADD_EXECUTABLE cuda_target)
495
###############################################################################
496
###############################################################################
498
###############################################################################
499
###############################################################################
500
MACRO(CUDA_COMPILE file_variable)
502
# Create custom commands and targets for each file.
503
CUDA_add_custom_commands( cuda_compile ${ARGN} )
505
SET(file_variable ${target_srcs} ${cuda_cu_sources})
507
ENDMACRO(CUDA_COMPILE)