/[escript]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6799 - (show annotations)
Mon Mar 25 05:53:58 2019 UTC (3 weeks, 6 days ago) by aellery
File size: 33575 byte(s)
I have rewritten the solverbuddy. Briefly:

1. The remaining AMG code has been removed from PASO.
2. If Trilinos is available, escript will now use it by default.
3. eScript will use a direct solver by default, (if one is available,) when solving 2 dimensional problems and an iterative solver, by default, when solving 3 dimensional problems. This can be changed by a user by manually specifying which solver to use.
4. There is a new option available, setHermitian(), that allows a user to specify when a coefficient matrix is Hermitian.
5. Symmetry information is always passed onto the Trilinos solver when this information is relevant.
6. All tests have been updated, when relevant, to reflect these changes.
7. I fixed a couple of undocumented bugs.


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

  ViewVC Help
Powered by ViewVC 1.1.26