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

  ViewVC Help
Powered by ViewVC 1.1.26