/[escript]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7011 - (show annotations)
Wed Jul 22 04:13:34 2020 UTC (2 weeks ago) by uqaeller
File size: 34453 byte(s)
Prototype for the builtin MUMPS solver.


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 if IS_WINDOWS:
34 IS_OSX = False
35 else:
36 IS_OSX = (os.uname()[0] == 'Darwin')
37
38 ########################## Determine options file ############################
39 # 1. command line
40 # 2. scons/<hostname>_options.py
41 # 3. name as part of a cluster
42 options_file=ARGUMENTS.get('options_file', None)
43 if not options_file:
44 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
51 if not os.path.isfile(options_file):
52 print("\nWARNING:\nOptions file %s" % options_file)
53 print("not found! Default options will be used which is most likely suboptimal.")
54 print("We recommend that you copy the most relavent options file in the scons/template/")
55 print("subdirectory and customize it to your needs.\n")
56 options_file = None
57
58 ############################### Build options ################################
59
60 default_prefix='/usr'
61 mpi_flavours=('no', 'none', 'MPT', 'MPICH', 'MPICH2', 'OPENMPI', 'INTELMPI')
62 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 all_domains = ['dudley','finley','ripley','speckley']
66
67 #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 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 PathVariable('build_dir', 'Top-level build directory', Dir('#/build').abspath, PathVariable.PathIsDirCreate),
78 BoolVariable('verbose', 'Output full compile/link lines', False),
79 # Compiler/Linker options
80 ('cxx', 'Path to C++ compiler', 'default'),
81 ('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 ('cxx_extra', 'Extra C++ compiler flags', ''),
85 ('ld_extra', 'Extra linker flags', ''),
86 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 ('boost_libs', 'Boost libraries to link with', ['boost_python-mt']),
94 # Mandatory for tests
95 ('cppunit_prefix', 'Prefix/Paths of CppUnit installation', default_prefix),
96 ('cppunit_libs', 'CppUnit libraries to link with', ['cppunit']),
97 # 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 BoolVariable('use_gmsh', 'Enable gmsh, if available', True),
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 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 TristateVariable('lapack', 'Enable LAPACK', 'auto'),
119 ('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 ('silo_libs', 'Silo libraries to link with', ['siloh5', 'hdf5']),
124 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 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 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 ('mathjax_path', 'Path to MathJax.js file', 'default'),
134 # Advanced settings
135 ('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 #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 # An option for specifying the compiler tools
143 ('tools_names', 'Compiler tools to use', ['default']),
144 ('env_export', 'Environment variables to be passed to tools',[]),
145 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 BoolVariable('build_shared', '(deprecated option, ignored)', True),
148 ('sys_libs', 'Extra libraries to link with', []),
149 ('escript_opts_version', 'Version of options file (do not specify on command line)'),
150 ('SVN_VERSION', 'Do not use from options file', -2),
151 ('pythoncmd', 'which python to compile with', sys.executable),
152 ('pythonlibname', 'Name of the python library to link. (This is found automatically for python2.X.)', ''),
153 ('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 BoolVariable('longindices', 'use long indices (for very large matrices)', False),
156 BoolVariable('compressed_files','Enables reading from compressed binary files', True),
157 ('compression_libs', 'Compression libraries to link with', ['boost_iostreams']),
158 BoolVariable('disable_boost_numpy', 'Do not build using boost_numpy, even if it is available', False),
159 BoolVariable('osx_dependency_fix', 'Fix dependencies for libraries to have absolute paths (OSX)', False),
160 BoolVariable('stdlocationisprefix', 'Set the prefix as escript root in the launcher', False),
161 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 )
164
165 ##################### Create environment and help text #######################
166
167 # 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
170 # 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
175 # set the vars for clang
176 def mkclang(env):
177 env['CXX']='clang++'
178
179 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 # 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 env['netcdf']=0
194 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
203 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 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 Exit(1)
215
216 # Generate help text (scons -h)
217 Help(vars.GenerateHelpText(env))
218
219 # Check for superfluous options
220 if len(vars.UnknownVariables())>0:
221 for k in vars.UnknownVariables():
222 print("Unknown option '%s'" % k)
223 Exit(1)
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-deprecated-declarations --param=max-vartrack-size=100000000"
293 cc_optim = "-O3"
294 #max-vartrack-size: avoid vartrack limit being exceeded with escriptcpp.cpp
295 cc_debug = "-g3 -O0 -DDOASSERT -DDOPROF -DBOUNDS_CHECK -DSLOWSHARECHECK --param=max-vartrack-size=100000000"
296 #Removed because new netcdf doesn't seem to like it
297 #cc_debug += ' -D_GLIBCXX_DEBUG '
298 omp_flags = "-fopenmp"
299 omp_ldflags = "-fopenmp"
300 fatalwarning = "-Werror"
301 sysheaderopt = "-isystem"
302 elif cc_name == 'cl':
303 # Microsoft Visual C on Windows
304 cc_flags = "/EHsc /MD /GR /wd4068 /D_USE_MATH_DEFINES /DDLL_NETCDF"
305 cc_optim = "/O2 /Op /W3"
306 cc_debug = "/Od /RTCcsu /ZI /DBOUNDS_CHECK"
307 fatalwarning = "/WX"
308 elif cc_name == 'icl':
309 # Intel C on Windows
310 cc_flags = '/EHsc /GR /MD'
311 cc_optim = '/fast /Oi /W3 /Qssp /Qinline-factor- /Qinline-min-size=0 /Qunroll'
312 cc_debug = '/Od /RTCcsu /Zi /Y- /debug:all /Qtrapuv'
313 omp_flags = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
314 omp_ldflags = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
315 elif cc_name == 'clang++':
316 # Clang++ on any system
317 cc_flags = "-std=c++11 -Wall -fPIC -fdiagnostics-color=always -Wno-uninitialized "
318 cc_flags += "-Wno-unused-private-field -Wno-unknown-pragmas "
319 if env['trilinos'] is True:
320 cc_flags += "-Wno-unused-variable -Wno-exceptions -Wno-deprecated-declarations"
321 cc_optim = "-O3"
322 cc_debug = "-ggdb3 -O0 -fdiagnostics-fixit-info -pedantic "
323 cc_debug += "-DDOASSERT -DDOPROF -DBOUNDS_CHECK -DSLOWSHARECHECK "
324 omp_flags = "-fopenmp"
325 omp_ldflags = "-fopenmp"
326 fatalwarning = "-Werror"
327 sysheaderopt = "-isystem"
328
329 env['sysheaderopt']=sysheaderopt
330
331 # set defaults if not otherwise specified
332 if env['cc_flags'] == 'default': env['cc_flags'] = cc_flags
333 if env['cc_optim'] == 'default': env['cc_optim'] = cc_optim
334 if env['cc_debug'] == 'default': env['cc_debug'] = cc_debug
335 if env['omp_flags'] == 'default': env['omp_flags'] = omp_flags
336 if env['omp_ldflags'] == 'default': env['omp_ldflags'] = omp_ldflags
337 if env['cxx_extra'] != '': env.Append(CXXFLAGS = env['cxx_extra'])
338 if env['ld_extra'] != '': env.Append(LINKFLAGS = env['ld_extra'])
339
340 if env['longindices']:
341 if env['paso']:
342 env.Append(CPPDEFINES = ['ESYS_INDEXTYPE_LONG'])
343 else:
344 env['warnings'].append("The longindices feature requires paso!")
345
346 # set up the autolazy values
347 if env['forcelazy'] == 1:
348 env.Append(CPPDEFINES=['FAUTOLAZYON'])
349 elif env['forcelazy'] == 0:
350 env.Append(CPPDEFINES=['FAUTOLAZYOFF'])
351
352 # set up the collective resolve values
353 if env['forcecollres'] == 1:
354 env.Append(CPPDEFINES=['FRESCOLLECTON'])
355 elif env['forcecollres'] == 0:
356 env.Append(CPPDEFINES=['FRESCOLLECTOFF'])
357
358 # allow non-standard C if requested
359 if env['iknowwhatimdoing']:
360 env.Append(CPPDEFINES=['IKNOWWHATIMDOING'])
361
362 # Disable OpenMP if no flags provided
363 if env['openmp'] and env['omp_flags'] == '':
364 env['warnings'].append("OpenMP requested but no flags provided - disabling OpenMP!")
365 env['openmp'] = False
366
367 if env['openmp']:
368 env.Append(CCFLAGS = env['omp_flags'])
369 if env['omp_ldflags'] != '': env.Append(LINKFLAGS = env['omp_ldflags'])
370 else:
371 env['omp_flags']=''
372 env['omp_ldflags']=''
373
374 env['buildvars']['openmp']=int(env['openmp'])
375
376 # add debug/non-debug compiler flags
377 env['buildvars']['debug']=int(env['debug'])
378 if env['debug']:
379 env.Append(CCFLAGS = env['cc_debug'])
380 else:
381 env.Append(CCFLAGS = env['cc_optim'])
382
383 # always add cc_flags
384 env.Append(CCFLAGS = env['cc_flags'])
385
386 # add system libraries
387 env.AppendUnique(LIBS = env['sys_libs'])
388
389 # determine svn revision
390 global_revision=ARGUMENTS.get('SVN_VERSION', None)
391 if global_revision:
392 global_revision = re.sub(':.*', '', global_revision)
393 global_revision = re.sub('[^0-9]', '', global_revision)
394 if global_revision == '': global_revision='-2'
395 else:
396 # Get the global Subversion revision number for the getVersion() method
397 try:
398 global_revision = os.popen('svnversion -n .').read()
399 global_revision = re.sub(':.*', '', global_revision)
400 global_revision = re.sub('[^0-9]', '', global_revision)
401 if global_revision == '': global_revision='-2'
402 except:
403 global_revision = '-1'
404 env['svn_revision']=global_revision
405 env['buildvars']['svn_revision']=global_revision
406 env.Append(CPPDEFINES=['SVN_VERSION='+global_revision])
407
408 # If that failed, try to get the version number from the file svn_version
409 if global_revision=='-2' or global_revision=='-1':
410 try:
411 global_revision=str(os.popen('cat svn_version 2>/dev/null').read())
412 if global_revision[global_revision.__len__()-1] == '\n':
413 temp=global_revision[0:(global_revision.__len__()-1)]
414 else:
415 temp=global_revision
416 print("Using svn revision information from file. Got revision = %s" % temp)
417 except:
418 global_revision='-2'
419
420 if global_revision=='-2' or global_revision=='-1':
421 env['warnings'].append("Could not detect the svn revision number!")
422
423 env['IS_WINDOWS']=IS_WINDOWS
424 env['IS_OSX']=IS_OSX
425
426 ###################### Copy required environment vars ########################
427
428 # Windows doesn't use LD_LIBRARY_PATH but PATH instead
429 if IS_WINDOWS:
430 LD_LIBRARY_PATH_KEY='PATH'
431 env['ENV']['LD_LIBRARY_PATH']=''
432 else:
433 LD_LIBRARY_PATH_KEY='LD_LIBRARY_PATH'
434
435 env['LD_LIBRARY_PATH_KEY']=LD_LIBRARY_PATH_KEY
436
437 # the following env variables are exported for the unit tests
438
439 for key in 'OMP_NUM_THREADS', 'ESCRIPT_NUM_PROCS', 'ESCRIPT_NUM_NODES':
440 try:
441 env['ENV'][key] = os.environ[key]
442 except KeyError:
443 env['ENV'][key] = '1'
444
445 env_export=env['env_export']
446 env_export.extend(['ESCRIPT_NUM_THREADS','ESCRIPT_HOSTFILE','DISPLAY','XAUTHORITY','PATH','HOME','KMP_MONITOR_STACKSIZE','TMPDIR','TEMP','TMP','LD_PRELOAD'])
447
448 for key in set(env_export):
449 try:
450 env['ENV'][key] = os.environ[key]
451 except KeyError:
452 pass
453
454 for key in os.environ.keys():
455 if key.startswith("SLURM_"):
456 env['ENV'][key] = os.environ[key]
457
458 try:
459 env.PrependENVPath(LD_LIBRARY_PATH_KEY, os.environ[LD_LIBRARY_PATH_KEY])
460 except KeyError:
461 pass
462
463 if IS_OSX:
464 try:
465 env.PrependENVPath('DYLD_LIBRARY_PATH', os.environ['DYLD_LIBRARY_PATH'])
466 except KeyError:
467 pass
468
469 try:
470 env['ENV']['PYTHONPATH'] = os.environ['PYTHONPATH']
471 except KeyError:
472 pass
473
474 ######################## Add some custom builders ############################
475
476 # Takes care of prefix and suffix for Python modules:
477 def build_python_module(env, target, source):
478 sl_suffix = '.pyd' if IS_WINDOWS else '.so'
479 return env.SharedLibrary(target, source, SHLIBPREFIX='', SHLIBSUFFIX=sl_suffix)
480 env.AddMethod(build_python_module, "PythonModule")
481
482 if env['pythoncmd']=='python':
483 py_builder = Builder(action = build_py, suffix = '.pyc', src_suffix = '.py', single_source=True)
484 else:
485 py_builder = Builder(action = env['pythoncmd']+" scripts/py_comp.py $SOURCE $TARGET", suffix = '.pyc', src_suffix = '.py', single_source=True)
486 env.Append(BUILDERS = {'PyCompile' : py_builder});
487
488 runUnitTest_builder = Builder(action = runUnitTest, suffix = '.passed', src_suffix=env['PROGSUFFIX'], single_source=True)
489 env.Append(BUILDERS = {'RunUnitTest' : runUnitTest_builder});
490
491 runPyUnitTest_builder = Builder(action = runPyUnitTest, suffix = '.passed', src_suffic='.py', single_source=True)
492 env.Append(BUILDERS = {'RunPyUnitTest' : runPyUnitTest_builder});
493
494 runPyExample_builder = Builder(action = runPyExample, suffix = '.passed', src_suffic='.py', single_source=True)
495 env.Append(BUILDERS = {'RunPyExample' : runPyExample_builder});
496
497 epstopdfbuilder = Builder(action = eps2pdf, suffix='.pdf', src_suffix='.eps', single_source=True)
498 env.Append(BUILDERS = {'EpsToPDF' : epstopdfbuilder});
499
500 ############################ Dependency checks ###############################
501
502 ######## Compiler
503 env=checkCompiler(env)
504
505 ######## Python headers & library (required)
506 env=checkPython(env)
507
508 ######## boost & boost-python (required)
509 env=checkBoost(env)
510
511 ######## numpy (required) and numpy headers (optional)
512 env=checkNumpy(env)
513
514 ######## CppUnit (required for tests)
515 env=checkCppUnit(env)
516
517 ######## optional python modules (sympy, pyproj)
518 env=checkOptionalModules(env)
519
520 ######## optional dependencies (netCDF, MKL, UMFPACK, MUMPS, Lapack, Silo, ...)
521 env=checkOptionalLibraries(env)
522
523 ######## PDFLaTeX (for documentation)
524 env=checkPDFLatex(env)
525
526 # set defaults for launchers if not otherwise specified
527 if env['prelaunch'] == 'default':
528 if env['mpi'] == 'INTELMPI' and env['openmp']:
529 env['prelaunch'] = "export I_MPI_PIN_DOMAIN=omp"
530 elif env['mpi'] == 'OPENMPI':
531 # transform comma-separated list to '-x a -x b -x c ...'
532 env['prelaunch'] = "EE=$(echo -x %e|sed -e 's/,/ -x /g')"
533 elif env['mpi'] == 'MPT':
534 env['prelaunch'] = "export MPI_NUM_MEMORY_REGIONS=0"
535 elif env['mpi'] == 'MPICH2':
536 env['prelaunch'] = "mpdboot -n %n -r ssh -f %f"
537 else:
538 env['prelaunch'] = ""
539
540 if env['launcher'] == 'default':
541 if env['mpi'] == 'INTELMPI':
542 env['launcher'] = "mpirun -hostfile %f -n %N -ppn %p %b"
543 elif env['mpi'] == 'OPENMPI':
544 if env['mpi_no_host']:
545 hostoptionstr=''
546 else:
547 hostoptionstr='--host %h'
548 # default to OpenMPI version 1.10 or higher
549 env['launcher'] = "mpirun ${AGENTOVERRIDE} --gmca mpi_warn_on_fork 0 ${EE} "+hostoptionstr+" --map-by node:pe=%t -bind-to core -np %N %b"
550 if 'orte_version' in env:
551 major,minor,point = [int(i) for i in env['orte_version'].split('.')]
552 if major == 1 and minor < 10:
553 env['launcher'] = "mpirun ${AGENTOVERRIDE} --gmca mpi_warn_on_fork 0 ${EE} "+hostoptionstr+" --cpus-per-rank %t -np %N %b"
554 elif env['mpi'] == 'MPT':
555 env['launcher'] = "mpirun %h -np %p %b"
556 elif env['mpi'] == 'MPICH':
557 env['launcher'] = "mpirun -machinefile %f -np %N %b"
558 elif env['mpi'] == 'MPICH2':
559 env['launcher'] = "mpiexec -genvlist %e -np %N %b"
560 else:
561 env['launcher'] = "%b"
562
563 if env['postlaunch'] == 'default':
564 if env['mpi'] == 'MPICH2':
565 env['postlaunch'] = "mpdallexit"
566 else:
567 env['postlaunch'] = ""
568
569 # dependency sanity checks
570
571 if len(env['domains']) == 0:
572 env['warnings'].append("No domains have been built, escript will not be very useful!")
573
574 # keep some of our install paths first in the list for the unit tests
575 env.PrependENVPath(LD_LIBRARY_PATH_KEY, env['libinstall'])
576 env.PrependENVPath('PYTHONPATH', prefix)
577 env['ENV']['ESCRIPT_ROOT'] = prefix
578
579 if not env['verbose']:
580 env['CXXCOMSTR'] = "Compiling $TARGET"
581 env['SHCXXCOMSTR'] = "Compiling $TARGET"
582 env['ARCOMSTR'] = "Linking $TARGET"
583 env['LINKCOMSTR'] = "Linking $TARGET"
584 env['SHLINKCOMSTR'] = "Linking $TARGET"
585 env['PDFLATEXCOMSTR'] = "Building $TARGET from LaTeX input $SOURCES"
586 env['BIBTEXCOMSTR'] = "Generating bibliography $TARGET"
587 env['MAKEINDEXCOMSTR'] = "Generating index $TARGET"
588 env['PDFLATEXCOMSTR'] = "Building $TARGET from LaTeX input $SOURCES"
589 #Progress(['Checking -\r', 'Checking \\\r', 'Checking |\r', 'Checking /\r'], interval=17)
590
591 ########################### Configure the targets ############################
592
593 from grouptest import GroupTest
594 TestGroups=[]
595
596 # keep an environment without warnings-as-errors
597 dodgy_env=env.Clone()
598
599 # now add warnings-as-errors flags. This needs to be done after configuration
600 # because the scons test files have warnings in them
601 if ((fatalwarning != '') and (env['werror'])):
602 env.Append(CCFLAGS = fatalwarning)
603
604 Export(
605 ['env',
606 'dodgy_env',
607 'IS_WINDOWS',
608 'TestGroups'
609 ]
610 )
611
612 target_init = env.Command(os.path.join(env['pyinstall'],'__init__.py'), None, Touch('$TARGET'))
613 env.Alias('target_init', [target_init])
614
615 # escript can't be turned off
616 build_all_list = ['build_escript']
617 install_all_list = ['target_init', 'install_escript']
618
619 if env['usempi']:
620 build_all_list += ['build_pythonMPI', 'build_overlord']
621 install_all_list += ['install_pythonMPI', 'install_overlord']
622
623 env['buildvars']['paso'] = int(env['paso'])
624 if env['paso']:
625 env.Append(CPPDEFINES = ['ESYS_HAVE_PASO'])
626 build_all_list += ['build_paso']
627 install_all_list += ['install_paso']
628
629 env['buildvars']['trilinos'] = int(env['trilinos'])
630 if env['trilinos']:
631 build_all_list += ['build_trilinoswrap']
632 install_all_list += ['install_trilinoswrap']
633
634 env['buildvars']['domains'] = ','.join(env['domains'])
635 for domain in env['domains']:
636 env.Append(CPPDEFINES = ['ESYS_HAVE_'+domain.upper()])
637 build_all_list += ['build_%s'%domain]
638 install_all_list += ['install_%s'%domain]
639
640 env['buildvars']['weipa'] = int(env['weipa'])
641 if env['weipa']:
642 env.Append(CPPDEFINES = ['ESYS_HAVE_WEIPA'])
643 build_all_list += ['build_weipa']
644 install_all_list += ['install_weipa']
645 if 'finley' in env['domains'] or 'dudley' in env['domains']:
646 build_all_list += ['build_escriptreader']
647 install_all_list += ['install_escriptreader']
648
649 variant='$BUILD_DIR/$PLATFORM/'
650 env.SConscript('escriptcore/SConscript', variant_dir=variant+'escriptcore', duplicate=0)
651 env.SConscript('escript/py_src/SConscript', variant_dir=variant+'escript', duplicate=0)
652 env.SConscript('pythonMPI/src/SConscript', variant_dir=variant+'pythonMPI', duplicate=0)
653 env.SConscript('tools/overlord/SConscript', variant_dir=variant+'tools/overlord', duplicate=0)
654 env.SConscript('paso/SConscript', variant_dir=variant+'paso', duplicate=0)
655 env.SConscript('trilinoswrap/SConscript', variant_dir=variant+'trilinoswrap', duplicate=0)
656 env.SConscript('cusplibrary/SConscript')
657 env.SConscript('dudley/SConscript', variant_dir=variant+'dudley', duplicate=0)
658 env.SConscript('finley/SConscript', variant_dir=variant+'finley', duplicate=0)
659 env.SConscript('ripley/SConscript', variant_dir=variant+'ripley', duplicate=0)
660 env.SConscript('speckley/SConscript', variant_dir=variant+'speckley', duplicate=0)
661 env.SConscript('weipa/SConscript', variant_dir=variant+'weipa', duplicate=0)
662 env.SConscript(dirs = ['downunder/py_src'], variant_dir=variant+'downunder', duplicate=0)
663 env.SConscript(dirs = ['modellib/py_src'], variant_dir=variant+'modellib', duplicate=0)
664 env.SConscript(dirs = ['pycad/py_src'], variant_dir=variant+'pycad', duplicate=0)
665 env.SConscript('tools/escriptconvert/SConscript', variant_dir=variant+'tools/escriptconvert', duplicate=0)
666 env.SConscript('doc/SConscript', variant_dir=variant+'doc', duplicate=0)
667
668 env.Alias('build', build_all_list)
669
670 install_all_list += ['install_downunder_py']
671 install_all_list += ['install_modellib_py']
672 install_all_list += ['install_pycad_py']
673 install_all_list += [env.Install(Dir('scripts',env['build_dir']), os.path.join('scripts', 'release_sanity.py'))]
674
675 if env['osx_dependency_fix']:
676 print("Require dependency fix")
677 install_all=env.Command('install', install_all_list, 'scripts/moveall.sh')
678 else:
679 install_all=env.Alias('install', install_all_list)
680
681 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')))
682 env.Depends('dummy', install_all)
683 if env['usempi']:
684 env.Depends('dummy', ['install_pythonMPI'])
685
686 # if all domains are built:
687 if env['domains'] == all_domains and env['insane'] == False:
688 env.AlwaysBuild('sanity')
689 env.Default('sanity')
690 else:
691 env.Default('install')
692
693 ################## Targets to build and run the test suite ###################
694
695 if not env['cppunit']:
696 test_msg = env.Command('.dummy.', None, '@echo "Cannot run C++ unit tests, CppUnit not found!";exit 1')
697 env.Alias('run_tests', test_msg)
698 env.Alias('build_tests', '')
699 env.Alias('run_tests', ['install'])
700 env.Alias('all_tests', ['install', 'run_tests', 'py_tests'])
701 env.Alias('build_full',['install','build_tests','build_py_tests'])
702 Requires('py_tests', 'install')
703
704 ##################### Targets to build the documentation #####################
705
706 env.Alias('pdfdocs',['user_pdf', 'install_pdf', 'cookbook_pdf', 'inversion_pdf'])
707 env.Alias('basedocs', ['pdfdocs','examples_tarfile', 'examples_zipfile', 'api_doxygen'])
708 env.Alias('docs', ['basedocs', 'sphinxdoc'])
709 env.Alias('release_prep', ['docs', 'install'])
710 env.Alias('release_prep_old', ['basedocs', 'api_epydoc', 'install'])
711
712 # The test scripts are always generated, this target allows us to
713 # generate the testscripts without doing a full build
714 env.Alias('testscripts',[])
715
716 generateTestScripts(env, TestGroups)
717
718 ######################## Populate the buildvars file #########################
719
720 write_buildvars(env)
721 # delete buildvars upon cleanup - target_init is default so use it
722 env.Clean('target_init', File('buildvars', env['libinstall']))
723
724 write_launcher(env)
725
726 # remove obsolete files
727 if not env['usempi']:
728 Execute(Delete(File(['pythonMPI','pythonMPIredirect'], env['libinstall'])))
729 Execute(Delete(File('escript-overlord', env['bininstall'])))
730
731 ######################## Summarize our environment ###########################
732 def print_summary():
733 d_list=[]
734 print("")
735 print("*** Config Summary (see config.log and <prefix>/lib/buildvars for details) ***")
736 print("Escript revision %s"%global_revision)
737 print(" Install prefix: %s"%env['prefix'])
738 print(" Python: %s (Version %s)"%(env['pythoncmd'],env['python_version']))
739 print(" boost: %s (Version %s)"%(env['boost_prefix'],env['boost_version']))
740 if env['have_boost_numpy'] is True:
741 print(" boost numpy: YES")
742 else:
743 print(" boost numpy: NO")
744 if env['trilinos']:
745 print(" trilinos: %s (Version %s)" % (env['trilinos_prefix'],env['trilinos_version']))
746 else:
747 print(" trilinos: NO")
748 if env['numpy_h']:
749 print(" numpy: YES (with headers)")
750 else:
751 print(" numpy: YES (without headers)")
752 if env['usempi']:
753 if 'orte_version' in env:
754 print(" MPI: %s (Version %s)"%(env['mpi'], env['orte_version']))
755 else:
756 print(" MPI: YES (flavour: %s)"%env['mpi'])
757 else:
758 d_list.append('mpi')
759 if env['parmetis']:
760 print(" ParMETIS: %s (Version %s)"%(env['parmetis_prefix'],env['parmetis_version']))
761 else:
762 d_list.append('parmetis')
763 if env['uselapack']:
764 print(" LAPACK: YES (flavour: %s)"%env['lapack'])
765 else:
766 d_list.append('lapack')
767 if env['gmshpy']:
768 gmshpy=" + python module"
769 else:
770 gmshpy=""
771 if env['gmsh']=='m':
772 print(" gmsh: YES, MPI-ENABLED"+gmshpy)
773 elif env['gmsh']=='s':
774 print(" gmsh: YES"+gmshpy)
775 else:
776 if env['gmshpy']:
777 print(" gmsh: python module only")
778 else:
779 d_list.append('gmsh')
780 if env['compressed_files']:
781 print(" gzip: YES")
782 else:
783 d_list.append('gzip')
784
785 solvers = []
786 direct = []
787 if env['paso']:
788 solvers.append('paso')
789 if env['mkl']:
790 direct.append('mkl')
791 if env['umfpack']:
792 direct.append('umfpack')
793 if env['mumps']:
794 direct.append('mumps')
795 else:
796 d_list.append('paso')
797 if env['trilinos']:
798 solvers.append('trilinos')
799 direct.append('trilinos')
800 else:
801 d_list.append('trilinos')
802
803 print(" Solver library: %s"%(", ".join(solvers)))
804 if len(direct) > 0:
805 print(" Direct solver: YES (%s)"%(", ".join(direct)))
806 else:
807 print(" Direct solver: NONE")
808 print(" domains: %s"%(", ".join(env['domains'])))
809 if env['netcdf']==4:
810 print(" netcdf: YES (4 + 3)")
811 elif env['netcdf']==3:
812 print(" netcdf: YES (3)")
813 else:
814 print(" netcdf: NO")
815 e_list=[]
816 for i in ('weipa','debug','openmp','cppunit','gdal','mkl',
817 'mumps','pyproj','scipy','silo','sympy','umfpack','visit'):
818 if env[i]: e_list.append(i)
819 else: d_list.append(i)
820
821 d_list += set(all_domains).difference(env['domains'])
822 for i in e_list:
823 print("%16s: YES"%i)
824 print("\n DISABLED features: %s"%(" ".join(sorted(d_list))))
825
826 if ((fatalwarning != '') and (env['werror'])):
827 print(" Treating warnings as errors")
828 else:
829 print(" NOT treating warnings as errors")
830 print("")
831 for w in env['warnings']:
832 print("WARNING: %s"%w)
833 if len(GetBuildFailures()):
834 print("\nERROR: build stopped due to errors\n")
835 else:
836 print("\nSUCCESS: build complete\n")
837
838 atexit.register(print_summary)

  ViewVC Help
Powered by ViewVC 1.1.26