/[escript]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7027 - (hide annotations)
Fri Aug 7 05:26:26 2020 UTC (3 months, 2 weeks ago) by uqaeller
File size: 34493 byte(s)
Merged in most of Mark's work
1 jfenwick 3982 ##############################################################################
2 jgs 214 #
3 jfenwick 6651 # Copyright (c) 2003-2018 by The University of Queensland
4 jfenwick 3982 # http://www.uq.edu.au
5 ksteube 1811 #
6     # Primary Business: Queensland, Australia
7 jfenwick 6112 # Licensed under the Apache License, version 2.0
8     # http://www.apache.org/licenses/LICENSE-2.0
9 ksteube 1811 #
10 jfenwick 3982 # Development until 2012 by Earth Systems Science Computational Center (ESSCC)
11 jfenwick 4657 # Development 2012-2013 by School of Earth Sciences
12     # Development from 2014 by Centre for Geoscience Computing (GeoComp)
13 jfenwick 3982 #
14     ##############################################################################
15 jgs 455
16 jfenwick 3259 EnsureSConsVersion(0,98,1)
17     EnsurePythonVersion(2,5)
18 ksteube 1811
19 caltinay 4295 import atexit, sys, os, platform, re
20 jfenwick 3259 from distutils import sysconfig
21 caltinay 4295 from dependencies import *
22 jfenwick 3259 from site_init import *
23 jgs 214
24 gross 6702 print(sys.version)
25    
26 jfenwick 3259 # Version number to check for in options file. Increment when new features are
27     # added or existing options changed.
28 caltinay 6241 REQUIRED_OPTS_VERSION=203
29 ksteube 1705
30     # MS Windows support, many thanks to PH
31 jfenwick 3259 IS_WINDOWS = (os.name == 'nt')
32 gross 806
33 uqaeller 7011 if IS_WINDOWS:
34     IS_OSX = False
35     else:
36     IS_OSX = (os.uname()[0] == 'Darwin')
37 jfenwick 4640
38 jfenwick 3259 ########################## Determine options file ############################
39     # 1. command line
40     # 2. scons/<hostname>_options.py
41     # 3. name as part of a cluster
42 jfenwick 2391 options_file=ARGUMENTS.get('options_file', None)
43     if not options_file:
44 jfenwick 3259 ext_dir = os.path.join(os.getcwd(), 'scons')
45     hostname = platform.node().split('.')[0]
46     for name in hostname, effectiveName(hostname):
47     mangledhostname = re.sub('[^0-9a-zA-Z]', '_', hostname)
48     options_file = os.path.join(ext_dir, mangledhostname+'_options.py')
49     if os.path.isfile(options_file): break
50 jfenwick 2391
51 ksteube 1866 if not os.path.isfile(options_file):
52 jfenwick 3259 print("\nWARNING:\nOptions file %s" % options_file)
53     print("not found! Default options will be used which is most likely suboptimal.")
54 jfenwick 5601 print("We recommend that you copy the most relavent options file in the scons/template/")
55 jfenwick 3259 print("subdirectory and customize it to your needs.\n")
56     options_file = None
57 ksteube 1217
58 jfenwick 3259 ############################### Build options ################################
59 gross 1149
60 jfenwick 3259 default_prefix='/usr'
61 jfenwick 3618 mpi_flavours=('no', 'none', 'MPT', 'MPICH', 'MPICH2', 'OPENMPI', 'INTELMPI')
62 jfenwick 6509 netcdf_flavours = ('no', 'off', 'none', 'False', # Must be last of the false alternatives
63     'yes', 'on', 'True', '3', # Must be last of the version 3 alternatives
64     '4')
65 caltinay 6119 all_domains = ['dudley','finley','ripley','speckley']
66 jfenwick 2430
67 jfenwick 5589 #Note that scons construction vars the the following purposes:
68     # CPPFLAGS -> to the preprocessor
69     # CCFLAGS -> flags for _both_ C and C++
70     # CXXFLAGS -> flags for c++ _only_
71     # CFLAGS -> flags for c only
72    
73 jfenwick 3259 vars = Variables(options_file, ARGUMENTS)
74     vars.AddVariables(
75     PathVariable('options_file', 'Path to options file', options_file, PathVariable.PathIsFile),
76     PathVariable('prefix', 'Installation prefix', Dir('#.').abspath, PathVariable.PathIsDirCreate),
77 caltinay 3349 PathVariable('build_dir', 'Top-level build directory', Dir('#/build').abspath, PathVariable.PathIsDirCreate),
78 jfenwick 3259 BoolVariable('verbose', 'Output full compile/link lines', False),
79     # Compiler/Linker options
80     ('cxx', 'Path to C++ compiler', 'default'),
81 jfenwick 5589 ('cc_flags', 'Base (C and C++) compiler flags', 'default'),
82     ('cc_optim', 'Additional (C and C++) flags for a non-debug build', 'default'),
83     ('cc_debug', 'Additional (C and C++) flags for a debug build', 'default'),
84 caltinay 2967 ('cxx_extra', 'Extra C++ compiler flags', ''),
85 ksteube 1771 ('ld_extra', 'Extra linker flags', ''),
86 jfenwick 3259 BoolVariable('werror','Treat compiler warnings as errors', True),
87     BoolVariable('debug', 'Compile with debug flags', False),
88     BoolVariable('openmp', 'Compile parallel version using OpenMP', False),
89     ('omp_flags', 'OpenMP compiler flags', 'default'),
90     ('omp_ldflags', 'OpenMP linker flags', 'default'),
91     # Mandatory libraries
92     ('boost_prefix', 'Prefix/Paths of boost installation', default_prefix),
93 jfenwick 3338 ('boost_libs', 'Boost libraries to link with', ['boost_python-mt']),
94 caltinay 3597 # Mandatory for tests
95     ('cppunit_prefix', 'Prefix/Paths of CppUnit installation', default_prefix),
96     ('cppunit_libs', 'CppUnit libraries to link with', ['cppunit']),
97 jfenwick 3259 # Optional libraries and options
98     EnumVariable('mpi', 'Compile parallel version using MPI flavour', 'none', allowed_values=mpi_flavours),
99     ('mpi_prefix', 'Prefix/Paths of MPI installation', default_prefix),
100     ('mpi_libs', 'MPI shared libraries to link with', ['mpi']),
101 aellery 6824 BoolVariable('use_gmsh', 'Enable gmsh, if available', True),
102 jfenwick 6509 EnumVariable('netcdf', 'Enable netCDF file support', False, allowed_values=netcdf_flavours),
103 jfenwick 3259 ('netcdf_prefix', 'Prefix/Paths of netCDF installation', default_prefix),
104 jfenwick 6509 ('netcdf_libs', 'netCDF libraries to link with', 'DEFAULT'),
105 jfenwick 3259 BoolVariable('parmetis', 'Enable ParMETIS (requires MPI)', False),
106     ('parmetis_prefix', 'Prefix/Paths of ParMETIS installation', default_prefix),
107     ('parmetis_libs', 'ParMETIS libraries to link with', ['parmetis', 'metis']),
108     BoolVariable('mkl', 'Enable the Math Kernel Library', False),
109     ('mkl_prefix', 'Prefix/Paths to MKL installation', default_prefix),
110     ('mkl_libs', 'MKL libraries to link with', ['mkl_solver','mkl_em64t','guide','pthread']),
111     BoolVariable('umfpack', 'Enable UMFPACK', False),
112     ('umfpack_prefix', 'Prefix/Paths to UMFPACK installation', default_prefix),
113     ('umfpack_libs', 'UMFPACK libraries to link with', ['umfpack']),
114 uqaeller 7011 BoolVariable('mumps', 'Enable MUMPS', False),
115     ('mumps_prefix', 'Prefix/Paths to MUMPS installation', default_prefix),
116     ('mumps_libs', 'MUMPS libraries to link with', ['mumps_common','pord','dmumps','zmumps',
117     'mpiseq','lapack','metis','scotch','esmumps','gfortran']),
118 caltinay 6247 TristateVariable('lapack', 'Enable LAPACK', 'auto'),
119 jfenwick 3259 ('lapack_prefix', 'Prefix/Paths to LAPACK installation', default_prefix),
120     ('lapack_libs', 'LAPACK libraries to link with', []),
121     BoolVariable('silo', 'Enable the Silo file format in weipa', False),
122     ('silo_prefix', 'Prefix/Paths to Silo installation', default_prefix),
123 caltinay 2184 ('silo_libs', 'Silo libraries to link with', ['siloh5', 'hdf5']),
124 caltinay 6119 BoolVariable('trilinos', 'Enable the Trilinos solvers', False),
125     ('trilinos_prefix', 'Prefix/Paths to Trilinos installation', default_prefix),
126     ('trilinos_libs', 'Trilinos libraries to link with', []),
127 jfenwick 3259 BoolVariable('visit', 'Enable the VisIt simulation interface', False),
128     ('visit_prefix', 'Prefix/Paths to VisIt installation', default_prefix),
129     ('visit_libs', 'VisIt libraries to link with', ['simV2']),
130 caltinay 6119 ListVariable('domains', 'Which domains to build', 'all', all_domains),
131     BoolVariable('paso', 'Build Paso solver library', True),
132     BoolVariable('weipa', 'Build Weipa data export library', True),
133 jfenwick 6682 ('mathjax_path', 'Path to MathJax.js file', 'default'),
134 jfenwick 3259 # Advanced settings
135 caltinay 5266 ('launcher', 'Launcher command (e.g. mpirun)', 'default'),
136     ('prelaunch', 'Command to execute before launcher (e.g. mpdboot)', 'default'),
137     ('postlaunch', 'Command to execute after launcher (e.g. mpdexit)', 'default'),
138 jfenwick 3259 #dudley_assemble_flags = -funroll-loops to actually do something
139     ('dudley_assemble_flags', 'compiler flags for some dudley optimisations', ''),
140     # To enable passing function pointers through python
141     BoolVariable('iknowwhatimdoing', 'Allow non-standard C', False),
142 caltinay 5266 # An option for specifying the compiler tools
143 jfenwick 3259 ('tools_names', 'Compiler tools to use', ['default']),
144     ('env_export', 'Environment variables to be passed to tools',[]),
145 caltinay 6297 TristateVariable('forcelazy', 'For testing use only - set the default value for autolazy', 'auto'),
146     TristateVariable('forcecollres', 'For testing use only - set the default value for force resolving collective ops', 'auto'),
147 caltinay 6241 BoolVariable('build_shared', '(deprecated option, ignored)', True),
148 jfenwick 3259 ('sys_libs', 'Extra libraries to link with', []),
149     ('escript_opts_version', 'Version of options file (do not specify on command line)'),
150 jfenwick 3618 ('SVN_VERSION', 'Do not use from options file', -2),
151 caltinay 6241 ('pythoncmd', 'which python to compile with', sys.executable),
152 jfenwick 3892 ('pythonlibname', 'Name of the python library to link. (This is found automatically for python2.X.)', ''),
153 jfenwick 3942 ('pythonlibpath', 'Path to the python library. (You should not need to set this unless your python has moved)',''),
154     ('pythonincpath','Path to python include files. (You should not need to set this unless your python has moved',''),
155 caltinay 5250 BoolVariable('longindices', 'use long indices (for very large matrices)', False),
156 sshaw 4738 BoolVariable('compressed_files','Enables reading from compressed binary files', True),
157 caltinay 5250 ('compression_libs', 'Compression libraries to link with', ['boost_iostreams']),
158 uqaeller 6944 BoolVariable('disable_boost_numpy', 'Do not build using boost_numpy, even if it is available', False),
159 jfenwick 6493 BoolVariable('osx_dependency_fix', 'Fix dependencies for libraries to have absolute paths (OSX)', False),
160 jfenwick 6573 BoolVariable('stdlocationisprefix', 'Set the prefix as escript root in the launcher', False),
161 aellery 6722 BoolVariable('mpi_no_host', 'Do not specify --host in run-escript launcher (only OPENMPI)', False),
162     BoolVariable('insane', 'Instructs scons to not run a sanity check after compilation.', False)
163 robwdcock 682 )
164 phornby 1232
165 jfenwick 3259 ##################### Create environment and help text #######################
166 jfenwick 3078
167 jfenwick 3259 # Intel's compiler uses regular expressions improperly and emits a warning
168     # about failing to find the compilers. This warning can be safely ignored.
169 jfenwick 3078
170 caltinay 3319 # PATH is needed so the compiler, linker and tools are found if they are not
171     # in default locations.
172     env = Environment(tools = ['default'], options = vars,
173     ENV = {'PATH': os.environ['PATH']})
174 jfenwick 3967
175 caltinay 4295 # set the vars for clang
176 jfenwick 3967 def mkclang(env):
177 caltinay 4295 env['CXX']='clang++'
178    
179 jfenwick 6510 if env['tools_names'] != ['default']:
180     zz=env['tools_names']
181     if 'clang' in zz:
182     zz.remove('clang')
183     zz.insert(0, mkclang)
184     env = Environment(tools = ['default'] + env['tools_names'], options = vars,
185     ENV = {'PATH' : os.environ['PATH']})
186    
187 jfenwick 6509 # Covert env['netcdf'] into one of False, 3, 4
188     # Also choose default values for libraries
189     pos1=netcdf_flavours.index('False')
190     pos2=netcdf_flavours.index('3')
191     mypos=netcdf_flavours.index(env['netcdf'])
192     if 0 <= mypos <=pos1:
193 jfenwick 6510 env['netcdf']=0
194 jfenwick 6509 elif pos1 < mypos <= pos2:
195     env['netcdf']=3
196     if env['netcdf_libs']=='DEFAULT':
197     env['netcdf_libs']=['netcdf_c++', 'netcdf']
198     else: # netcdf4
199     env['netcdf']=4
200     if env['netcdf_libs']=='DEFAULT':
201     env['netcdf_libs']=['netcdf_c++4']
202 jfenwick 3078
203 jfenwick 3259 if options_file:
204     opts_valid=False
205     if 'escript_opts_version' in env.Dictionary() and \
206     int(env['escript_opts_version']) >= REQUIRED_OPTS_VERSION:
207     opts_valid=True
208     if opts_valid:
209     print("Using options in %s." % options_file)
210     else:
211     print("\nOptions file %s" % options_file)
212 caltinay 6241 print("is outdated! Please update the file after reading scons/templates/README_FIRST")
213     print("and setting escript_opts_version to %d.\n"%REQUIRED_OPTS_VERSION)
214 jfenwick 3259 Exit(1)
215 jfenwick 3078
216 jfenwick 3259 # Generate help text (scons -h)
217     Help(vars.GenerateHelpText(env))
218 jfenwick 3078
219 jfenwick 3259 # Check for superfluous options
220 caltinay 3268 if len(vars.UnknownVariables())>0:
221     for k in vars.UnknownVariables():
222     print("Unknown option '%s'" % k)
223     Exit(1)
224 jfenwick 3078
225 sshaw 5381 if 'dudley' in env['domains']:
226     env['domains'].append('finley')
227    
228 caltinay 6119 env['domains'] = sorted(set(env['domains']))
229    
230 caltinay 4295 # create dictionary which will be populated with info for buildvars file
231 caltinay 6119 env['buildvars'] = {}
232 caltinay 4295 # create list which will be populated with warnings if there are any
233 caltinay 6119 env['warnings'] = []
234 caltinay 4295
235 jfenwick 3259 #################### Make sure install directories exist #####################
236 ksteube 1705
237 caltinay 6119 env['BUILD_DIR'] = Dir(env['build_dir']).abspath
238     prefix = Dir(env['prefix']).abspath
239     env['buildvars']['prefix'] = prefix
240 jfenwick 3259 env['incinstall'] = os.path.join(prefix, 'include')
241     env['bininstall'] = os.path.join(prefix, 'bin')
242     env['libinstall'] = os.path.join(prefix, 'lib')
243     env['pyinstall'] = os.path.join(prefix, 'esys')
244 jfenwick 2604 if not os.path.isdir(env['bininstall']):
245     os.makedirs(env['bininstall'])
246     if not os.path.isdir(env['libinstall']):
247     os.makedirs(env['libinstall'])
248     if not os.path.isdir(env['pyinstall']):
249     os.makedirs(env['pyinstall'])
250    
251 jfenwick 3259 env.Append(CPPPATH = [env['incinstall']])
252     env.Append(LIBPATH = [env['libinstall']])
253 jfenwick 2603
254 jfenwick 3259 ################# Fill in compiler options if not set above ##################
255 ksteube 1312
256 caltinay 6119 if env['cxx'] != 'default':
257     env['CXX'] = env['cxx']
258 gross 1024
259 jfenwick 3259 # default compiler/linker options
260 caltinay 6287 cc_flags = '-std=c++11'
261 jfenwick 3259 cc_optim = ''
262     cc_debug = ''
263     omp_flags = ''
264     omp_ldflags = ''
265     fatalwarning = '' # switch to turn warnings into errors
266     sysheaderopt = '' # how to indicate that a header is a system header
267 jfenwick 2130
268 jfenwick 3259 # env['CC'] might be a full path
269 caltinay 4520 cc_name=os.path.basename(env['CXX'])
270 caltinay 2882
271 caltinay 4520 if cc_name == 'icpc':
272 jfenwick 3259 # Intel compiler
273 caltinay 6010 # #1478: class "std::auto_ptr<...>" was declared deprecated
274 caltinay 4090 # #1875: offsetof applied to non-POD types is nonstandard (in boost)
275 jfenwick 4542 # removed -std=c99 because icpc doesn't like it and we aren't using c anymore
276 caltinay 6010 cc_flags = "-std=c++11 -fPIC -w2 -wd1875 -wd1478 -Wno-unknown-pragmas"
277 aellery 6723 cc_optim = "-Ofast -ftz -fno-alias -xCORE-AVX2 -ipo"
278 gross 6702 #cc_optim = "-Ofast -ftz -fno-alias -inline-level=2 -ipo -xCORE-AVX2"
279     #cc_optim = "-O2 -ftz -fno-alias -inline-level=2"
280     #cc_optim = "-O0 -ftz -fno-alias"
281     #cc_optim = "-O3 -ftz -fno-alias -inline-level=2 -ipo -xHost"
282 jfenwick 6098 cc_debug = "-g -O0 -DDOASSERT -DDOPROF -DBOUNDS_CHECK -DSLOWSHARECHECK"
283 jfenwick 6404 omp_flags = "-qopenmp"
284     omp_ldflags = "-qopenmp" # removing -openmp-report (which is deprecated) because the replacement outputs to a file
285 jfenwick 3259 fatalwarning = "-Werror"
286 caltinay 4520 elif cc_name[:3] == 'g++':
287 caltinay 5250 # GNU C++ on any system
288 caltinay 4173 # note that -ffast-math is not used because it breaks isnan(),
289     # see mantis #691
290 aellery 6786 cc_flags = "-std=c++11 -pedantic -Wall -fPIC -finline-functions"
291 aellery 6799 cc_flags += " -Wno-unknown-pragmas -Wno-sign-compare -Wno-system-headers -Wno-long-long -Wno-strict-aliasing "
292 uqaeller 7027 cc_flags += " -Wno-unused-function"
293 aellery 7002 cc_flags += " -Wno-stringop-truncation -Wno-deprecated-declarations --param=max-vartrack-size=100000000"
294 jfenwick 3259 cc_optim = "-O3"
295 caltinay 5250 #max-vartrack-size: avoid vartrack limit being exceeded with escriptcpp.cpp
296 jfenwick 6501 cc_debug = "-g3 -O0 -DDOASSERT -DDOPROF -DBOUNDS_CHECK -DSLOWSHARECHECK --param=max-vartrack-size=100000000"
297     #Removed because new netcdf doesn't seem to like it
298 aellery 6898 #cc_debug += ' -D_GLIBCXX_DEBUG '
299 jfenwick 3259 omp_flags = "-fopenmp"
300     omp_ldflags = "-fopenmp"
301     fatalwarning = "-Werror"
302     sysheaderopt = "-isystem"
303     elif cc_name == 'cl':
304     # Microsoft Visual C on Windows
305     cc_flags = "/EHsc /MD /GR /wd4068 /D_USE_MATH_DEFINES /DDLL_NETCDF"
306     cc_optim = "/O2 /Op /W3"
307     cc_debug = "/Od /RTCcsu /ZI /DBOUNDS_CHECK"
308     fatalwarning = "/WX"
309     elif cc_name == 'icl':
310     # Intel C on Windows
311     cc_flags = '/EHsc /GR /MD'
312     cc_optim = '/fast /Oi /W3 /Qssp /Qinline-factor- /Qinline-min-size=0 /Qunroll'
313     cc_debug = '/Od /RTCcsu /Zi /Y- /debug:all /Qtrapuv'
314     omp_flags = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
315     omp_ldflags = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
316 aellery 6788 elif cc_name == 'clang++':
317     # Clang++ on any system
318 aellery 6879 cc_flags = "-std=c++11 -Wall -fPIC -fdiagnostics-color=always -Wno-uninitialized "
319 aellery 6791 cc_flags += "-Wno-unused-private-field -Wno-unknown-pragmas "
320 aellery 6799 if env['trilinos'] is True:
321     cc_flags += "-Wno-unused-variable -Wno-exceptions -Wno-deprecated-declarations"
322 aellery 6788 cc_optim = "-O3"
323     cc_debug = "-ggdb3 -O0 -fdiagnostics-fixit-info -pedantic "
324     cc_debug += "-DDOASSERT -DDOPROF -DBOUNDS_CHECK -DSLOWSHARECHECK "
325     omp_flags = "-fopenmp"
326     omp_ldflags = "-fopenmp"
327     fatalwarning = "-Werror"
328     sysheaderopt = "-isystem"
329 phornby 1243
330 caltinay 4295 env['sysheaderopt']=sysheaderopt
331    
332 jfenwick 3259 # set defaults if not otherwise specified
333     if env['cc_flags'] == 'default': env['cc_flags'] = cc_flags
334     if env['cc_optim'] == 'default': env['cc_optim'] = cc_optim
335     if env['cc_debug'] == 'default': env['cc_debug'] = cc_debug
336     if env['omp_flags'] == 'default': env['omp_flags'] = omp_flags
337     if env['omp_ldflags'] == 'default': env['omp_ldflags'] = omp_ldflags
338     if env['cxx_extra'] != '': env.Append(CXXFLAGS = env['cxx_extra'])
339     if env['ld_extra'] != '': env.Append(LINKFLAGS = env['ld_extra'])
340 jfenwick 2130
341 caltinay 5183 if env['longindices']:
342 aellery 6844 if env['paso']:
343 caltinay 5183 env.Append(CPPDEFINES = ['ESYS_INDEXTYPE_LONG'])
344 aellery 6844 else:
345     env['warnings'].append("The longindices feature requires paso!")
346 caltinay 5183
347 jfenwick 3259 # set up the autolazy values
348 caltinay 6297 if env['forcelazy'] == 1:
349 jfenwick 3259 env.Append(CPPDEFINES=['FAUTOLAZYON'])
350 caltinay 6297 elif env['forcelazy'] == 0:
351 jfenwick 3259 env.Append(CPPDEFINES=['FAUTOLAZYOFF'])
352 ksteube 1312
353 jfenwick 3259 # set up the collective resolve values
354 caltinay 6297 if env['forcecollres'] == 1:
355 jfenwick 3259 env.Append(CPPDEFINES=['FRESCOLLECTON'])
356 caltinay 6297 elif env['forcecollres'] == 0:
357 jfenwick 3259 env.Append(CPPDEFINES=['FRESCOLLECTOFF'])
358 jfenwick 2273
359 jfenwick 3259 # allow non-standard C if requested
360 jfenwick 2827 if env['iknowwhatimdoing']:
361 jfenwick 3259 env.Append(CPPDEFINES=['IKNOWWHATIMDOING'])
362 jfenwick 2827
363 jfenwick 3259 # Disable OpenMP if no flags provided
364     if env['openmp'] and env['omp_flags'] == '':
365 caltinay 4295 env['warnings'].append("OpenMP requested but no flags provided - disabling OpenMP!")
366 jfenwick 3259 env['openmp'] = False
367 gross 1160
368 jfenwick 3259 if env['openmp']:
369     env.Append(CCFLAGS = env['omp_flags'])
370     if env['omp_ldflags'] != '': env.Append(LINKFLAGS = env['omp_ldflags'])
371     else:
372     env['omp_flags']=''
373     env['omp_ldflags']=''
374 ksteube 1312
375 caltinay 4295 env['buildvars']['openmp']=int(env['openmp'])
376    
377 jfenwick 3259 # add debug/non-debug compiler flags
378 caltinay 4295 env['buildvars']['debug']=int(env['debug'])
379 jfenwick 3259 if env['debug']:
380     env.Append(CCFLAGS = env['cc_debug'])
381 gross 2423 else:
382 jfenwick 3259 env.Append(CCFLAGS = env['cc_optim'])
383 gross 1163
384 jfenwick 3259 # always add cc_flags
385     env.Append(CCFLAGS = env['cc_flags'])
386 phornby 1243
387 jfenwick 3259 # add system libraries
388     env.AppendUnique(LIBS = env['sys_libs'])
389 gross 2363
390 caltinay 4295 # determine svn revision
391 jfenwick 3618 global_revision=ARGUMENTS.get('SVN_VERSION', None)
392     if global_revision:
393     global_revision = re.sub(':.*', '', global_revision)
394     global_revision = re.sub('[^0-9]', '', global_revision)
395     if global_revision == '': global_revision='-2'
396     else:
397     # Get the global Subversion revision number for the getVersion() method
398     try:
399 jfenwick 3259 global_revision = os.popen('svnversion -n .').read()
400     global_revision = re.sub(':.*', '', global_revision)
401     global_revision = re.sub('[^0-9]', '', global_revision)
402     if global_revision == '': global_revision='-2'
403 jfenwick 3618 except:
404 jfenwick 3259 global_revision = '-1'
405 caltinay 3271 env['svn_revision']=global_revision
406 caltinay 4295 env['buildvars']['svn_revision']=global_revision
407 jfenwick 3259 env.Append(CPPDEFINES=['SVN_VERSION='+global_revision])
408 gross 2363
409 aellery 6848 # If that failed, try to get the version number from the file svn_version
410 aellery 6843 if global_revision=='-2' or global_revision=='-1':
411 aellery 6848 try:
412     global_revision=str(os.popen('cat svn_version 2>/dev/null').read())
413     if global_revision[global_revision.__len__()-1] == '\n':
414     temp=global_revision[0:(global_revision.__len__()-1)]
415     else:
416     temp=global_revision
417     print("Using svn revision information from file. Got revision = %s" % temp)
418     except:
419     global_revision='-2'
420 aellery 6843
421 aellery 6848 if global_revision=='-2' or global_revision=='-1':
422     env['warnings'].append("Could not detect the svn revision number!")
423    
424 caltinay 4295 env['IS_WINDOWS']=IS_WINDOWS
425 jfenwick 5407 env['IS_OSX']=IS_OSX
426 caltinay 4295
427 jfenwick 3259 ###################### Copy required environment vars ########################
428 gross 2363
429 jfenwick 3259 # Windows doesn't use LD_LIBRARY_PATH but PATH instead
430     if IS_WINDOWS:
431     LD_LIBRARY_PATH_KEY='PATH'
432     env['ENV']['LD_LIBRARY_PATH']=''
433     else:
434     LD_LIBRARY_PATH_KEY='LD_LIBRARY_PATH'
435 robwdcock 682
436 caltinay 4295 env['LD_LIBRARY_PATH_KEY']=LD_LIBRARY_PATH_KEY
437    
438 caltinay 3319 # the following env variables are exported for the unit tests
439 phornby 1244
440 jfenwick 3259 for key in 'OMP_NUM_THREADS', 'ESCRIPT_NUM_PROCS', 'ESCRIPT_NUM_NODES':
441     try:
442     env['ENV'][key] = os.environ[key]
443     except KeyError:
444 caltinay 5045 env['ENV'][key] = '1'
445 robwdcock 682
446 jfenwick 3259 env_export=env['env_export']
447 caltinay 4917 env_export.extend(['ESCRIPT_NUM_THREADS','ESCRIPT_HOSTFILE','DISPLAY','XAUTHORITY','PATH','HOME','KMP_MONITOR_STACKSIZE','TMPDIR','TEMP','TMP','LD_PRELOAD'])
448 robwdcock 682
449 jfenwick 3259 for key in set(env_export):
450     try:
451     env['ENV'][key] = os.environ[key]
452     except KeyError:
453     pass
454 ksteube 1312
455 caltinay 5436 for key in os.environ.keys():
456     if key.startswith("SLURM_"):
457     env['ENV'][key] = os.environ[key]
458    
459 jfenwick 3259 try:
460     env.PrependENVPath(LD_LIBRARY_PATH_KEY, os.environ[LD_LIBRARY_PATH_KEY])
461     except KeyError:
462     pass
463 ksteube 1312
464 jfenwick 4640 if IS_OSX:
465     try:
466     env.PrependENVPath('DYLD_LIBRARY_PATH', os.environ['DYLD_LIBRARY_PATH'])
467     except KeyError:
468     pass
469    
470 jfenwick 3259 try:
471     env['ENV']['PYTHONPATH'] = os.environ['PYTHONPATH']
472     except KeyError:
473     pass
474 ksteube 1312
475 jfenwick 3259 ######################## Add some custom builders ############################
476 ksteube 1312
477 caltinay 6124 # Takes care of prefix and suffix for Python modules:
478     def build_python_module(env, target, source):
479 uqaeller 7011 sl_suffix = '.pyd' if IS_WINDOWS else '.so'
480     return env.SharedLibrary(target, source, SHLIBPREFIX='', SHLIBSUFFIX=sl_suffix)
481 caltinay 6124 env.AddMethod(build_python_module, "PythonModule")
482    
483 jfenwick 3851 if env['pythoncmd']=='python':
484     py_builder = Builder(action = build_py, suffix = '.pyc', src_suffix = '.py', single_source=True)
485     else:
486 jfenwick 3892 py_builder = Builder(action = env['pythoncmd']+" scripts/py_comp.py $SOURCE $TARGET", suffix = '.pyc', src_suffix = '.py', single_source=True)
487 jfenwick 3259 env.Append(BUILDERS = {'PyCompile' : py_builder});
488 gross 2423
489 jfenwick 3259 runUnitTest_builder = Builder(action = runUnitTest, suffix = '.passed', src_suffix=env['PROGSUFFIX'], single_source=True)
490     env.Append(BUILDERS = {'RunUnitTest' : runUnitTest_builder});
491 gross 2423
492 jfenwick 3259 runPyUnitTest_builder = Builder(action = runPyUnitTest, suffix = '.passed', src_suffic='.py', single_source=True)
493     env.Append(BUILDERS = {'RunPyUnitTest' : runPyUnitTest_builder});
494 ksteube 1756
495 sshaw 5017 runPyExample_builder = Builder(action = runPyExample, suffix = '.passed', src_suffic='.py', single_source=True)
496     env.Append(BUILDERS = {'RunPyExample' : runPyExample_builder});
497    
498 jfenwick 3259 epstopdfbuilder = Builder(action = eps2pdf, suffix='.pdf', src_suffix='.eps', single_source=True)
499     env.Append(BUILDERS = {'EpsToPDF' : epstopdfbuilder});
500 ksteube 817
501 jfenwick 3259 ############################ Dependency checks ###############################
502 phornby 1246
503 caltinay 4295 ######## Compiler
504     env=checkCompiler(env)
505 phornby 1634
506 jfenwick 3259 ######## Python headers & library (required)
507 caltinay 4295 env=checkPython(env)
508 gross 806
509 caltinay 4295 ######## boost & boost-python (required)
510     env=checkBoost(env)
511 jfenwick 3892
512 caltinay 4295 ######## numpy (required) and numpy headers (optional)
513     env=checkNumpy(env)
514 jfenwick 3892
515 caltinay 3597 ######## CppUnit (required for tests)
516 caltinay 4295 env=checkCppUnit(env)
517 caltinay 3597
518 caltinay 4295 ######## optional python modules (sympy, pyproj)
519     env=checkOptionalModules(env)
520 caltinay 3597
521 uqaeller 7011 ######## optional dependencies (netCDF, MKL, UMFPACK, MUMPS, Lapack, Silo, ...)
522 caltinay 4295 env=checkOptionalLibraries(env)
523 caltinay 3975
524 caltinay 3604 ######## PDFLaTeX (for documentation)
525 caltinay 4295 env=checkPDFLatex(env)
526 caltinay 3604
527 caltinay 6249 # set defaults for launchers if not otherwise specified
528     if env['prelaunch'] == 'default':
529     if env['mpi'] == 'INTELMPI' and env['openmp']:
530     env['prelaunch'] = "export I_MPI_PIN_DOMAIN=omp"
531     elif env['mpi'] == 'OPENMPI':
532     # transform comma-separated list to '-x a -x b -x c ...'
533     env['prelaunch'] = "EE=$(echo -x %e|sed -e 's/,/ -x /g')"
534     elif env['mpi'] == 'MPT':
535     env['prelaunch'] = "export MPI_NUM_MEMORY_REGIONS=0"
536     elif env['mpi'] == 'MPICH2':
537     env['prelaunch'] = "mpdboot -n %n -r ssh -f %f"
538     else:
539     env['prelaunch'] = ""
540    
541     if env['launcher'] == 'default':
542     if env['mpi'] == 'INTELMPI':
543     env['launcher'] = "mpirun -hostfile %f -n %N -ppn %p %b"
544     elif env['mpi'] == 'OPENMPI':
545 jfenwick 6573 if env['mpi_no_host']:
546     hostoptionstr=''
547     else:
548     hostoptionstr='--host %h'
549 caltinay 6249 # default to OpenMPI version 1.10 or higher
550 jfenwick 6573 env['launcher'] = "mpirun ${AGENTOVERRIDE} --gmca mpi_warn_on_fork 0 ${EE} "+hostoptionstr+" --map-by node:pe=%t -bind-to core -np %N %b"
551 caltinay 6249 if 'orte_version' in env:
552     major,minor,point = [int(i) for i in env['orte_version'].split('.')]
553     if major == 1 and minor < 10:
554 jfenwick 6573 env['launcher'] = "mpirun ${AGENTOVERRIDE} --gmca mpi_warn_on_fork 0 ${EE} "+hostoptionstr+" --cpus-per-rank %t -np %N %b"
555 caltinay 6249 elif env['mpi'] == 'MPT':
556     env['launcher'] = "mpirun %h -np %p %b"
557     elif env['mpi'] == 'MPICH':
558     env['launcher'] = "mpirun -machinefile %f -np %N %b"
559     elif env['mpi'] == 'MPICH2':
560     env['launcher'] = "mpiexec -genvlist %e -np %N %b"
561     else:
562     env['launcher'] = "%b"
563    
564     if env['postlaunch'] == 'default':
565     if env['mpi'] == 'MPICH2':
566     env['postlaunch'] = "mpdallexit"
567     else:
568     env['postlaunch'] = ""
569    
570 caltinay 6119 # dependency sanity checks
571    
572     if len(env['domains']) == 0:
573     env['warnings'].append("No domains have been built, escript will not be very useful!")
574    
575 jfenwick 3259 # keep some of our install paths first in the list for the unit tests
576     env.PrependENVPath(LD_LIBRARY_PATH_KEY, env['libinstall'])
577     env.PrependENVPath('PYTHONPATH', prefix)
578     env['ENV']['ESCRIPT_ROOT'] = prefix
579 ksteube 1705
580 jfenwick 3259 if not env['verbose']:
581     env['CXXCOMSTR'] = "Compiling $TARGET"
582     env['SHCXXCOMSTR'] = "Compiling $TARGET"
583     env['ARCOMSTR'] = "Linking $TARGET"
584     env['LINKCOMSTR'] = "Linking $TARGET"
585     env['SHLINKCOMSTR'] = "Linking $TARGET"
586 caltinay 3271 env['PDFLATEXCOMSTR'] = "Building $TARGET from LaTeX input $SOURCES"
587     env['BIBTEXCOMSTR'] = "Generating bibliography $TARGET"
588     env['MAKEINDEXCOMSTR'] = "Generating index $TARGET"
589     env['PDFLATEXCOMSTR'] = "Building $TARGET from LaTeX input $SOURCES"
590 jfenwick 3259 #Progress(['Checking -\r', 'Checking \\\r', 'Checking |\r', 'Checking /\r'], interval=17)
591 ksteube 1705
592 caltinay 6119 ########################### Configure the targets ############################
593 ksteube 1247
594 caltinay 6119 from grouptest import GroupTest
595 jfenwick 2235 TestGroups=[]
596    
597 jfenwick 3259 # keep an environment without warnings-as-errors
598     dodgy_env=env.Clone()
599 jfenwick 2827
600 jfenwick 3259 # now add warnings-as-errors flags. This needs to be done after configuration
601     # because the scons test files have warnings in them
602     if ((fatalwarning != '') and (env['werror'])):
603     env.Append(CCFLAGS = fatalwarning)
604 jfenwick 2827
605 phornby 2027 Export(
606 jfenwick 3259 ['env',
607     'dodgy_env',
608     'IS_WINDOWS',
609     'TestGroups'
610     ]
611     )
612 ksteube 1705
613 caltinay 3604 target_init = env.Command(os.path.join(env['pyinstall'],'__init__.py'), None, Touch('$TARGET'))
614 ksteube 1705 env.Alias('target_init', [target_init])
615    
616 caltinay 6119 # escript can't be turned off
617 caltinay 6174 build_all_list = ['build_escript']
618     install_all_list = ['target_init', 'install_escript']
619 caltinay 2810
620 caltinay 6119 if env['usempi']:
621     build_all_list += ['build_pythonMPI', 'build_overlord']
622     install_all_list += ['install_pythonMPI', 'install_overlord']
623 caltinay 3096
624 caltinay 6333 env['buildvars']['paso'] = int(env['paso'])
625 caltinay 6119 if env['paso']:
626 caltinay 6167 env.Append(CPPDEFINES = ['ESYS_HAVE_PASO'])
627 caltinay 6119 build_all_list += ['build_paso']
628     install_all_list += ['install_paso']
629 caltinay 2910
630 caltinay 6555 env['buildvars']['trilinos'] = int(env['trilinos'])
631 caltinay 6119 if env['trilinos']:
632     build_all_list += ['build_trilinoswrap']
633     install_all_list += ['install_trilinoswrap']
634 caltinay 3792
635 caltinay 6333 env['buildvars']['domains'] = ','.join(env['domains'])
636 caltinay 6119 for domain in env['domains']:
637 caltinay 6174 env.Append(CPPDEFINES = ['ESYS_HAVE_'+domain.upper()])
638 caltinay 6119 build_all_list += ['build_%s'%domain]
639     install_all_list += ['install_%s'%domain]
640 ksteube 1705
641 caltinay 6333 env['buildvars']['weipa'] = int(env['weipa'])
642 caltinay 6119 if env['weipa']:
643 caltinay 6174 env.Append(CPPDEFINES = ['ESYS_HAVE_WEIPA'])
644 caltinay 6119 build_all_list += ['build_weipa']
645     install_all_list += ['install_weipa']
646 caltinay 6184 if 'finley' in env['domains'] or 'dudley' in env['domains']:
647 caltinay 6119 build_all_list += ['build_escriptreader']
648     install_all_list += ['install_escriptreader']
649 ksteube 1705
650 caltinay 6174 variant='$BUILD_DIR/$PLATFORM/'
651     env.SConscript('escriptcore/SConscript', variant_dir=variant+'escriptcore', duplicate=0)
652     env.SConscript('escript/py_src/SConscript', variant_dir=variant+'escript', duplicate=0)
653     env.SConscript('pythonMPI/src/SConscript', variant_dir=variant+'pythonMPI', duplicate=0)
654     env.SConscript('tools/overlord/SConscript', variant_dir=variant+'tools/overlord', duplicate=0)
655     env.SConscript('paso/SConscript', variant_dir=variant+'paso', duplicate=0)
656     env.SConscript('trilinoswrap/SConscript', variant_dir=variant+'trilinoswrap', duplicate=0)
657     env.SConscript('cusplibrary/SConscript')
658     env.SConscript('dudley/SConscript', variant_dir=variant+'dudley', duplicate=0)
659     env.SConscript('finley/SConscript', variant_dir=variant+'finley', duplicate=0)
660     env.SConscript('ripley/SConscript', variant_dir=variant+'ripley', duplicate=0)
661     env.SConscript('speckley/SConscript', variant_dir=variant+'speckley', duplicate=0)
662     env.SConscript('weipa/SConscript', variant_dir=variant+'weipa', duplicate=0)
663     env.SConscript(dirs = ['downunder/py_src'], variant_dir=variant+'downunder', duplicate=0)
664     env.SConscript(dirs = ['modellib/py_src'], variant_dir=variant+'modellib', duplicate=0)
665     env.SConscript(dirs = ['pycad/py_src'], variant_dir=variant+'pycad', duplicate=0)
666     env.SConscript('tools/escriptconvert/SConscript', variant_dir=variant+'tools/escriptconvert', duplicate=0)
667     env.SConscript('doc/SConscript', variant_dir=variant+'doc', duplicate=0)
668 ksteube 1705
669 caltinay 6119 env.Alias('build', build_all_list)
670    
671 caltinay 3947 install_all_list += ['install_downunder_py']
672 jfenwick 3259 install_all_list += ['install_modellib_py']
673     install_all_list += ['install_pycad_py']
674 caltinay 6119 install_all_list += [env.Install(Dir('scripts',env['build_dir']), os.path.join('scripts', 'release_sanity.py'))]
675 ksteube 1705
676 jfenwick 5851 if env['osx_dependency_fix']:
677     print("Require dependency fix")
678 caltinay 6119 install_all=env.Command('install', install_all_list, 'scripts/moveall.sh')
679 jfenwick 5851 else:
680 caltinay 6119 install_all=env.Alias('install', install_all_list)
681 jfenwick 5851
682 jfenwick 5811 sanity=env.Alias('sanity', env.Command('dummy','',os.path.join(env['prefix'], 'bin', 'run-escript')+' '+os.path.join(env['build_dir'],'scripts', 'release_sanity.py')))
683 jfenwick 5802 env.Depends('dummy', install_all)
684 jfenwick 5801 if env['usempi']:
685 caltinay 6119 env.Depends('dummy', ['install_pythonMPI'])
686 jfenwick 5801
687 caltinay 6119 # if all domains are built:
688 aellery 6722 if env['domains'] == all_domains and env['insane'] == False:
689     env.AlwaysBuild('sanity')
690     env.Default('sanity')
691 jfenwick 5802 else:
692 caltinay 6119 env.Default('install')
693 jfenwick 5800
694 jfenwick 3259 ################## Targets to build and run the test suite ###################
695 ksteube 1705
696 caltinay 3597 if not env['cppunit']:
697 caltinay 4520 test_msg = env.Command('.dummy.', None, '@echo "Cannot run C++ unit tests, CppUnit not found!";exit 1')
698 caltinay 3597 env.Alias('run_tests', test_msg)
699 caltinay 4249 env.Alias('build_tests', '')
700 caltinay 6119 env.Alias('run_tests', ['install'])
701     env.Alias('all_tests', ['install', 'run_tests', 'py_tests'])
702     env.Alias('build_full',['install','build_tests','build_py_tests'])
703     Requires('py_tests', 'install')
704 ksteube 1705
705 jfenwick 3259 ##################### Targets to build the documentation #####################
706 artak 2820
707 jfenwick 4244 env.Alias('pdfdocs',['user_pdf', 'install_pdf', 'cookbook_pdf', 'inversion_pdf'])
708     env.Alias('basedocs', ['pdfdocs','examples_tarfile', 'examples_zipfile', 'api_doxygen'])
709 jfenwick 4167 env.Alias('docs', ['basedocs', 'sphinxdoc'])
710 caltinay 6119 env.Alias('release_prep', ['docs', 'install'])
711     env.Alias('release_prep_old', ['basedocs', 'api_epydoc', 'install'])
712 ksteube 1705
713 jfenwick 4078 # The test scripts are always generated, this target allows us to
714     # generate the testscripts without doing a full build
715     env.Alias('testscripts',[])
716    
717 uqaeller 7011 generateTestScripts(env, TestGroups)
718 jfenwick 2879
719 caltinay 6119 ######################## Populate the buildvars file #########################
720 caltinay 3604
721 caltinay 6119 write_buildvars(env)
722     # delete buildvars upon cleanup - target_init is default so use it
723     env.Clean('target_init', File('buildvars', env['libinstall']))
724    
725     write_launcher(env)
726    
727     # remove obsolete files
728     if not env['usempi']:
729     Execute(Delete(File(['pythonMPI','pythonMPIredirect'], env['libinstall'])))
730     Execute(Delete(File('escript-overlord', env['bininstall'])))
731    
732 caltinay 4295 ######################## Summarize our environment ###########################
733     def print_summary():
734 caltinay 6255 d_list=[]
735 caltinay 4295 print("")
736 caltinay 4299 print("*** Config Summary (see config.log and <prefix>/lib/buildvars for details) ***")
737 caltinay 6119 print("Escript revision %s"%global_revision)
738 caltinay 4295 print(" Install prefix: %s"%env['prefix'])
739 caltinay 6248 print(" Python: %s (Version %s)"%(env['pythoncmd'],env['python_version']))
740 caltinay 5696 print(" boost: %s (Version %s)"%(env['boost_prefix'],env['boost_version']))
741 aellery 6882 if env['have_boost_numpy'] is True:
742 aellery 6872 print(" boost numpy: YES")
743     else:
744     print(" boost numpy: NO")
745 aellery 6818 if env['trilinos']:
746 aellery 6898 print(" trilinos: %s (Version %s)" % (env['trilinos_prefix'],env['trilinos_version']))
747 aellery 6818 else:
748     print(" trilinos: NO")
749 caltinay 4299 if env['numpy_h']:
750     print(" numpy: YES (with headers)")
751     else:
752     print(" numpy: YES (without headers)")
753 caltinay 4295 if env['usempi']:
754 caltinay 6249 if 'orte_version' in env:
755     print(" MPI: %s (Version %s)"%(env['mpi'], env['orte_version']))
756     else:
757     print(" MPI: YES (flavour: %s)"%env['mpi'])
758 caltinay 4295 else:
759 caltinay 6255 d_list.append('mpi')
760 caltinay 5696 if env['parmetis']:
761     print(" ParMETIS: %s (Version %s)"%(env['parmetis_prefix'],env['parmetis_version']))
762     else:
763 caltinay 6255 d_list.append('parmetis')
764 caltinay 4295 if env['uselapack']:
765     print(" LAPACK: YES (flavour: %s)"%env['lapack'])
766     else:
767 caltinay 6255 d_list.append('lapack')
768 caltinay 5391 if env['gmshpy']:
769     gmshpy=" + python module"
770     else:
771     gmshpy=""
772 caltinay 4295 if env['gmsh']=='m':
773 caltinay 5391 print(" gmsh: YES, MPI-ENABLED"+gmshpy)
774 caltinay 4295 elif env['gmsh']=='s':
775 caltinay 5391 print(" gmsh: YES"+gmshpy)
776 caltinay 4295 else:
777 caltinay 5391 if env['gmshpy']:
778     print(" gmsh: python module only")
779     else:
780 caltinay 6255 d_list.append('gmsh')
781     if env['compressed_files']:
782     print(" gzip: YES")
783     else:
784     d_list.append('gzip')
785 caltinay 4299
786 caltinay 6255 solvers = []
787     direct = []
788     if env['paso']:
789     solvers.append('paso')
790     if env['mkl']:
791     direct.append('mkl')
792     if env['umfpack']:
793     direct.append('umfpack')
794 uqaeller 7027 if env['mumps']:
795     direct.append('mumps')
796 caltinay 6255 else:
797     d_list.append('paso')
798     if env['trilinos']:
799     solvers.append('trilinos')
800     direct.append('trilinos')
801     else:
802     d_list.append('trilinos')
803    
804     print(" Solver library: %s"%(", ".join(solvers)))
805     if len(direct) > 0:
806     print(" Direct solver: YES (%s)"%(", ".join(direct)))
807     else:
808     print(" Direct solver: NONE")
809     print(" domains: %s"%(", ".join(env['domains'])))
810 jfenwick 6509 if env['netcdf']==4:
811     print(" netcdf: YES (4 + 3)")
812     elif env['netcdf']==3:
813     print(" netcdf: YES (3)")
814     else:
815     print(" netcdf: NO")
816 caltinay 6255 e_list=[]
817 aellery 6739 for i in ('weipa','debug','openmp','cppunit','gdal','mkl',
818 uqaeller 7027 'mumps','pyproj','scipy','silo','sympy','umfpack','visit'):
819 caltinay 6255 if env[i]: e_list.append(i)
820     else: d_list.append(i)
821    
822     d_list += set(all_domains).difference(env['domains'])
823     for i in e_list:
824     print("%16s: YES"%i)
825     print("\n DISABLED features: %s"%(" ".join(sorted(d_list))))
826    
827 caltinay 4295 if ((fatalwarning != '') and (env['werror'])):
828     print(" Treating warnings as errors")
829     else:
830     print(" NOT treating warnings as errors")
831     print("")
832     for w in env['warnings']:
833     print("WARNING: %s"%w)
834 sshaw 4726 if len(GetBuildFailures()):
835     print("\nERROR: build stopped due to errors\n")
836     else:
837     print("\nSUCCESS: build complete\n")
838 caltinay 4295
839     atexit.register(print_summary)

  ViewVC Help
Powered by ViewVC 1.1.26