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

Contents of /branches/complex/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26