/[escript]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5450 - (show annotations)
Mon Feb 9 01:39:26 2015 UTC (4 years, 4 months ago) by sshaw
File size: 32751 byte(s)
Solving MPI gmsh invocation race conditions via network-IPC with the help of escript-overlord.
I, for one, welcome it.

1 ##############################################################################
2 #
3 # Copyright (c) 2003-2015 by University of Queensland
4 # http://www.uq.edu.au
5 #
6 # Primary Business: Queensland, Australia
7 # Licensed under the Open Software License version 3.0
8 # http://www.opensource.org/licenses/osl-3.0.php
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=202
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/os/")
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 lapack_flavours=('none', 'clapack', 'mkl')
58
59 vars = Variables(options_file, ARGUMENTS)
60 vars.AddVariables(
61 PathVariable('options_file', 'Path to options file', options_file, PathVariable.PathIsFile),
62 PathVariable('prefix', 'Installation prefix', Dir('#.').abspath, PathVariable.PathIsDirCreate),
63 PathVariable('build_dir', 'Top-level build directory', Dir('#/build').abspath, PathVariable.PathIsDirCreate),
64 BoolVariable('verbose', 'Output full compile/link lines', False),
65 # Compiler/Linker options
66 ('cxx', 'Path to C++ compiler', 'default'),
67 ('cc_flags', 'Base C++ compiler flags', 'default'),
68 ('cc_optim', 'Additional C++ flags for a non-debug build', 'default'),
69 ('cc_debug', 'Additional C++ flags for a debug build', 'default'),
70 ('cxx_extra', 'Extra C++ compiler flags', ''),
71 ('ld_extra', 'Extra linker flags', ''),
72 ('nvcc', 'Path to CUDA compiler', 'default'),
73 ('nvccflags', 'Base CUDA compiler flags', 'default'),
74 BoolVariable('werror','Treat compiler warnings as errors', True),
75 BoolVariable('debug', 'Compile with debug flags', False),
76 BoolVariable('openmp', 'Compile parallel version using OpenMP', False),
77 ('omp_flags', 'OpenMP compiler flags', 'default'),
78 ('omp_ldflags', 'OpenMP linker flags', 'default'),
79 # Mandatory libraries
80 ('boost_prefix', 'Prefix/Paths of boost installation', default_prefix),
81 ('boost_libs', 'Boost libraries to link with', ['boost_python-mt']),
82 # Mandatory for tests
83 ('cppunit_prefix', 'Prefix/Paths of CppUnit installation', default_prefix),
84 ('cppunit_libs', 'CppUnit libraries to link with', ['cppunit']),
85 # Optional libraries and options
86 EnumVariable('mpi', 'Compile parallel version using MPI flavour', 'none', allowed_values=mpi_flavours),
87 ('mpi_prefix', 'Prefix/Paths of MPI installation', default_prefix),
88 ('mpi_libs', 'MPI shared libraries to link with', ['mpi']),
89 BoolVariable('cuda', 'Enable GPU code with CUDA (requires thrust)', False),
90 ('cuda_prefix', 'Prefix/Paths to NVidia CUDA installation', default_prefix),
91 BoolVariable('netcdf', 'Enable netCDF file support', False),
92 ('netcdf_prefix', 'Prefix/Paths of netCDF installation', default_prefix),
93 ('netcdf_libs', 'netCDF libraries to link with', ['netcdf_c++', 'netcdf']),
94 BoolVariable('parmetis', 'Enable ParMETIS (requires MPI)', False),
95 ('parmetis_prefix', 'Prefix/Paths of ParMETIS installation', default_prefix),
96 ('parmetis_libs', 'ParMETIS libraries to link with', ['parmetis', 'metis']),
97 BoolVariable('mkl', 'Enable the Math Kernel Library', False),
98 ('mkl_prefix', 'Prefix/Paths to MKL installation', default_prefix),
99 ('mkl_libs', 'MKL libraries to link with', ['mkl_solver','mkl_em64t','guide','pthread']),
100 BoolVariable('umfpack', 'Enable UMFPACK', False),
101 ('umfpack_prefix', 'Prefix/Paths to UMFPACK installation', default_prefix),
102 ('umfpack_libs', 'UMFPACK libraries to link with', ['umfpack']),
103 BoolVariable('boomeramg', 'Enable BoomerAMG', False),
104 ('boomeramg_prefix', 'Prefix/Paths to BoomerAMG installation', default_prefix),
105 ('boomeramg_libs', 'BoomerAMG libraries to link with', ['boomeramg']),
106 EnumVariable('lapack', 'Set LAPACK flavour', 'none', allowed_values=lapack_flavours),
107 ('lapack_prefix', 'Prefix/Paths to LAPACK installation', default_prefix),
108 ('lapack_libs', 'LAPACK libraries to link with', []),
109 BoolVariable('silo', 'Enable the Silo file format in weipa', False),
110 ('silo_prefix', 'Prefix/Paths to Silo installation', default_prefix),
111 ('silo_libs', 'Silo libraries to link with', ['siloh5', 'hdf5']),
112 BoolVariable('visit', 'Enable the VisIt simulation interface', False),
113 ('visit_prefix', 'Prefix/Paths to VisIt installation', default_prefix),
114 ('visit_libs', 'VisIt libraries to link with', ['simV2']),
115 ListVariable('domains', 'Which domains to build', 'all',\
116 ['dudley','finley','ripley','speckley']),
117 # Advanced settings
118 ('launcher', 'Launcher command (e.g. mpirun)', 'default'),
119 ('prelaunch', 'Command to execute before launcher (e.g. mpdboot)', 'default'),
120 ('postlaunch', 'Command to execute after launcher (e.g. mpdexit)', 'default'),
121 #dudley_assemble_flags = -funroll-loops to actually do something
122 ('dudley_assemble_flags', 'compiler flags for some dudley optimisations', ''),
123 # To enable passing function pointers through python
124 BoolVariable('iknowwhatimdoing', 'Allow non-standard C', False),
125 # An option for specifying the compiler tools
126 ('tools_names', 'Compiler tools to use', ['default']),
127 ('env_export', 'Environment variables to be passed to tools',[]),
128 EnumVariable('forcelazy', 'For testing use only - set the default value for autolazy', 'leave_alone', allowed_values=('leave_alone', 'on', 'off')),
129 EnumVariable('forcecollres', 'For testing use only - set the default value for force resolving collective ops', 'leave_alone', allowed_values=('leave_alone', 'on', 'off')),
130 ('build_shared', 'Build dynamic libraries only', False),
131 ('sys_libs', 'Extra libraries to link with', []),
132 ('escript_opts_version', 'Version of options file (do not specify on command line)'),
133 ('SVN_VERSION', 'Do not use from options file', -2),
134 ('pythoncmd', 'which python to compile with','python'),
135 ('usepython3', 'Is this a python3 build? (experimental)', False),
136 ('pythonlibname', 'Name of the python library to link. (This is found automatically for python2.X.)', ''),
137 ('pythonlibpath', 'Path to the python library. (You should not need to set this unless your python has moved)',''),
138 ('pythonincpath','Path to python include files. (You should not need to set this unless your python has moved',''),
139 BoolVariable('longindices', 'use long indices (for very large matrices)', False),
140 BoolVariable('BADPYTHONMACROS','Extra \#include to get around a python bug.', True),
141 BoolVariable('compressed_files','Enables reading from compressed binary files', True),
142 ('compression_libs', 'Compression libraries to link with', ['boost_iostreams']),
143 BoolVariable('papi', 'Enable PAPI', False),
144 ('papi_prefix', 'Prefix/Paths to PAPI installation', default_prefix),
145 ('papi_libs', 'PAPI libraries to link with', ['papi']),
146 BoolVariable('papi_instrument_solver', 'Use PAPI to instrument each iteration of the solver', False)
147 )
148
149 ##################### Create environment and help text #######################
150
151 # Intel's compiler uses regular expressions improperly and emits a warning
152 # about failing to find the compilers. This warning can be safely ignored.
153
154 # PATH is needed so the compiler, linker and tools are found if they are not
155 # in default locations.
156 env = Environment(tools = ['default'], options = vars,
157 ENV = {'PATH': os.environ['PATH']})
158
159 # set the vars for clang
160 def mkclang(env):
161 env['CXX']='clang++'
162
163 if env['tools_names'] != ['default']:
164 zz=env['tools_names']
165 if 'clang' in zz:
166 zz.remove('clang')
167 zz.insert(0, mkclang)
168 env = Environment(tools = ['default'] + env['tools_names'], options = vars,
169 ENV = {'PATH' : os.environ['PATH']})
170
171 if options_file:
172 opts_valid=False
173 if 'escript_opts_version' in env.Dictionary() and \
174 int(env['escript_opts_version']) >= REQUIRED_OPTS_VERSION:
175 opts_valid=True
176 if opts_valid:
177 print("Using options in %s." % options_file)
178 else:
179 print("\nOptions file %s" % options_file)
180 print("is outdated! Please update the file by examining one of the TEMPLATE")
181 print("files in the scons/ subdirectory and setting escript_opts_version to %d.\n"%REQUIRED_OPTS_VERSION)
182 Exit(1)
183
184 # Generate help text (scons -h)
185 Help(vars.GenerateHelpText(env))
186
187 # Check for superfluous options
188 if len(vars.UnknownVariables())>0:
189 for k in vars.UnknownVariables():
190 print("Unknown option '%s'" % k)
191 Exit(1)
192
193 if env['cuda']:
194 if env['nvcc'] != 'default':
195 env['NVCC'] = env['nvcc']
196 env.Tool('nvcc')
197
198 if 'dudley' in env['domains']:
199 env['domains'].append('finley')
200
201 # create dictionary which will be populated with info for buildvars file
202 env['buildvars']={}
203 # create list which will be populated with warnings if there are any
204 env['warnings']=[]
205
206 #################### Make sure install directories exist #####################
207
208 env['BUILD_DIR']=Dir(env['build_dir']).abspath
209 prefix=Dir(env['prefix']).abspath
210 env['buildvars']['prefix']=prefix
211 env['incinstall'] = os.path.join(prefix, 'include')
212 env['bininstall'] = os.path.join(prefix, 'bin')
213 env['libinstall'] = os.path.join(prefix, 'lib')
214 env['pyinstall'] = os.path.join(prefix, 'esys')
215 if not os.path.isdir(env['bininstall']):
216 os.makedirs(env['bininstall'])
217 if not os.path.isdir(env['libinstall']):
218 os.makedirs(env['libinstall'])
219 if not os.path.isdir(env['pyinstall']):
220 os.makedirs(env['pyinstall'])
221
222 env.Append(CPPPATH = [env['incinstall']])
223 env.Append(LIBPATH = [env['libinstall']])
224
225 ################# Fill in compiler options if not set above ##################
226
227 if env['cxx'] != 'default': env['CXX']=env['cxx']
228
229 # version >=9 of intel C++ compiler requires use of icpc to link in C++
230 # runtimes (icc does not)
231 if not IS_WINDOWS and os.uname()[4]=='ia64' and env['CXX']=='icpc':
232 env['LINK'] = env['CXX']
233
234 # default compiler/linker options
235 cc_flags = ''
236 cc_optim = ''
237 cc_debug = ''
238 omp_flags = ''
239 omp_ldflags = ''
240 fatalwarning = '' # switch to turn warnings into errors
241 sysheaderopt = '' # how to indicate that a header is a system header
242
243 # env['CC'] might be a full path
244 cc_name=os.path.basename(env['CXX'])
245
246 if cc_name == 'icpc':
247 # Intel compiler
248 # #1875: offsetof applied to non-POD types is nonstandard (in boost)
249 # removed -std=c99 because icpc doesn't like it and we aren't using c anymore
250 cc_flags = "-fPIC -w2 -wd1875 -Wno-unknown-pragmas"
251 cc_optim = "-O3 -ftz -fno-alias -inline-level=2 -ipo -xHost"
252 cc_debug = "-g -O0 -DDOASSERT -DDOPROF -DBOUNDS_CHECK"
253 omp_flags = "-openmp"
254 omp_ldflags = "-openmp -openmp_report=1"
255 fatalwarning = "-Werror"
256 elif cc_name[:3] == 'g++':
257 # GNU C++ on any system
258 # note that -ffast-math is not used because it breaks isnan(),
259 # see mantis #691
260 cc_flags = "-pedantic -Wall -fPIC -Wno-unknown-pragmas -Wno-sign-compare -Wno-system-headers -Wno-long-long -Wno-strict-aliasing -finline-functions"
261 cc_optim = "-O3"
262 #max-vartrack-size: avoid vartrack limit being exceeded with escriptcpp.cpp
263 cc_debug = "-g3 -O0 -D_GLIBCXX_DEBUG -DDOASSERT -DDOPROF -DBOUNDS_CHECK --param=max-vartrack-size=100000000"
264 omp_flags = "-fopenmp"
265 omp_ldflags = "-fopenmp"
266 fatalwarning = "-Werror"
267 sysheaderopt = "-isystem"
268 elif cc_name == 'cl':
269 # Microsoft Visual C on Windows
270 cc_flags = "/EHsc /MD /GR /wd4068 /D_USE_MATH_DEFINES /DDLL_NETCDF"
271 cc_optim = "/O2 /Op /W3"
272 cc_debug = "/Od /RTCcsu /ZI /DBOUNDS_CHECK"
273 fatalwarning = "/WX"
274 elif cc_name == 'icl':
275 # Intel C on Windows
276 cc_flags = '/EHsc /GR /MD'
277 cc_optim = '/fast /Oi /W3 /Qssp /Qinline-factor- /Qinline-min-size=0 /Qunroll'
278 cc_debug = '/Od /RTCcsu /Zi /Y- /debug:all /Qtrapuv'
279 omp_flags = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
280 omp_ldflags = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
281
282 env['sysheaderopt']=sysheaderopt
283
284 # set defaults if not otherwise specified
285 if env['cc_flags'] == 'default': env['cc_flags'] = cc_flags
286 if env['cc_optim'] == 'default': env['cc_optim'] = cc_optim
287 if env['cc_debug'] == 'default': env['cc_debug'] = cc_debug
288 if env['omp_flags'] == 'default': env['omp_flags'] = omp_flags
289 if env['omp_ldflags'] == 'default': env['omp_ldflags'] = omp_ldflags
290 if env['cxx_extra'] != '': env.Append(CXXFLAGS = env['cxx_extra'])
291 if env['ld_extra'] != '': env.Append(LINKFLAGS = env['ld_extra'])
292
293 if env['nvccflags'] != 'default':
294 env['NVCCFLAGS'] = env['nvccflags']
295 env['SHNVCCFLAGS'] = env['nvccflags'] + ' -shared'
296
297 if env['BADPYTHONMACROS']:
298 env.Append(CPPDEFINES = ['BADPYTHONMACROS'])
299
300 if env['longindices']:
301 env.Append(CPPDEFINES = ['ESYS_INDEXTYPE_LONG'])
302
303 if env['usepython3']:
304 env.Append(CPPDEFINES=['ESPYTHON3'])
305
306 # set up the autolazy values
307 if env['forcelazy'] == 'on':
308 env.Append(CPPDEFINES=['FAUTOLAZYON'])
309 elif env['forcelazy'] == 'off':
310 env.Append(CPPDEFINES=['FAUTOLAZYOFF'])
311
312 # set up the collective resolve values
313 if env['forcecollres'] == 'on':
314 env.Append(CPPDEFINES=['FRESCOLLECTON'])
315 elif env['forcecollres'] == 'off':
316 env.Append(CPPDEFINES=['FRESCOLLECTOFF'])
317
318 # allow non-standard C if requested
319 if env['iknowwhatimdoing']:
320 env.Append(CPPDEFINES=['IKNOWWHATIMDOING'])
321
322 # Disable OpenMP if no flags provided
323 if env['openmp'] and env['omp_flags'] == '':
324 env['warnings'].append("OpenMP requested but no flags provided - disabling OpenMP!")
325 env['openmp'] = False
326
327 if env['openmp']:
328 env.Append(CCFLAGS = env['omp_flags'])
329 if env['omp_ldflags'] != '': env.Append(LINKFLAGS = env['omp_ldflags'])
330 else:
331 env['omp_flags']=''
332 env['omp_ldflags']=''
333
334 env['buildvars']['openmp']=int(env['openmp'])
335
336 # add debug/non-debug compiler flags
337 env['buildvars']['debug']=int(env['debug'])
338 if env['debug']:
339 env.Append(CCFLAGS = env['cc_debug'])
340 else:
341 env.Append(CCFLAGS = env['cc_optim'])
342
343 # always add cc_flags
344 env.Append(CCFLAGS = env['cc_flags'])
345
346 # add system libraries
347 env.AppendUnique(LIBS = env['sys_libs'])
348
349 # set defaults for launchers if not otherwise specified
350 if env['prelaunch'] == 'default':
351 if env['mpi'] == 'INTELMPI' and env['openmp']:
352 env['prelaunch'] = "export I_MPI_PIN_DOMAIN=omp"
353 elif env['mpi'] == 'OPENMPI':
354 # transform comma-separated list to '-x a -x b -x c ...'
355 env['prelaunch'] = "EE=$(echo -x %e|sed -e 's/,/ -x /g')"
356 elif env['mpi'] == 'MPT':
357 env['prelaunch'] = "export MPI_NUM_MEMORY_REGIONS=0"
358 elif env['mpi'] == 'MPICH2':
359 env['prelaunch'] = "mpdboot -n %n -r ssh -f %f"
360 else:
361 env['prelaunch'] = ""
362
363 if env['launcher'] == 'default':
364 if env['mpi'] == 'INTELMPI':
365 env['launcher'] = "mpirun -hostfile %f -n %N -ppn %p %b"
366 elif env['mpi'] == 'OPENMPI':
367 env['launcher'] = "mpirun --gmca mpi_warn_on_fork 0 ${EE} --host %h -bynode -bind-to-core --cpus-per-rank %t -np %N %b"
368 elif env['mpi'] == 'MPT':
369 env['launcher'] = "mpirun %h -np %p %b"
370 elif env['mpi'] == 'MPICH':
371 env['launcher'] = "mpirun -machinefile %f -np %N %b"
372 elif env['mpi'] == 'MPICH2':
373 env['launcher'] = "mpiexec -genvlist %e -np %N %b"
374 else:
375 env['launcher'] = "%b"
376
377 if env['postlaunch'] == 'default':
378 if env['mpi'] == 'MPICH2':
379 env['postlaunch'] = "mpdallexit"
380 else:
381 env['postlaunch'] = ""
382
383 # determine svn revision
384 global_revision=ARGUMENTS.get('SVN_VERSION', None)
385 if global_revision:
386 global_revision = re.sub(':.*', '', global_revision)
387 global_revision = re.sub('[^0-9]', '', global_revision)
388 if global_revision == '': global_revision='-2'
389 else:
390 # Get the global Subversion revision number for the getVersion() method
391 try:
392 global_revision = os.popen('svnversion -n .').read()
393 global_revision = re.sub(':.*', '', global_revision)
394 global_revision = re.sub('[^0-9]', '', global_revision)
395 if global_revision == '': global_revision='-2'
396 except:
397 global_revision = '-1'
398 env['svn_revision']=global_revision
399 env['buildvars']['svn_revision']=global_revision
400 env.Append(CPPDEFINES=['SVN_VERSION='+global_revision])
401
402 if IS_WINDOWS:
403 if not env['build_shared']:
404 env.Append(CPPDEFINES = ['ESYSUTILS_STATIC_LIB'])
405 env.Append(CPPDEFINES = ['PASO_STATIC_LIB'])
406
407 env['IS_WINDOWS']=IS_WINDOWS
408 env['IS_OSX']=IS_OSX
409
410 ###################### Copy required environment vars ########################
411
412 # Windows doesn't use LD_LIBRARY_PATH but PATH instead
413 if IS_WINDOWS:
414 LD_LIBRARY_PATH_KEY='PATH'
415 env['ENV']['LD_LIBRARY_PATH']=''
416 else:
417 LD_LIBRARY_PATH_KEY='LD_LIBRARY_PATH'
418
419 env['LD_LIBRARY_PATH_KEY']=LD_LIBRARY_PATH_KEY
420
421 # the following env variables are exported for the unit tests
422
423 for key in 'OMP_NUM_THREADS', 'ESCRIPT_NUM_PROCS', 'ESCRIPT_NUM_NODES':
424 try:
425 env['ENV'][key] = os.environ[key]
426 except KeyError:
427 env['ENV'][key] = '1'
428
429 env_export=env['env_export']
430 env_export.extend(['ESCRIPT_NUM_THREADS','ESCRIPT_HOSTFILE','DISPLAY','XAUTHORITY','PATH','HOME','KMP_MONITOR_STACKSIZE','TMPDIR','TEMP','TMP','LD_PRELOAD'])
431
432 for key in set(env_export):
433 try:
434 env['ENV'][key] = os.environ[key]
435 except KeyError:
436 pass
437
438 for key in os.environ.keys():
439 if key.startswith("SLURM_"):
440 env['ENV'][key] = os.environ[key]
441
442 try:
443 env.PrependENVPath(LD_LIBRARY_PATH_KEY, os.environ[LD_LIBRARY_PATH_KEY])
444 except KeyError:
445 pass
446
447 if IS_OSX:
448 try:
449 env.PrependENVPath('DYLD_LIBRARY_PATH', os.environ['DYLD_LIBRARY_PATH'])
450 except KeyError:
451 pass
452
453
454 # these shouldn't be needed
455 #for key in 'C_INCLUDE_PATH','CPLUS_INCLUDE_PATH','LIBRARY_PATH':
456 # try:
457 # env['ENV'][key] = os.environ[key]
458 # except KeyError:
459 # pass
460
461 try:
462 env['ENV']['PYTHONPATH'] = os.environ['PYTHONPATH']
463 except KeyError:
464 pass
465
466 ######################## Add some custom builders ############################
467
468 if env['pythoncmd']=='python':
469 py_builder = Builder(action = build_py, suffix = '.pyc', src_suffix = '.py', single_source=True)
470 else:
471 py_builder = Builder(action = env['pythoncmd']+" scripts/py_comp.py $SOURCE $TARGET", suffix = '.pyc', src_suffix = '.py', single_source=True)
472 env.Append(BUILDERS = {'PyCompile' : py_builder});
473
474 runUnitTest_builder = Builder(action = runUnitTest, suffix = '.passed', src_suffix=env['PROGSUFFIX'], single_source=True)
475 env.Append(BUILDERS = {'RunUnitTest' : runUnitTest_builder});
476
477 runPyUnitTest_builder = Builder(action = runPyUnitTest, suffix = '.passed', src_suffic='.py', single_source=True)
478 env.Append(BUILDERS = {'RunPyUnitTest' : runPyUnitTest_builder});
479
480 runPyExample_builder = Builder(action = runPyExample, suffix = '.passed', src_suffic='.py', single_source=True)
481 env.Append(BUILDERS = {'RunPyExample' : runPyExample_builder});
482
483 epstopdfbuilder = Builder(action = eps2pdf, suffix='.pdf', src_suffix='.eps', single_source=True)
484 env.Append(BUILDERS = {'EpsToPDF' : epstopdfbuilder});
485
486 ############################ Dependency checks ###############################
487
488 ######## Compiler
489 env=checkCompiler(env)
490
491 ######## Python headers & library (required)
492 env=checkPython(env)
493
494 ######## boost & boost-python (required)
495 env=checkBoost(env)
496
497 ######## NVCC version (optional)
498 if env['cuda']:
499 env=checkCudaVersion(env)
500 env=checkCUDA(env)
501
502 ######## numpy (required) and numpy headers (optional)
503 env=checkNumpy(env)
504
505 ######## CppUnit (required for tests)
506 env=checkCppUnit(env)
507
508 ######## optional python modules (sympy, pyproj)
509 env=checkOptionalModules(env)
510
511 ######## optional dependencies (netCDF, PAPI, MKL, UMFPACK, Lapack, Silo, ...)
512 env=checkOptionalLibraries(env)
513
514 #use gmsh info to set some defines
515 if env['gmsh'] == 's':
516 env.Append(CPPDEFINES=['GMSH'])
517 elif env['gmsh'] == 'm':
518 env.Append(CPPDEFINES=['GMSH','GMSH_MPI'])
519
520 ######## PDFLaTeX (for documentation)
521 env=checkPDFLatex(env)
522
523 # keep some of our install paths first in the list for the unit tests
524 env.PrependENVPath(LD_LIBRARY_PATH_KEY, env['libinstall'])
525 env.PrependENVPath('PYTHONPATH', prefix)
526 env['ENV']['ESCRIPT_ROOT'] = prefix
527
528 if not env['verbose']:
529 env['CXXCOMSTR'] = "Compiling $TARGET"
530 env['SHCXXCOMSTR'] = "Compiling $TARGET"
531 env['ARCOMSTR'] = "Linking $TARGET"
532 env['LINKCOMSTR'] = "Linking $TARGET"
533 env['SHLINKCOMSTR'] = "Linking $TARGET"
534 env['PDFLATEXCOMSTR'] = "Building $TARGET from LaTeX input $SOURCES"
535 env['BIBTEXCOMSTR'] = "Generating bibliography $TARGET"
536 env['MAKEINDEXCOMSTR'] = "Generating index $TARGET"
537 env['PDFLATEXCOMSTR'] = "Building $TARGET from LaTeX input $SOURCES"
538 #Progress(['Checking -\r', 'Checking \\\r', 'Checking |\r', 'Checking /\r'], interval=17)
539
540 ####################### Configure the subdirectories #########################
541
542 # remove obsolete files
543 if not env['usempi']:
544 Execute(Delete(os.path.join(env['libinstall'], 'pythonMPI')))
545 Execute(Delete(os.path.join(env['bininstall'], 'escript-overlord')))
546 Execute(Delete(os.path.join(env['libinstall'], 'pythonMPIredirect')))
547
548 from grouptest import *
549 TestGroups=[]
550
551 # keep an environment without warnings-as-errors
552 dodgy_env=env.Clone()
553
554 # now add warnings-as-errors flags. This needs to be done after configuration
555 # because the scons test files have warnings in them
556 if ((fatalwarning != '') and (env['werror'])):
557 env.Append(CCFLAGS = fatalwarning)
558
559 Export(
560 ['env',
561 'dodgy_env',
562 'IS_WINDOWS',
563 'TestGroups'
564 ]
565 )
566
567 #do not auto build
568 env.SConscript(dirs = ['tools/escriptconvert'], variant_dir='$BUILD_DIR/$PLATFORM/tools/escriptconvert', duplicate=0)
569 env.SConscript(dirs = ['tools/overlord'], variant_dir='$BUILD_DIR/$PLATFORM/tools/overlord', duplicate=0)
570 env.SConscript(dirs = ['paso/src'], variant_dir='$BUILD_DIR/$PLATFORM/paso', duplicate=0)
571 env.SConscript(dirs = ['weipa/src'], variant_dir='$BUILD_DIR/$PLATFORM/weipa', duplicate=0)
572 env.SConscript(dirs = ['escript/py_src'], variant_dir='$BUILD_DIR/$PLATFORM/escript', duplicate=0)
573
574 env.SConscript(dirs = ['cusplibrary'])
575
576 #This will pull in the escriptcore/py_src and escriptcore/test
577 env.SConscript(dirs = ['escriptcore/src'], variant_dir='$BUILD_DIR/$PLATFORM/escriptcore', duplicate=0)
578 env.SConscript(dirs = ['esysUtils/src'], variant_dir='$BUILD_DIR/$PLATFORM/esysUtils', duplicate=0)
579 env.SConscript(dirs = ['pasowrap/src'], variant_dir='$BUILD_DIR/$PLATFORM/pasowrap', duplicate=0)
580 if 'dudley' in env['domains']:
581 env.SConscript(dirs = ['dudley/src'], variant_dir='$BUILD_DIR/$PLATFORM/dudley', duplicate=0)
582 if 'finley' in env['domains']:
583 env.SConscript(dirs = ['finley/src'], variant_dir='$BUILD_DIR/$PLATFORM/finley', duplicate=0)
584 if 'ripley' in env['domains']:
585 env.SConscript(dirs = ['ripley/src'], variant_dir='$BUILD_DIR/$PLATFORM/ripley', duplicate=0)
586 if 'speckley' in env['domains']:
587 env.SConscript(dirs = ['speckley/src'], variant_dir='$BUILD_DIR/$PLATFORM/speckley', duplicate=0)
588 env.SConscript(dirs = ['downunder/py_src'], variant_dir='$BUILD_DIR/$PLATFORM/downunder', duplicate=0)
589 env.SConscript(dirs = ['modellib/py_src'], variant_dir='$BUILD_DIR/$PLATFORM/modellib', duplicate=0)
590 env.SConscript(dirs = ['pycad/py_src'], variant_dir='$BUILD_DIR/$PLATFORM/pycad', duplicate=0)
591 env.SConscript(dirs = ['pythonMPI/src'], variant_dir='$BUILD_DIR/$PLATFORM/pythonMPI', duplicate=0)
592 env.SConscript(dirs = ['doc'], variant_dir='$BUILD_DIR/$PLATFORM/doc', duplicate=0)
593 env.SConscript(dirs = ['paso/profiling'], variant_dir='$BUILD_DIR/$PLATFORM/paso/profiling', duplicate=0)
594
595
596 ######################## Populate the buildvars file #########################
597
598 write_buildvars(env)
599
600 write_launcher(env)
601
602 ################### Targets to build and install libraries ###################
603
604 target_init = env.Command(os.path.join(env['pyinstall'],'__init__.py'), None, Touch('$TARGET'))
605 env.Alias('target_init', [target_init])
606 # delete buildvars upon cleanup
607 env.Clean('target_init', os.path.join(env['libinstall'], 'buildvars'))
608
609 # The headers have to be installed prior to build in order to satisfy
610 # #include <paso/Common.h>
611 env.Alias('build_esysUtils', ['install_esysUtils_headers', 'build_esysUtils_lib'])
612 env.Alias('install_esysUtils', ['build_esysUtils', 'install_esysUtils_lib'])
613
614 env.Alias('build_paso', ['install_paso_headers', 'build_paso_lib'])
615 env.Alias('install_paso', ['build_paso', 'install_paso_lib'])
616
617 env.Alias('build_escript', ['install_escript_headers', 'build_escript_lib', 'build_escriptcpp_lib'])
618 env.Alias('install_escript', ['build_escript', 'install_escript_lib', 'install_escriptcpp_lib', 'install_escriptcore_py', 'install_escript_py'])
619
620 env.Alias('build_pasowrap', ['install_pasowrap_headers', 'build_pasowrap_lib', 'build_pasowrapcpp_lib'])
621 env.Alias('install_pasowrap', ['build_pasowrap', 'install_pasowrap_lib', 'install_pasowrapcpp_lib', 'install_pasowrap_py'])
622
623 if 'dudley' in env['domains']:
624 env.Alias('build_dudley', ['install_dudley_headers', 'build_dudley_lib', 'build_dudleycpp_lib'])
625 env.Alias('install_dudley', ['build_dudley', 'install_dudley_lib', 'install_dudleycpp_lib', 'install_dudley_py'])
626
627 if 'finley' in env['domains']:
628 env.Alias('build_finley', ['install_finley_headers', 'build_finley_lib', 'build_finleycpp_lib'])
629 env.Alias('install_finley', ['build_finley', 'install_finley_lib', 'install_finleycpp_lib', 'install_finley_py'])
630
631 if 'ripley' in env['domains']:
632 env.Alias('build_ripley', ['install_cusp_headers', 'install_ripley_headers', 'build_ripley_lib', 'build_ripleycpp_lib'])
633 env.Alias('install_ripley', ['build_ripley', 'install_ripley_lib', 'install_ripleycpp_lib', 'install_ripley_py'])
634
635 if 'speckley' in env['domains']:
636 env.Alias('build_speckley', ['install_speckley_headers', 'build_speckley_lib', 'build_speckleycpp_lib'])
637 env.Alias('install_speckley', ['build_speckley', 'install_speckley_lib', 'install_speckleycpp_lib', 'install_speckley_py'])
638
639 env.Alias('build_weipa', ['install_weipa_headers', 'build_weipa_lib', 'build_weipacpp_lib'])
640 env.Alias('install_weipa', ['build_weipa', 'install_weipa_lib', 'install_weipacpp_lib', 'install_weipa_py'])
641
642 env.Alias('build_escriptreader', ['install_weipa_headers', 'build_escriptreader_lib'])
643 env.Alias('install_escriptreader', ['build_escriptreader', 'install_escriptreader_lib'])
644
645 # Now gather all the above into some easy targets: build_all and install_all
646 build_all_list = []
647 build_all_list += ['build_esysUtils']
648 build_all_list += ['build_paso']
649 build_all_list += ['build_escript']
650 build_all_list += ['build_pasowrap']
651 if 'dudley' in env['domains']: build_all_list += ['build_dudley']
652 if 'finley' in env['domains']: build_all_list += ['build_finley']
653 if 'ripley' in env['domains']: build_all_list += ['build_ripley']
654 if 'speckley' in env['domains']: build_all_list += ['build_speckley']
655 build_all_list += ['build_weipa']
656 if not IS_WINDOWS and 'finley' in env['domains']:
657 build_all_list += ['build_escriptreader']
658 if env['usempi']:
659 build_all_list += ['build_pythonMPI', 'build_overlord']
660 env.Alias('build_all', build_all_list)
661
662 install_all_list = []
663 install_all_list += ['target_init']
664 install_all_list += ['install_esysUtils']
665 install_all_list += ['install_paso']
666 install_all_list += ['install_escript']
667 install_all_list += ['install_pasowrap']
668 if 'dudley' in env['domains']: install_all_list += ['install_dudley']
669 if 'finley' in env['domains']: install_all_list += ['install_finley']
670 if 'ripley' in env['domains']: install_all_list += ['install_ripley']
671 if 'speckley' in env['domains']: install_all_list += ['install_speckley']
672 install_all_list += ['install_weipa']
673 if not IS_WINDOWS and 'finley' in env['domains']:
674 install_all_list += ['install_escriptreader']
675 install_all_list += ['install_downunder_py']
676 install_all_list += ['install_modellib_py']
677 install_all_list += ['install_pycad_py']
678 if env['usempi']:
679 install_all_list += ['install_pythonMPI', 'install_overlord']
680 env.Alias('install_all', install_all_list)
681
682 # Default target is install
683 env.Default('install_all')
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_all'])
692 env.Alias('all_tests', ['install_all', 'run_tests', 'py_tests'])
693 env.Alias('build_full',['install_all','build_tests','build_py_tests'])
694 env.Alias('build_PasoTests','$BUILD_DIR/$PLATFORM/paso/profiling/PasoTests')
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_all'])
702 env.Alias('release_prep_old', ['basedocs', 'api_epydoc', 'install_all'])
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
712 ######################## Summarize our environment ###########################
713 def print_summary():
714 print("")
715 print("*** Config Summary (see config.log and <prefix>/lib/buildvars for details) ***")
716 print("Escript/Finley revision %s"%global_revision)
717 print(" Install prefix: %s"%env['prefix'])
718 print(" Python: %s"%sysconfig.PREFIX)
719 print(" boost: %s"%env['boost_prefix'])
720 if env['numpy_h']:
721 print(" numpy: YES (with headers)")
722 else:
723 print(" numpy: YES (without headers)")
724 if env['usempi']:
725 print(" MPI: YES (flavour: %s)"%env['mpi'])
726 else:
727 print(" MPI: NO")
728 if env['uselapack']:
729 print(" LAPACK: YES (flavour: %s)"%env['lapack'])
730 else:
731 print(" LAPACK: NO")
732 if env['cuda']:
733 print(" CUDA: YES (nvcc: %s)"%env['nvcc_version'])
734 else:
735 print(" CUDA: NO")
736 d_list=[]
737 e_list=[]
738 for i in 'debug','openmp','boomeramg','gdal','mkl','netcdf','papi','parmetis','pyproj','scipy','silo','sympy','umfpack','visit':
739 if env[i]: e_list.append(i)
740 else: d_list.append(i)
741 for i in e_list:
742 print("%16s: YES"%i)
743 for i in d_list:
744 print("%16s: NO"%i)
745 if env['cppunit']:
746 print(" CppUnit: YES")
747 else:
748 print(" CppUnit: NO")
749 if env['gmshpy']:
750 gmshpy=" + python module"
751 else:
752 gmshpy=""
753 if env['gmsh']=='m':
754 print(" gmsh: YES, MPI-ENABLED"+gmshpy)
755 elif env['gmsh']=='s':
756 print(" gmsh: YES"+gmshpy)
757 else:
758 if env['gmshpy']:
759 print(" gmsh: python module only")
760 else:
761 print(" gmsh: NO")
762 print( " gzip: " + ("YES" if env['compressed_files'] else "NO"))
763
764 if ((fatalwarning != '') and (env['werror'])):
765 print(" Treating warnings as errors")
766 else:
767 print(" NOT treating warnings as errors")
768 print("")
769 for w in env['warnings']:
770 print("WARNING: %s"%w)
771 if len(GetBuildFailures()):
772 print("\nERROR: build stopped due to errors\n")
773 else:
774 print("\nSUCCESS: build complete\n")
775
776 atexit.register(print_summary)
777

  ViewVC Help
Powered by ViewVC 1.1.26