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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6651 - (hide annotations)
Wed Feb 7 02:12:08 2018 UTC (2 years, 4 months ago) by jfenwick
File MIME type: text/x-python
File size: 11722 byte(s)
Make everyone sad by touching all the files

Copyright dates update

1 sshaw 5707
2     ##############################################################################
3     #
4 jfenwick 6651 # Copyright (c) 2003-2018 by The University of Queensland
5 sshaw 5707 # http://www.uq.edu.au
6     #
7     # Primary Business: Queensland, Australia
8 jfenwick 6112 # Licensed under the Apache License, version 2.0
9     # http://www.apache.org/licenses/LICENSE-2.0
10 sshaw 5707 #
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 sshaw 5706 from __future__ import print_function, division
17    
18 caltinay 4955 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 caltinay 5130 bin_path = '/usr/bin'
38     lib_path = '/usr/lib'
39     inc_path = '/usr/include'
40 caltinay 4955 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 sshaw 5705 # 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 caltinay 4955
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 caltinay 5130 vars.Add(EnumVariable('arch', 'Compute capability code generation', 'sm_30',
245 caltinay 4955 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 caltinay 5130 env.Append(CFLAGS = ['-Wno-unknown-pragmas','-Wno-unused-local-typedefs'])
297     env.Append(CXXFLAGS = ['-Wno-unknown-pragmas','-Wno-unused-local-typedefs'])
298 caltinay 4955
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 sshaw 5705 intel_lib += '_lp64'
327 caltinay 4955
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 sshaw 5705 env['ENV']['DYLD_LIBRARY_PATH'] = os.environ['DYLD_LIBRARY_PATH']
348 caltinay 4955 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