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

Contents of /branches/clazy/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6511 - (show annotations)
Fri Mar 3 01:41:39 2017 UTC (2 years ago) by jfenwick
File size: 32713 byte(s)
For some experiments

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

  ViewVC Help
Powered by ViewVC 1.1.26