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

  ViewVC Help
Powered by ViewVC 1.1.26