About

The following tool, cuda (cuda.py) is for using the CUDA toolkit/sdk by NVidia. See the end of the page for an example SConscript for building the simpleGL sample that comes with the SDK and some notes.

The tool code

Note: save this as cuda.py

   1 """
   2 SCons.Tool.cuda
   3 
   4 CUDA Tool for SCons
   5 
   6 """
   7 
   8 import os
   9 import sys
  10 import SCons.Tool
  11 import SCons.Scanner.C
  12 import SCons.Defaults
  13 
  14 CUDAScanner = SCons.Scanner.C.CScanner()
  15 
  16 # this object emitters add '.linkinfo' suffixed files as extra targets
  17 # these files are generated by nvcc. The reason to do this is to remove
  18 # the extra .linkinfo files when calling scons -c
  19 def CUDANVCCStaticObjectEmitter(target, source, env):
  20         tgt, src = SCons.Defaults.StaticObjectEmitter(target, source, env)
  21         for file in src:
  22                 lifile = os.path.splitext(src[0].rstr())[0] + '.linkinfo'
  23                 tgt.append(lifile)
  24         return tgt, src
  25 def CUDANVCCSharedObjectEmitter(target, source, env):
  26         tgt, src = SCons.Defaults.SharedObjectEmitter(target, source, env)
  27         for file in src:
  28                 lifile = os.path.splitext(src[0].rstr())[0] + '.linkinfo'
  29                 tgt.append(lifile)
  30         return tgt, src
  31 
  32 def generate(env):
  33         staticObjBuilder, sharedObjBuilder = SCons.Tool.createObjBuilders(env);
  34         staticObjBuilder.add_action('.cu', '$STATICNVCCCMD')
  35         staticObjBuilder.add_emitter('.cu', CUDANVCCStaticObjectEmitter)
  36         sharedObjBuilder.add_action('.cu', '$SHAREDNVCCCMD')
  37         sharedObjBuilder.add_emitter('.cu', CUDANVCCSharedObjectEmitter)
  38         SCons.Tool.SourceFileScanner.add_scanner('.cu', CUDAScanner)
  39         
  40         # default compiler
  41         env['NVCC'] = 'nvcc'
  42         
  43         # default flags for the NVCC compiler
  44         env['NVCCFLAGS'] = ''
  45         env['STATICNVCCFLAGS'] = ''
  46         env['SHAREDNVCCFLAGS'] = ''
  47         env['ENABLESHAREDNVCCFLAG'] = '-shared'
  48         
  49         # default NVCC commands
  50         env['STATICNVCCCMD'] = '$NVCC -o $TARGET -c $NVCCFLAGS $STATICNVCCFLAGS $SOURCES'
  51         env['SHAREDNVCCCMD'] = '$NVCC -o $TARGET -c $NVCCFLAGS $SHAREDNVCCFLAGS $ENABLESHAREDNVCCFLAG $SOURCES'
  52 
  53         # helpers
  54         home=os.environ.get('HOME', '')
  55         programfiles=os.environ.get('PROGRAMFILES', '')
  56         homedrive=os.environ.get('HOMEDRIVE', '')
  57         
  58         # find CUDA Toolkit path and set CUDA_TOOLKIT_PATH
  59         try:
  60                 cudaToolkitPath = env['CUDA_TOOLKIT_PATH']
  61         except:
  62                 paths=[home + '/NVIDIA_CUDA_TOOLKIT',
  63                        home + '/Apps/NVIDIA_CUDA_TOOLKIT',
  64                            home + '/Apps/NVIDIA_CUDA_TOOLKIT',
  65                            home + '/Apps/CudaToolkit',
  66                            home + '/Apps/CudaTK',
  67                            '/usr/local/NVIDIA_CUDA_TOOLKIT',
  68                            '/usr/local/CUDA_TOOLKIT',
  69                            '/usr/local/cuda_toolkit',
  70                            '/usr/local/CUDA',
  71                            '/usr/local/cuda',
  72                            '/Developer/NVIDIA CUDA TOOLKIT',
  73                            '/Developer/CUDA TOOLKIT',
  74                            '/Developer/CUDA',
  75                            programfiles + 'NVIDIA Corporation/NVIDIA CUDA TOOLKIT',
  76                            programfiles + 'NVIDIA Corporation/NVIDIA CUDA',
  77                            programfiles + 'NVIDIA Corporation/CUDA TOOLKIT',
  78                            programfiles + 'NVIDIA Corporation/CUDA',
  79                            programfiles + 'NVIDIA/NVIDIA CUDA TOOLKIT',
  80                            programfiles + 'NVIDIA/NVIDIA CUDA',
  81                            programfiles + 'NVIDIA/CUDA TOOLKIT',
  82                            programfiles + 'NVIDIA/CUDA',
  83                            programfiles + 'CUDA TOOLKIT',
  84                            programfiles + 'CUDA',
  85                            homedrive + '/CUDA TOOLKIT',
  86                            homedrive + '/CUDA']
  87                 pathFound = False
  88                 for path in paths:
  89                         if os.path.isdir(path):
  90                                 pathFound = True
  91                                 print 'scons: CUDA Toolkit found in ' + path
  92                                 cudaToolkitPath = path
  93                                 break
  94                 if not pathFound:
  95                         sys.exit("Cannot find the CUDA Toolkit path. Please modify your SConscript or add the path in cudaenv.py")
  96         env['CUDA_TOOLKIT_PATH'] = cudaToolkitPath
  97 
  98         # find CUDA SDK path and set CUDA_SDK_PATH
  99         try:
 100                 cudaSDKPath = env['CUDA_SDK_PATH']
 101         except:
 102                 paths=[home + '/NVIDIA_CUDA_SDK', # i am just guessing here
 103                        home + '/Apps/NVIDIA_CUDA_SDK',
 104                            home + '/Apps/CudaSDK',
 105                            '/usr/local/NVIDIA_CUDA_SDK',
 106                            '/usr/local/CUDASDK',
 107                            '/usr/local/cuda_sdk',
 108                            '/Developer/NVIDIA CUDA SDK',
 109                            '/Developer/CUDA SDK',
 110                            '/Developer/CUDA',
 111                            '/Developer/GPU Computing/C',
 112                            programfiles + 'NVIDIA Corporation/NVIDIA CUDA SDK',
 113                            programfiles + 'NVIDIA/NVIDIA CUDA SDK',
 114                            programfiles + 'NVIDIA CUDA SDK',
 115                            programfiles + 'CudaSDK',
 116                            homedrive + '/NVIDIA CUDA SDK',
 117                            homedrive + '/CUDA SDK',
 118                            homedrive + '/CUDA/SDK']
 119                 pathFound = False
 120                 for path in paths:
 121                         if os.path.isdir(path):
 122                                 pathFound = True
 123                                 print 'scons: CUDA SDK found in ' + path
 124                                 cudaSDKPath = path
 125                                 break
 126                 if not pathFound:
 127                         sys.exit("Cannot find the CUDA SDK path. Please set env['CUDA_SDK_PATH'] to point to your SDK path")
 128         env['CUDA_SDK_PATH'] = cudaSDKPath
 129         
 130         # cuda libraries
 131         if env['PLATFORM'] == 'posix':
 132                 cudaSDKSubLibDir = '/linux'
 133         elif env['PLATFORM'] == 'darwin':
 134                 cudaSDKSubLibDir = '/darwin'
 135         else:
 136                 cudaSDKSubLibDir = ''
 137 
 138         # add nvcc to PATH
 139         env.PrependENVPath('PATH', cudaToolkitPath + '/bin')
 140         
 141         # add required libraries
 142         env.Append(CPPPATH=[cudaSDKPath + '/common/inc', cudaToolkitPath + '/include'])
 143         env.Append(LIBPATH=[cudaSDKPath + '/lib', cudaSDKPath + '/common/lib' + cudaSDKSubLibDir, cudaToolkitPath + '/lib'])
 144         env.Append(LIBS=['cudart'])
 145 
 146 def exists(env):
 147         return env.Detect('nvcc')

