/[escript]/trunk/cusplibrary/build/build-env.py
ViewVC logotype

Contents of /trunk/cusplibrary/build/build-env.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5148 - (show annotations)
Mon Sep 15 01:25:23 2014 UTC (6 years, 2 months ago) by caltinay
File MIME type: text/x-python
File size: 11040 byte(s)
Merging ripley diagonal storage + CUDA support into trunk.
Options file version has been incremented due to new options
'cuda' and 'nvccflags'.

1 EnsureSConsVersion(1,2)
2
3 import os
4
5 import inspect
6 import platform
7
8 def get_cuda_paths():
9 """Determines CUDA {bin,lib,include} paths
10
11 returns (bin_path,lib_path,inc_path)
12 """
13
14 # determine defaults
15 if os.name == 'nt':
16 bin_path = 'C:/CUDA/bin'
17 lib_path = 'C:/CUDA/lib'
18 inc_path = 'C:/CUDA/include'
19 elif os.name == 'posix':
20 bin_path = '/usr/bin'
21 lib_path = '/usr/lib'
22 inc_path = '/usr/include'
23 else:
24 raise ValueError, 'Error: unknown OS. Where is nvcc installed?'
25
26 if platform.machine()[-2:] == '64':
27 lib_path += '64'
28
29 # override with environement variables
30 if 'CUDA_BIN_PATH' in os.environ:
31 bin_path = os.path.abspath(os.environ['CUDA_BIN_PATH'])
32 if 'CUDA_LIB_PATH' in os.environ:
33 lib_path = os.path.abspath(os.environ['CUDA_LIB_PATH'])
34 if 'CUDA_INC_PATH' in os.environ:
35 inc_path = os.path.abspath(os.environ['CUDA_INC_PATH'])
36
37 return (bin_path,lib_path,inc_path)
38
39 def get_mkl_paths():
40 """Determines MKL {lib,include} paths
41
42 returns (lib_path,inc_path)
43 """
44
45 arch64 = False
46 if platform.machine()[-2:] == '64':
47 arch64 = True
48
49 if 'MKLROOT' not in os.environ:
50 raise ValueError, "MKLROOT is not an environment variable"
51
52 # determine defaults
53 if os.name == 'nt':
54 raise ValueError, "Intel MKL support for Windows not implemented."
55 elif os.name == 'posix':
56 lib_base = os.environ['MKLROOT'] + '/lib'
57 dirs = os.listdir(lib_base)
58 for dir in dirs :
59 # select 64/32 bit MKL library path based on architecture
60 if arch64 == True and dir.find('64') > -1 :
61 lib_path = lib_base + '/' + dir
62 break
63 elif arch64 == False and dir.find('64') == -1 :
64 lib_path = lib_base + '/' + dir
65 break
66
67 if lib_path == lib_base :
68 raise ValueError, 'Could not find MKL library directory which matches the arctitecture.'
69
70 inc_path = os.environ['MKLROOT'] + '/include'
71 else:
72 raise ValueError, 'Error: unknown OS. Where is nvcc installed?'
73
74 return (lib_path,inc_path)
75
76 def getTools():
77 result = []
78 if os.name == 'nt':
79 result = ['default', 'msvc']
80 elif os.name == 'posix':
81 result = ['default', 'gcc']
82 else:
83 result = ['default']
84 return result;
85
86
87 OldEnvironment = Environment;
88
89
90 # this dictionary maps the name of a compiler program to a dictionary mapping the name of
91 # a compiler switch of interest to the specific switch implementing the feature
92 gCompilerOptions = {
93 'gcc' : {'warn_all' : '-Wall', 'warn_errors' : '-Werror', 'optimization' : '-O2', 'debug' : '-g', 'exception_handling' : '', 'omp' : '-fopenmp'},
94 'g++' : {'warn_all' : '-Wall', 'warn_errors' : '-Werror', 'optimization' : '-O2', 'debug' : '-g', 'exception_handling' : '', 'omp' : '-fopenmp'},
95 'cl' : {'warn_all' : '/Wall', 'warn_errors' : '/WX', 'optimization' : '/Ox', 'debug' : ['/Zi', '-D_DEBUG', '/MTd'], 'exception_handling' : '/EHsc', 'omp' : '/openmp'}
96 }
97
98
99 # this dictionary maps the name of a linker program to a dictionary mapping the name of
100 # a linker switch of interest to the specific switch implementing the feature
101 gLinkerOptions = {
102 'gcc' : {'debug' : ''},
103 'g++' : {'debug' : ''},
104 'link' : {'debug' : '/debug'}
105 }
106
107
108 def getCFLAGS(mode, backend, warn, warnings_as_errors, hostspblas, b40c, CC):
109 result = []
110 if mode == 'release':
111 # turn on optimization
112 result.append(gCompilerOptions[CC]['optimization'])
113 elif mode == 'debug':
114 # turn on debug mode
115 result.append(gCompilerOptions[CC]['debug'])
116 result.append('-DTHRUST_DEBUG')
117 # force 32b code on darwin
118 if platform.platform()[:6] == 'Darwin':
119 result.append('-m32')
120 # build with B40C enabled
121 if b40c == True :
122 result.append('-D__CUSP_USE_B40C__')
123
124 if CC == 'cl':
125 result.append('/bigobj')
126
127 # generate omp code
128 if backend == 'omp':
129 result.append(gCompilerOptions[CC]['omp'])
130
131 if warn:
132 # turn on all warnings
133 result.append(gCompilerOptions[CC]['warn_all'])
134
135 if warnings_as_errors:
136 # treat warnings as errors
137 result.append(gCompilerOptions[CC]['warn_errors'])
138
139 # generate hostspblas code
140 if hostspblas == 'mkl':
141 result.append('-DINTEL_MKL_SPBLAS')
142
143 return result
144
145
146 def getCXXFLAGS(mode, backend, warn, warnings_as_errors, hostspblas, b40c, CXX):
147 result = []
148 if mode == 'release':
149 # turn on optimization
150 result.append(gCompilerOptions[CXX]['optimization'])
151 elif mode == 'debug':
152 # turn on debug mode
153 result.append(gCompilerOptions[CXX]['debug'])
154 # enable exception handling
155 result.append(gCompilerOptions[CXX]['exception_handling'])
156 # force 32b code on darwin
157 if platform.platform()[:6] == 'Darwin':
158 result.append('-m32')
159 # build with B40C enabled
160 if b40c is not None :
161 result.append('-D__CUSP_USE_B40C__')
162
163 # generate omp code
164 if backend == 'omp':
165 result.append(gCompilerOptions[CXX]['omp'])
166
167 if warn:
168 # turn on all warnings
169 result.append(gCompilerOptions[CXX]['warn_all'])
170
171 if warnings_as_errors:
172 # treat warnings as errors
173 result.append(gCompilerOptions[CXX]['warn_errors'])
174
175 # generate hostspblas code
176 if hostspblas == 'mkl':
177 result.append('-DINTEL_MKL_SPBLAS')
178
179 return result
180
181
182 def getNVCCFLAGS(mode, backend, arch):
183 result = ['-arch=' + arch]
184 if mode == 'debug':
185 # turn on debug mode
186 # XXX make this work when we've debugged nvcc -G
187 #result.append('-G')
188 pass
189 return result
190
191
192 def getLINKFLAGS(mode, backend, hostspblas, LINK):
193 result = []
194 if mode == 'debug':
195 # turn on debug mode
196 result.append(gLinkerOptions[LINK]['debug'])
197 # force 32b code on darwin
198 if platform.platform()[:6] == 'Darwin':
199 result.append('-m32')
200
201 # XXX make this portable
202 if backend == 'ocelot':
203 result.append(os.popen('OcelotConfig -l').read().split())
204
205 if hostspblas == 'mkl':
206 result.append('-fopenmp')
207
208 return result
209
210
211 def Environment():
212 # allow the user discretion to choose the MSVC version
213 vars = Variables()
214 if os.name == 'nt':
215 vars.Add(EnumVariable('MSVC_VERSION', 'MS Visual C++ version', None, allowed_values=('8.0', '9.0', '10.0')))
216
217 # add a variable to handle the device backend
218 backend_variable = EnumVariable('backend', 'The parallel device backend to target', 'cuda',
219 allowed_values = ('cuda', 'omp', 'ocelot'))
220 vars.Add(backend_variable)
221
222 # add a variable to handle RELEASE/DEBUG mode
223 vars.Add(EnumVariable('mode', 'Release versus debug mode', 'release',
224 allowed_values = ('release', 'debug')))
225
226 # add a variable to handle compute capability
227 vars.Add(EnumVariable('arch', 'Compute capability code generation', 'sm_30',
228 allowed_values = ('sm_10', 'sm_11', 'sm_12', 'sm_13', 'sm_20', 'sm_21', 'sm_30', 'sm_35')))
229
230 # add a variable to handle warnings
231 if os.name == 'posix':
232 vars.Add(BoolVariable('Wall', 'Enable all compilation warnings', 1))
233 else:
234 vars.Add(BoolVariable('Wall', 'Enable all compilation warnings', 0))
235
236 # add a variable to treat warnings as errors
237 vars.Add(BoolVariable('Werror', 'Treat warnings as errors', 0))
238
239 # add a variable to filter source files by a regex
240 vars.Add('tests', help='Filter test files using a regex')
241
242 # add a variable to handle the device backend
243 hostspblas_variable = EnumVariable('hostspblas', 'Host sparse math library', 'cusp',
244 allowed_values = ('cusp', 'mkl'))
245 vars.Add(hostspblas_variable)
246
247 # add a variable to enable B40C support
248 vars.Add(BoolVariable('b40c', 'Enable support for B40C', 0))
249
250 # create an Environment
251 env = OldEnvironment(tools = getTools(), variables = vars)
252
253 # get the absolute path to the directory containing
254 # this source file
255 thisFile = inspect.getabsfile(Environment)
256 thisDir = os.path.dirname(thisFile)
257
258 # enable nvcc
259 env.Tool('nvcc', toolpath = [os.path.join(thisDir)])
260
261 # get the preprocessor define to use for the backend
262 backend_define = { 'cuda' : 'THRUST_DEVICE_SYSTEM_CUDA', 'omp' : 'THRUST_DEVICE_SYSTEM_OMP', 'ocelot' : 'THRUST_DEVICE_SYSTEM_CUDA' }[env['backend']]
263 env.Append(CFLAGS = ['-DTHRUST_DEVICE_SYSTEM=%s' % backend_define])
264 env.Append(CXXFLAGS = ['-DTHRUST_DEVICE_SYSTEM=%s' % backend_define])
265
266 # get C compiler switches
267 env.Append(CFLAGS = getCFLAGS(env['mode'], env['backend'], env['Wall'], env['Werror'], env['hostspblas'], env['b40c'], env.subst('$CC')))
268
269 # get CXX compiler switches
270 env.Append(CXXFLAGS = getCXXFLAGS(env['mode'], env['backend'], env['Wall'], env['Werror'], env['hostspblas'], env['b40c'], env.subst('$CXX')))
271
272 # get NVCC compiler switches
273 env.Append(NVCCFLAGS = getNVCCFLAGS(env['mode'], env['backend'], env['arch']))
274
275 # get linker switches
276 env.Append(LINKFLAGS = getLINKFLAGS(env['mode'], env['backend'], env['hostspblas'], env.subst('$LINK')))
277
278 # silence unknown pragma warnings
279 env.Append(CFLAGS = ['-Wno-unknown-pragmas','-Wno-unused-local-typedefs'])
280 env.Append(CXXFLAGS = ['-Wno-unknown-pragmas','-Wno-unused-local-typedefs'])
281
282 # get CUDA paths
283 (cuda_exe_path,cuda_lib_path,cuda_inc_path) = get_cuda_paths()
284 env.Append(LIBPATH = [cuda_lib_path])
285 env.Append(CPPPATH = [cuda_inc_path])
286
287 # link against backend-specific runtimes
288 # XXX we shouldn't have to link against cudart unless we're using the
289 # cuda runtime, but cudafe inserts some dependencies when compiling .cu files
290 # XXX ideally this gets handled in nvcc.py if possible
291 env.Append(LIBS = ['cudart','stdc++','m'])
292
293 if env['backend'] == 'ocelot':
294 if os.name == 'posix':
295 env.Append(LIBPATH = ['/usr/local/lib'])
296 else:
297 raise ValueError, "Unknown OS. What is the Ocelot library path?"
298 elif env['backend'] == 'omp':
299 if os.name == 'posix':
300 env.Append(LIBS = ['gomp'])
301 elif os.name == 'nt':
302 env.Append(LIBS = ['VCOMP'])
303 else:
304 raise ValueError, "Unknown OS. What is the name of the OpenMP library?"
305
306 if env['hostspblas'] == 'mkl':
307 intel_lib = 'mkl_intel'
308 if platform.machine()[-2:] == '64':
309 intel_lib += '_lp64'
310
311 (mkl_lib_path,mkl_inc_path) = get_mkl_paths()
312 env.Append(CPPPATH = [mkl_inc_path])
313 env.Append(LIBPATH = [mkl_lib_path])
314 env.Append(LIBS = ['mkl_core', 'mkl_gnu_thread', intel_lib])
315
316 # set thrust include path
317 # this needs to come before the CUDA include path appended above,
318 # which may include a different version of thrust
319 env.Prepend(CPPPATH = os.path.dirname(thisDir))
320
321
322 if 'THRUST_PATH' in os.environ:
323 env.Prepend(CPPPATH = [os.path.abspath(os.environ['THRUST_PATH'])])
324
325 # import the LD_LIBRARY_PATH so we can run commands which depend
326 # on shared libraries
327 # XXX we should probably just copy the entire environment
328 if os.name == 'posix':
329 if ('DYLD_LIBRARY_PATH' in os.environ) and (env['PLATFORM'] == "darwin") :
330 env['ENV']['DYLD_LIBRARY_PATH'] = os.environ['DYLD_LIBRARY_PATH']
331 elif 'LD_LIBRARY_PATH' in os.environ:
332 env['ENV']['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
333
334 # generate help text
335 Help(vars.GenerateHelpText(env))
336
337 return env
338

  ViewVC Help
Powered by ViewVC 1.1.26