【IT168 文档】一、简介
在Windows平台下,用cmake来搭建环境环境,在VS2005下运行CUDA程序。其实,在Windows下,在CUDA2.3的SDK里,有一个Cuda.Rules的文件。通过这个文件,在VS2005里可以很方便的设置各个编译参数。不过通过cmake文件可以不用重复设置编译参数。
二、机子环境
1 计算机 : ThinkPad R61i
2 显卡 : NVIDIA Quadro NVS 140M
3 CUDA版本 : CUDA2.3
三、所需文件
1 cmake文件 : CMakeLists.txt - 主要的cmake配置文件 FindCuda.cmake - 设置CUDA编译环境 FindCudaLibrary.cmake - 寻找 CUDA 和 CUDA SDK 库
2 源代码 : template.cu template_kernel.cu template_gold.cpp -CUDA SDK 里一个很经典的小程序
注意:各个文件之间的路径
-bin
-cmke
- FindCuda.cmake
- FindCudaLibrary.cmake
-test_cuda
- CMakeLists.txt
- template.cu
- template_kernel.cu
- template_gold.cpp
四 步骤
1 CUDA安装好后,确定一下有没有 CUDA_BIN_PATH 和 NVSDKCUDA_ROOT 这两个环境变量
2 CMakeList.txt 文件
PROJECT( test_cuda )
OPTION( BUILD_test
"Build the test of cmake of cuda."
ON )
IF( BUILD_test )
#注意一下FindCuda.cmake所放的路径
INCLUDE( ../cmake/FindCuda.cmake )
CUDA_ADD_EXECUTABLE( test
template.cu
template_gold.cpp template_kernel.cu
)
ENDIF( BUILD_test )
3 FindCuda.cmake 文件
# CUDA_INCLUDE_DIRECTORIES( path0 path1 ... )
# -- Sets the directories that should be passed to nvcc
# (e.g. nvcc -Ipath0 -Ipath1 ... ). These paths usually contain other .cu
# files.
#
# CUDA_ADD_LIBRARY( cuda_target file0 file1 ... )
# -- Creates a shared library "cuda_target" which contains all of the source
# (*.c, *.cc, etc.) specified and all of the nvcc'ed .cu files specified.
# All of the specified source files and generated .c files are compiled
# using the standard CMake compiler, so the normal INCLUDE_DIRECTORIES,
# LINK_DIRECTORIES, and TARGET_LINK_LIBRARIES can be used to affect their
# build and link.
#
# CUDA_ADD_EXECUTABLE( cuda_target file0 file1 ... )
# -- Same as CUDA_ADD_LIBRARY except that an exectuable is created.
# FindCuda.cmake
# 设置 device 和 emulation 属性
IF( NOT CUDA_BUILD_TYPE )
SET( CUDA_BUILD_TYPE "Device" CACHE STRING "Cuda build type: Emulation or Device" )
ENDIF( NOT CUDA_BUILD_TYPE )
IF( CUDA_BUILD_TYPE MATCHES "Device" )
SET( CUDA_NVCC_FLAGS "")
ELSE( CUDA_BUILD_TYPE MATCHES "Device" )
SET( CUDA_NVCC_FLAGS --device-emulation -D_DEVICEEMU -g )
ENDIF( CUDA_BUILD_TYPE MATCHES "Device")
# 设置DEBUG 和 RELEASE 属性
IF( NOT CUDA_DEBUG_TYPE )
SET( CUDA_DEBUG_TYPE "Debug" CACHE STRING "Debug or Release" )
ENDIF( NOT CUDA_DEBUG_TYPE )
IF( CUDA_DEBUG_TYPE MATCHES "Debug" )
SET( CUDA_DEBUG -D_DEBUG )
SET( CUDA_DEBUG_FLAGS /0d,/MTd )
ELSE( CUDA_DEBUG_TYPE MATCHES "Debug" )
SET( CUDA_DEBUG "" )
SET( CUDA_DEBUG_FLAGS /2d,/MT )
ENDIF( CUDA_DEBUG_TYPE MATCHES "Debug" )
# 寻找CUDA安装路径
IF( NOT CUDA_INSTALL_PREFIX )
# 寻找 nvcc.exe
FIND_PROGRAM( CUDA_NVCC
nvcc
PATHS $ENV{CUDA_BIN_PATH}
)
IF( NOT CUDA_NVCC )
MESSAGE( STATUS "Could not find nvcc" )
ENDIF( NOT CUDA_NVCC )
# 找 CUDA 库所在的路径
FIND_PATH( CUDA_INSTALL_PREFIX
bin/nvcc.exe
PATHS $ENV{CUDA_BIN_PATH}/../
)
IF( NOT EXISTS ${CUDA_INSTALL_PREFIX} )
MESSAGE( STATUS "Specify CUDA_INSTALL_PREFIX" )
ENDIF( NOT EXISTS ${CUDA_INSTALL_PREFIX} )
ENDIF( NOT CUDA_INSTALL_PREFIX )
# 寻找 cuda 和 cutil 库的头文件和库文件
INCLUDE( ../cmake/FindCudaLibrary.cmake )
##################################################
# 自定义规则命令
##################################################
MACRO( CUDA_ADD_CUSTOM_COMMANDS )
# 非 *.cu 文件
SET( target_srcs "" )
# *.cu 文件
SET( cuda_cu_sources "" )
FOREACH( file ${ARGN} )
IF( ${file} MATCHES ".*\\.cu$" )
GET_FILENAME_COMPONENT( file_we ${file} NAME_WE )
# 设置输出文件
SET( generated_object "${file_we}.obj" )
# 设置文件
SET( source_file ${file} )
# 设置文件属性
SET_SOURCE_FILES_PROPERTIES( ${source_file} PROPERTIES CPLUSPLUS ON )
# 自定义命令 - CUDA编译命令
ADD_CUSTOM_COMMAND(
OUTPUT ../bin/$(ConfigurationName)/${generated_object}
MAIN_DEPENDENCY ${source_file}
COMMAND ${CUDA_NVCC}
ARGS -c
${CUDA_DEBUG}
${CUDA_NVCC_FLAGS}
-Xcompiler
/EHsc,/W3,/nologo,/Wp64,/Zi,/RTC1,${CUDA_DEBUG_FLAGS}
${CUDA_NVCC_INCLUDE_ARGS}
${CUDA_INCLUDE_COMMAND_DIR}
-o ../bin/$(ConfigurationName)/${generated_object}
#${source_file}
$(InputPath) # 注意:这些变量是针对于 VS2005的
COMMENT "Building NVCC ${file}: ${generated_object}\n"
)
SET( cuda_cu_sources ${cuda_cu_sources} ${source_file} )
ELSE( ${file} MATCHES ".*\\.cu$" )
SET( target_srcs ${target_srcs} ${file} )
ENDIF( ${file} MATCHES ".*\\.cu$" )
ENDFOREACH( file ${ARGN} )
ENDMACRO( CUDA_ADD_CUSTOM_COMMANDS )
##################################################
# 加头文件路径宏
##################################################
MACRO( CUDA_INCLUDE_DIRECTORIES )
FOREACH( dir ${ARGN} )
SET( CUDA_NVCC_INCLUDE_ARGS ${CUDA_NVCC_INCLUDE_ARGS} -I${dir} )
ENDFOREACH( dir ${ARGN} )
ENDMACRO( CUDA_INCLUDE_DIRECTORIES )
##################################################
# 建立生成静态库工程
##################################################
MACRO( CUDA_ADD_LIBRARY cuda_target )
# 生成命令规则
CUDA_ADD_CUSTOM_COMMANDS( ${ARGN} )
# 加入头文件路径
INCLUDE_DIRECTORIES( ${CUDA_INCLUDE_DIR} )
# 库工程
ADD_LIBRARY( ${cuda_target}
${target_srcs}
${cuda_cu_sources}
)
# 加入工程所需的库名
TARGET_LINK_LIBRARIES( ${cuda_target}
${CUDA_LIBRARIES}
)
ENDMACRO( CUDA_ADD_LIBRARY cuda_target )
##################################################
# 建立生成可执行文件的工程
##################################################
MACRO( CUDA_ADD_EXECUTABLE cuda_target )
# 生成命令规则
CUDA_ADD_CUSTOM_COMMANDS( ${ARGN} )
# 加入头文件路径
INCLUDE_DIRECTORIES( ${CUDA_INCLUDE_DIR} )
# 加入库路径
LINK_DIRECTORIES( ${CUDA_LIBRARY_DIR} )
#可执行工程
ADD_EXECUTABLE( ${cuda_target}
${target_srcs}
${cuda_cu_sources}
)
# 加入的库名
TARGET_LINK_LIBRARIES( ${cuda_target}
${CUDA_LIBRARIES}
)
ENDMACRO( CUDA_ADD_EXECUTABLE cuda_target )
4 FindCudaLibrary.cmake
# Once done this will define
# neek known the var ENV CUDA_BIN_PATH and ENV NVSDKCUDA_ROOT
#
# CUDA_FOUND - system has CUDA
# CUDA_INCLUDE_DIR - the include directory
# CUDA_LIBRARY_DIR - the directory containing the libraries
# CUDA_LIBRARIES - Link these to use CUDA
#
IF( WIN32 )
# 寻找CUDA库路径
FIND_PATH( CUDA_LIBRARY_DIR
NAMES cublas.lib cudart.lib cufft.lib
PATHS $ENV{CUDA_BIN_PATH}/../lib
)
# 寻找CUDA头文件路径
FIND_PATH( CUDA_INCLUDE_DIR
NAMES cuda.h cublas.h cufft.h
PATHS $ENV{CUDA_BIN_PATH}/../include
)
# 寻找CUDA SDK库路径
FIND_PATH( CUDA_SDK_LIBRARY_DIR
NAMES cutil.lib glut32.lib
PATHS $ENV{NVSDKCUDA_ROOT}/common/lib
)
# 寻找CUDA SDK头文件路径
FIND_PATH( CUDA_SDK_INCLUDE_DIR
NAMES cutil.h cutil_gl_error.h
PATHS $ENV{NVSDKCUDA_ROOT}/common/inc
)
ELSE( WIN32 )
ENDIF( WIN32 )
SET( CUDA_FOUND FALSE )
IF ( CUDA_INCLUDE_DIR AND CUDA_LIBRARY_DIR )
SET ( CUDA_FOUND TRUE )
SET ( CUDA_INCLUDE_COMMAND_DIR
-I${CUDA_INCLUDE_DIR}
-I${CUDA_SDK_INCLUDE_DIR}
)
SET ( CUDA_INCLUDE_DIR
${CUDA_INCLUDE_DIR}
${CUDA_SDK_INCLUDE_DIR}
)
SET( CUDA_LIBRARY_DIR
${CUDA_LIBRARY_DIR}
${CUDA_SDK_LIBRARY_DIR}
)
SET ( CUDA_LIBRARIES cutil32D.lib cudart.lib cufft.lib cublas.lib cuda.lib )
ENDIF ( CUDA_INCLUDE_DIR AND CUDA_LIBRARY_DIR )
5 把所需要的dll文件放在生成exe文件的目录下。
6 由于编译cpp文件时,用到的是 /MDd 选项,而cu文件用到的是 /MTd 选项。这两个选项不统一会出现链接错误。改掉一个设置,统一起来就行了。
7 template_kernel.cu 文件不用编译,所以要改一个这文件的编译选项。让这个文件变成 “从生成中排掉”
五 总结
虽然用写cmake很复杂,但对以后就比较简单了。不过如果只在windows底下写程序的话,还是用别人的工具比较好用。如果跨平台的话,还是写个cmake文件吧。这次写的cmake文件还是有很多限制的。在好多规定的条件下才能执行成功。而且也没有在linux底下的代码。如果下次有机会的话,会补上的。