/[escript]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6848 - (show annotations)
Thu Jul 4 06:33:52 2019 UTC (2 weeks, 3 days ago) by aellery
File size: 33686 byte(s)
Minor changes to the svn revision code in SConstruct.


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 BoolVariable('werror','Treat compiler warnings as errors', True),
84 BoolVariable('debug', 'Compile with debug flags', False),
85 BoolVariable('openmp', 'Compile parallel version using OpenMP', False),
86 ('omp_flags', 'OpenMP compiler flags', 'default'),
87 ('omp_ldflags', 'OpenMP linker flags', 'default'),
88 # Mandatory libraries
89 ('boost_prefix', 'Prefix/Paths of boost installation', default_prefix),
90 ('boost_libs', 'Boost libraries to link with', ['boost_python-mt']),
91 # Mandatory for tests
92 ('cppunit_prefix', 'Prefix/Paths of CppUnit installation', default_prefix),
93 ('cppunit_libs', 'CppUnit libraries to link with', ['cppunit']),
94 # Optional libraries and options
95 EnumVariable('mpi', 'Compile parallel version using MPI flavour', 'none', allowed_values=mpi_flavours),
96 ('mpi_prefix', 'Prefix/Paths of MPI installation', default_prefix),
97 ('mpi_libs', 'MPI shared libraries to link with', ['mpi']),
98 BoolVariable('use_gmsh', 'Enable gmsh, if available', True),
99 EnumVariable('netcdf', 'Enable netCDF file support', False, allowed_values=netcdf_flavours),
100 ('netcdf_prefix', 'Prefix/Paths of netCDF installation', default_prefix),
101 ('netcdf_libs', 'netCDF libraries to link with', 'DEFAULT'),
102 BoolVariable('parmetis', 'Enable ParMETIS (requires MPI)', False),
103 ('parmetis_prefix', 'Prefix/Paths of ParMETIS installation', default_prefix),
104 ('parmetis_libs', 'ParMETIS libraries to link with', ['parmetis', 'metis']),
105 BoolVariable('mkl', 'Enable the Math Kernel Library', False),
106 ('mkl_prefix', 'Prefix/Paths to MKL installation', default_prefix),
107 ('mkl_libs', 'MKL libraries to link with', ['mkl_solver','mkl_em64t','guide','pthread']),
108 BoolVariable('umfpack', 'Enable UMFPACK', False),
109 ('umfpack_prefix', 'Prefix/Paths to UMFPACK installation', default_prefix),
110 ('umfpack_libs', 'UMFPACK libraries to link with', ['umfpack']),
111 TristateVariable('lapack', 'Enable LAPACK', 'auto'),
112 ('lapack_prefix', 'Prefix/Paths to LAPACK installation', default_prefix),
113 ('lapack_libs', 'LAPACK libraries to link with', []),
114 BoolVariable('silo', 'Enable the Silo file format in weipa', False),
115 ('silo_prefix', 'Prefix/Paths to Silo installation', default_prefix),
116 ('silo_libs', 'Silo libraries to link with', ['siloh5', 'hdf5']),
117 BoolVariable('trilinos', 'Enable the Trilinos solvers', False),
118 ('trilinos_prefix', 'Prefix/Paths to Trilinos installation', default_prefix),
119 ('trilinos_libs', 'Trilinos libraries to link with', []),
120 BoolVariable('visit', 'Enable the VisIt simulation interface', False),
121 ('visit_prefix', 'Prefix/Paths to VisIt installation', default_prefix),
122 ('visit_libs', 'VisIt libraries to link with', ['simV2']),
123 ListVariable('domains', 'Which domains to build', 'all', all_domains),
124 BoolVariable('paso', 'Build Paso solver library', True),
125 BoolVariable('weipa', 'Build Weipa data export library', True),
126 ('mathjax_path', 'Path to MathJax.js file', 'default'),
127 # Advanced settings
128 ('launcher', 'Launcher command (e.g. mpirun)', 'default'),
129 ('prelaunch', 'Command to execute before launcher (e.g. mpdboot)', 'default'),
130 ('postlaunch', 'Command to execute after launcher (e.g. mpdexit)', 'default'),
131 #dudley_assemble_flags = -funroll-loops to actually do something
132 ('dudley_assemble_flags', 'compiler flags for some dudley optimisations', ''),
133 # To enable passing function pointers through python
134 BoolVariable('iknowwhatimdoing', 'Allow non-standard C', False),
135 # An option for specifying the compiler tools
136 ('tools_names', 'Compiler tools to use', ['default']),
137 ('env_export', 'Environment variables to be passed to tools',[]),
138 TristateVariable('forcelazy', 'For testing use only - set the default value for autolazy', 'auto'),
139 TristateVariable('forcecollres', 'For testing use only - set the default value for force resolving collective ops', 'auto'),
140 BoolVariable('build_shared', '(deprecated option, ignored)', True),
141 ('sys_libs', 'Extra libraries to link with', []),
142 ('escript_opts_version', 'Version of options file (do not specify on command line)'),
143 ('SVN_VERSION', 'Do not use from options file', -2),
144 ('pythoncmd', 'which python to compile with', sys.executable),
145 ('pythonlibname', 'Name of the python library to link. (This is found automatically for python2.X.)', ''),
146 ('pythonlibpath', 'Path to the python library. (You should not need to set this unless your python has moved)',''),
147 ('pythonincpath','Path to python include files. (You should not need to set this unless your python has moved',''),
148 BoolVariable('longindices', 'use long indices (for very large matrices)', False),
149 BoolVariable('compressed_files','Enables reading from compressed binary files', True),
150 ('compression_libs', 'Compression libraries to link with', ['boost_iostreams']),
151 BoolVariable('osx_dependency_fix', 'Fix dependencies for libraries to have absolute paths (OSX)', False),
152 BoolVariable('stdlocationisprefix', 'Set the prefix as escript root in the launcher', False),
153 BoolVariable('mpi_no_host', 'Do not specify --host in run-escript launcher (only OPENMPI)', False),
154 BoolVariable('insane', 'Instructs scons to not run a sanity check after compilation.', False)
155 )
156
157 ##################### Create environment and help text #######################
158
159 # Intel's compiler uses regular expressions improperly and emits a warning
160 # about failing to find the compilers. This warning can be safely ignored.
161
162 # PATH is needed so the compiler, linker and tools are found if they are not
163 # in default locations.
164 env = Environment(tools = ['default'], options = vars,
165 ENV = {'PATH': os.environ['PATH']})
166
167 # set the vars for clang
168 def mkclang(env):
169 env['CXX']='clang++'
170
171 if env['tools_names'] != ['default']:
172 zz=env['tools_names']
173 if 'clang' in zz:
174 zz.remove('clang')
175 zz.insert(0, mkclang)
176 env = Environment(tools = ['default'] + env['tools_names'], options = vars,
177 ENV = {'PATH' : os.environ['PATH']})
178
179 # Covert env['netcdf'] into one of False, 3, 4
180 # Also choose default values for libraries
181 pos1=netcdf_flavours.index('False')
182 pos2=netcdf_flavours.index('3')
183 mypos=netcdf_flavours.index(env['netcdf'])
184 if 0 <= mypos <=pos1:
185 env['netcdf']=0
186 elif pos1 < mypos <= pos2:
187 env['netcdf']=3
188 if env['netcdf_libs']=='DEFAULT':
189 env['netcdf_libs']=['netcdf_c++', 'netcdf']
190 else: # netcdf4
191 env['netcdf']=4
192 if env['netcdf_libs']=='DEFAULT':
193 env['netcdf_libs']=['netcdf_c++4']
194
195 if options_file:
196 opts_valid=False
197 if 'escript_opts_version' in env.Dictionary() and \
198 int(env['escript_opts_version']) >= REQUIRED_OPTS_VERSION:
199 opts_valid=True
200 if opts_valid:
201 print("Using options in %s." % options_file)
202 else:
203 print("\nOptions file %s" % options_file)
204 print("is outdated! Please update the file after reading scons/templates/README_FIRST")
205 print("and setting escript_opts_version to %d.\n"%REQUIRED_OPTS_VERSION)
206 Exit(1)
207
208 # Generate help text (scons -h)
209 Help(vars.GenerateHelpText(env))
210
211 # Check for superfluous options
212 if len(vars.UnknownVariables())>0:
213 for k in vars.UnknownVariables():
214 print("Unknown option '%s'" % k)
215 Exit(1)
216
217 if 'dudley' in env['domains']:
218 env['domains'].append('finley')
219
220 env['domains'] = sorted(set(env['domains']))
221
222 # create dictionary which will be populated with info for buildvars file
223 env['buildvars'] = {}
224 # create list which will be populated with warnings if there are any
225 env['warnings'] = []
226
227 #################### Make sure install directories exist #####################
228
229 env['BUILD_DIR'] = Dir(env['build_dir']).abspath
230 prefix = Dir(env['prefix']).abspath
231 env['buildvars']['prefix'] = prefix
232 env['incinstall'] = os.path.join(prefix, 'include')
233 env['bininstall'] = os.path.join(prefix, 'bin')
234 env['libinstall'] = os.path.join(prefix, 'lib')
235 env['pyinstall'] = os.path.join(prefix, 'esys')
236 if not os.path.isdir(env['bininstall']):
237 os.makedirs(env['bininstall'])
238 if not os.path.isdir(env['libinstall']):
239 os.makedirs(env['libinstall'])
240 if not os.path.isdir(env['pyinstall']):
241 os.makedirs(env['pyinstall'])
242
243 env.Append(CPPPATH = [env['incinstall']])
244 env.Append(LIBPATH = [env['libinstall']])
245
246 ################# Fill in compiler options if not set above ##################
247
248 if env['cxx'] != 'default':
249 env['CXX'] = env['cxx']
250
251 # default compiler/linker options
252 cc_flags = '-std=c++11'
253 cc_optim = ''
254 cc_debug = ''
255 omp_flags = ''
256 omp_ldflags = ''
257 fatalwarning = '' # switch to turn warnings into errors
258 sysheaderopt = '' # how to indicate that a header is a system header
259
260 # env['CC'] might be a full path
261 cc_name=os.path.basename(env['CXX'])
262
263 if cc_name == 'icpc':
264 # Intel compiler
265 # #1478: class "std::auto_ptr<...>" was declared deprecated
266 # #1875: offsetof applied to non-POD types is nonstandard (in boost)
267 # removed -std=c99 because icpc doesn't like it and we aren't using c anymore
268 cc_flags = "-std=c++11 -fPIC -w2 -wd1875 -wd1478 -Wno-unknown-pragmas"
269 cc_optim = "-Ofast -ftz -fno-alias -xCORE-AVX2 -ipo"
270 #cc_optim = "-Ofast -ftz -fno-alias -inline-level=2 -ipo -xCORE-AVX2"
271 #cc_optim = "-O2 -ftz -fno-alias -inline-level=2"
272 #cc_optim = "-O0 -ftz -fno-alias"
273 #cc_optim = "-O3 -ftz -fno-alias -inline-level=2 -ipo -xHost"
274 cc_debug = "-g -O0 -DDOASSERT -DDOPROF -DBOUNDS_CHECK -DSLOWSHARECHECK"
275 omp_flags = "-qopenmp"
276 omp_ldflags = "-qopenmp" # removing -openmp-report (which is deprecated) because the replacement outputs to a file
277 fatalwarning = "-Werror"
278 elif cc_name[:3] == 'g++':
279 # GNU C++ on any system
280 # note that -ffast-math is not used because it breaks isnan(),
281 # see mantis #691
282 cc_flags = "-std=c++11 -pedantic -Wall -fPIC -finline-functions"
283 cc_flags += " -Wno-unknown-pragmas -Wno-sign-compare -Wno-system-headers -Wno-long-long -Wno-strict-aliasing "
284 cc_flags += " --param=max-vartrack-size=100000000"
285 cc_optim = "-O3"
286 #max-vartrack-size: avoid vartrack limit being exceeded with escriptcpp.cpp
287 cc_debug = "-g3 -O0 -DDOASSERT -DDOPROF -DBOUNDS_CHECK -DSLOWSHARECHECK --param=max-vartrack-size=100000000"
288 #Removed because new netcdf doesn't seem to like it
289 #cc_debug += ' -D_GLIBCXX_DEBUG '
290 omp_flags = "-fopenmp"
291 omp_ldflags = "-fopenmp"
292 fatalwarning = "-Werror"
293 sysheaderopt = "-isystem"
294 elif cc_name == 'cl':
295 # Microsoft Visual C on Windows
296 cc_flags = "/EHsc /MD /GR /wd4068 /D_USE_MATH_DEFINES /DDLL_NETCDF"
297 cc_optim = "/O2 /Op /W3"
298 cc_debug = "/Od /RTCcsu /ZI /DBOUNDS_CHECK"
299 fatalwarning = "/WX"
300 elif cc_name == 'icl':
301 # Intel C on Windows
302 cc_flags = '/EHsc /GR /MD'
303 cc_optim = '/fast /Oi /W3 /Qssp /Qinline-factor- /Qinline-min-size=0 /Qunroll'
304 cc_debug = '/Od /RTCcsu /Zi /Y- /debug:all /Qtrapuv'
305 omp_flags = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
306 omp_ldflags = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
307 elif cc_name == 'clang++':
308 # Clang++ on any system
309 cc_flags = "-std=c++11 -Wall -fPIC -fdiagnostics-color=always "
310 cc_flags += "-Wno-unused-private-field -Wno-unknown-pragmas "
311 if env['trilinos'] is True:
312 cc_flags += "-Wno-unused-variable -Wno-exceptions -Wno-deprecated-declarations"
313 cc_optim = "-O3"
314 cc_debug = "-ggdb3 -O0 -fdiagnostics-fixit-info -pedantic "
315 cc_debug += "-DDOASSERT -DDOPROF -DBOUNDS_CHECK -DSLOWSHARECHECK "
316 omp_flags = "-fopenmp"
317 omp_ldflags = "-fopenmp"
318 fatalwarning = "-Werror"
319 sysheaderopt = "-isystem"
320
321 env['sysheaderopt']=sysheaderopt
322
323 # set defaults if not otherwise specified
324 if env['cc_flags'] == 'default': env['cc_flags'] = cc_flags
325 if env['cc_optim'] == 'default': env['cc_optim'] = cc_optim
326 if env['cc_debug'] == 'default': env['cc_debug'] = cc_debug
327 if env['omp_flags'] == 'default': env['omp_flags'] = omp_flags
328 if env['omp_ldflags'] == 'default': env['omp_ldflags'] = omp_ldflags
329 if env['cxx_extra'] != '': env.Append(CXXFLAGS = env['cxx_extra'])
330 if env['ld_extra'] != '': env.Append(LINKFLAGS = env['ld_extra'])
331
332 if env['longindices']:
333 if env['paso']:
334 env.Append(CPPDEFINES = ['ESYS_INDEXTYPE_LONG'])
335 else:
336 env['warnings'].append("The longindices feature requires paso!")
337
338 # set up the autolazy values
339 if env['forcelazy'] == 1:
340 env.Append(CPPDEFINES=['FAUTOLAZYON'])
341 elif env['forcelazy'] == 0:
342 env.Append(CPPDEFINES=['FAUTOLAZYOFF'])
343
344 # set up the collective resolve values
345 if env['forcecollres'] == 1:
346 env.Append(CPPDEFINES=['FRESCOLLECTON'])
347 elif env['forcecollres'] == 0:
348 env.Append(CPPDEFINES=['FRESCOLLECTOFF'])
349
350 # allow non-standard C if requested
351 if env['iknowwhatimdoing']:
352 env.Append(CPPDEFINES=['IKNOWWHATIMDOING'])
353
354 # Disable OpenMP if no flags provided
355 if env['openmp'] and env['omp_flags'] == '':
356 env['warnings'].append("OpenMP requested but no flags provided - disabling OpenMP!")
357 env['openmp'] = False
358
359 if env['openmp']:
360 env.Append(CCFLAGS = env['omp_flags'])
361 if env['omp_ldflags'] != '': env.Append(LINKFLAGS = env['omp_ldflags'])
362 else:
363 env['omp_flags']=''
364 env['omp_ldflags']=''
365
366 env['buildvars']['openmp']=int(env['openmp'])
367
368 # add debug/non-debug compiler flags
369 env['buildvars']['debug']=int(env['debug'])
370 if env['debug']:
371 env.Append(CCFLAGS = env['cc_debug'])
372 else:
373 env.Append(CCFLAGS = env['cc_optim'])
374
375 # always add cc_flags
376 env.Append(CCFLAGS = env['cc_flags'])
377
378 # add system libraries
379 env.AppendUnique(LIBS = env['sys_libs'])
380
381 # determine svn revision
382 global_revision=ARGUMENTS.get('SVN_VERSION', None)
383 if global_revision:
384 global_revision = re.sub(':.*', '', global_revision)
385 global_revision = re.sub('[^0-9]', '', global_revision)
386 if global_revision == '': global_revision='-2'
387 else:
388 # Get the global Subversion revision number for the getVersion() method
389 try:
390 global_revision = os.popen('svnversion -n .').read()
391 global_revision = re.sub(':.*', '', global_revision)
392 global_revision = re.sub('[^0-9]', '', global_revision)
393 if global_revision == '': global_revision='-2'
394 except:
395 global_revision = '-1'
396 env['svn_revision']=global_revision
397 env['buildvars']['svn_revision']=global_revision
398 env.Append(CPPDEFINES=['SVN_VERSION='+global_revision])
399
400 # If that failed, try to get the version number from the file svn_version
401 if global_revision=='-2' or global_revision=='-1':
402 try:
403 global_revision=str(os.popen('cat svn_version 2>/dev/null').read())
404 if global_revision[global_revision.__len__()-1] == '\n':
405 temp=global_revision[0:(global_revision.__len__()-1)]
406 else:
407 temp=global_revision
408 print("Using svn revision information from file. Got revision = %s" % temp)
409 except:
410 global_revision='-2'
411
412 if global_revision=='-2' or global_revision=='-1':
413 env['warnings'].append("Could not detect the svn revision number!")
414
415 env['IS_WINDOWS']=IS_WINDOWS
416 env['IS_OSX']=IS_OSX
417
418 ###################### Copy required environment vars ########################
419
420 # Windows doesn't use LD_LIBRARY_PATH but PATH instead
421 if IS_WINDOWS:
422 LD_LIBRARY_PATH_KEY='PATH'
423 env['ENV']['LD_LIBRARY_PATH']=''
424 else:
425 LD_LIBRARY_PATH_KEY='LD_LIBRARY_PATH'
426
427 env['LD_LIBRARY_PATH_KEY']=LD_LIBRARY_PATH_KEY
428
429 # the following env variables are exported for the unit tests
430
431 for key in 'OMP_NUM_THREADS', 'ESCRIPT_NUM_PROCS', 'ESCRIPT_NUM_NODES':
432 try:
433 env['ENV'][key] = os.environ[key]
434 except KeyError:
435 env['ENV'][key] = '1'
436
437 env_export=env['env_export']
438 env_export.extend(['ESCRIPT_NUM_THREADS','ESCRIPT_HOSTFILE','DISPLAY','XAUTHORITY','PATH','HOME','KMP_MONITOR_STACKSIZE','TMPDIR','TEMP','TMP','LD_PRELOAD'])
439
440 for key in set(env_export):
441 try:
442 env['ENV'][key] = os.environ[key]
443 except KeyError:
444 pass
445
446 for key in os.environ.keys():
447 if key.startswith("SLURM_"):
448 env['ENV'][key] = os.environ[key]
449
450 try:
451 env.PrependENVPath(LD_LIBRARY_PATH_KEY, os.environ[LD_LIBRARY_PATH_KEY])
452 except KeyError:
453 pass
454
455 if IS_OSX:
456 try:
457 env.PrependENVPath('DYLD_LIBRARY_PATH', os.environ['DYLD_LIBRARY_PATH'])
458 except KeyError:
459 pass
460
461 try:
462 env['ENV']['PYTHONPATH'] = os.environ['PYTHONPATH']
463 except KeyError:
464 pass
465
466 ######################## Add some custom builders ############################
467
468 # Takes care of prefix and suffix for Python modules:
469 def build_python_module(env, target, source):
470 return env.SharedLibrary(target, source, SHLIBPREFIX='', SHLIBSUFFIX='.so')
471 env.AddMethod(build_python_module, "PythonModule")
472
473 if env['pythoncmd']=='python':
474 py_builder = Builder(action = build_py, suffix = '.pyc', src_suffix = '.py', single_source=True)
475 else:
476 py_builder = Builder(action = env['pythoncmd']+" scripts/py_comp.py $SOURCE $TARGET", suffix = '.pyc', src_suffix = '.py', single_source=True)
477 env.Append(BUILDERS = {'PyCompile' : py_builder});
478
479 runUnitTest_builder = Builder(action = runUnitTest, suffix = '.passed', src_suffix=env['PROGSUFFIX'], single_source=True)
480 env.Append(BUILDERS = {'RunUnitTest' : runUnitTest_builder});
481
482 runPyUnitTest_builder = Builder(action = runPyUnitTest, suffix = '.passed', src_suffic='.py', single_source=True)
483 env.Append(BUILDERS = {'RunPyUnitTest' : runPyUnitTest_builder});
484
485 runPyExample_builder = Builder(action = runPyExample, suffix = '.passed', src_suffic='.py', single_source=True)
486 env.Append(BUILDERS = {'RunPyExample' : runPyExample_builder});
487
488 epstopdfbuilder = Builder(action = eps2pdf, suffix='.pdf', src_suffix='.eps', single_source=True)
489 env.Append(BUILDERS = {'EpsToPDF' : epstopdfbuilder});
490
491 ############################ Dependency checks ###############################
492
493 ######## Compiler
494 env=checkCompiler(env)
495
496 ######## Python headers & library (required)
497 env=checkPython(env)
498
499 ######## boost & boost-python (required)
500 env=checkBoost(env)
501
502 ######## numpy (required) and numpy headers (optional)
503 env=checkNumpy(env)
504
505 ######## CppUnit (required for tests)
506 env=checkCppUnit(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['trilinos']:
733 print(" trilinos: %s "%(env['trilinos_prefix']))
734 else:
735 print(" trilinos: NO")
736 if env['numpy_h']:
737 print(" numpy: YES (with headers)")
738 else:
739 print(" numpy: YES (without headers)")
740 if env['usempi']:
741 if 'orte_version' in env:
742 print(" MPI: %s (Version %s)"%(env['mpi'], env['orte_version']))
743 else:
744 print(" MPI: YES (flavour: %s)"%env['mpi'])
745 else:
746 d_list.append('mpi')
747 if env['parmetis']:
748 print(" ParMETIS: %s (Version %s)"%(env['parmetis_prefix'],env['parmetis_version']))
749 else:
750 d_list.append('parmetis')
751 if env['uselapack']:
752 print(" LAPACK: YES (flavour: %s)"%env['lapack'])
753 else:
754 d_list.append('lapack')
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