Sample

The SConscript for building simpleGL:

   1 env = Environment()
   2 env.Tool('cuda')
   3 env.Append(LIBS=['cutil', 'glut', 'GLEW'])
   4 
   5 env.Program('simpleGL', ['simpleGL.cpp', 'simpleGL_kernel.cu'])

Notes

The above tool has only been tested on Linux and Mac OS X. If your project doesn't use any of the above paths, you can specify

env['CUDA_TOOLKIT_PATH'] = path to the CUDA Toolkit
env['CUDA_SDK_PATH'] = path to the CUDA SDK

If the tool finds the paths, it sets the above to the path it found. If you want to include CFLAGS for the nvcc, set the

env['NVCCFLAGS'] = flags common to static and shared objects
env['STATICNVCCFLAGS'] = flags for static objects
env['SHAREDNVCCFLAGS'] = flags for shared objects

variables. The tool will include automatically the 'cudart' library in LIBS but not cublas nor cufft because you might not need them. Call env.Append as shown in the sample above to add extra libraries after calling env.Tool('cuda').

Emitters

This is an implementation detail, but i'm posting this too here. I'm not sure if this was the best thing to do, but it seems to work. I added two emitters for .cu files which modify the results of the Scons.Defaults.Static/SharedObjectEmitter to also add .linkinfo suffixed files as a target because the nvcc compiler builds a .o/.obj and a .linkinfo from a .cu file and i needed to somehow tell to SCons to delete the .linkinfo files when scons -c is issued. If you think of a better method for this, please inform me.

CudaTool (last edited 2011-12-12 04:34:30 by AndrewHelwer)