/[escript]/branches/pml/SConstruct
ViewVC logotype

Contents of /branches/pml/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6700 - (show annotations)
Tue Jun 26 03:26:46 2018 UTC (9 months, 3 weeks ago) by aellery
File size: 32980 byte(s)
Creating a new branch for PML

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

  ViewVC Help
Powered by ViewVC 1.1.26