/[escript]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6944 - (show annotations)
Thu Jan 30 03:39:44 2020 UTC (3 weeks, 5 days ago) by uqaeller
File size: 34000 byte(s)
Updated the install guide.

Also, added in a new option (disable_boost_numpy) which enables a user to disable the boost_numpy libraries (on by default) during the build.



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

  ViewVC Help
Powered by ViewVC 1.1.26