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

Diff of /branches/diaplayground/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 805 by gross, Thu Aug 10 06:09:02 2006 UTC revision 4249 by caltinay, Tue Feb 26 01:01:59 2013 UTC
# Line 1  Line 1 
1  #          Copyright 2006 by ACcESS MNRF                    ##############################################################################
 #                                                            
 #              http://www.access.edu.au                      
 #       Primary Business: Queensland, Australia              
 #  Licensed under the Open Software License version 3.0      
 #     http://www.opensource.org/licenses/osl-3.0.php        
 #                                                            
2  #  #
3    # Copyright (c) 2003-2013 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 since 2012 by School of Earth Sciences
12    #
13    ##############################################################################
14    
15    EnsureSConsVersion(0,98,1)
16    EnsurePythonVersion(2,5)
17    
18  # top-level Scons configuration file for all esys13 modules  import sys, os, platform, re
19  # Begin initialisation Section  from distutils import sysconfig
20  # all of this section just intialises default environments and helper  from site_init import *
21  # scripts. You shouldn't need to modify this section.  from subprocess import PIPE, Popen
22  EnsureSConsVersion(0,96,91)  
23  EnsurePythonVersion(2,3)  # Version number to check for in options file. Increment when new features are
24    # added or existing options changed.
25  # import tools:  REQUIRED_OPTS_VERSION=201
26  import glob  
27  import sys, os  # MS Windows support, many thanks to PH
28  # Add our extensions  IS_WINDOWS = (os.name == 'nt')
29  if sys.path.count('scons')==0: sys.path.append('scons')  
30  import scons_extensions  ########################## Determine options file ############################
31    # 1. command line
32  # check if UMFPACK is installed on the system:  # 2. scons/<hostname>_options.py
33  if os.path.isdir('/opt/UMFPACK/Include') and os.path.isdir('/opt/UMFPACK/Lib') and os.path.isdir('/opt/AMD/Lib'):  # 3. name as part of a cluster
34     umf_path_default='/opt/UMFPACK/Include'  options_file=ARGUMENTS.get('options_file', None)
35     umf_lib_path_default='/opt/UMFPACK/Lib'  if not options_file:
36     amd_lib_path_default='/opt/AMD/Lib'      ext_dir = os.path.join(os.getcwd(), 'scons')
37     umf_libs_default=['amd', 'umfpack']      hostname = platform.node().split('.')[0]
38  else:      for name in hostname, effectiveName(hostname):
39     umf_path_default=None          mangledhostname = re.sub('[^0-9a-zA-Z]', '_', hostname)
40     umf_lib_path_default=None          options_file = os.path.join(ext_dir, mangledhostname+'_options.py')
41     amd_lib_path_default=None          if os.path.isfile(options_file): break
42     umf_libs_default=None  
43  if os.path.isdir('/opt/GotoBLAS'):  if not os.path.isfile(options_file):
44     blas_path_default='/opt/GotoBLAS'      print("\nWARNING:\nOptions file %s" % options_file)
45     blas_lib_path_default='/opt/GotoBLAS'      print("not found! Default options will be used which is most likely suboptimal.")
46     blas_libs_default=['goto',]      print("It is recommended that you copy one of the TEMPLATE files in the scons/")
47  else:      print("subdirectory and customize it to your needs.\n")
48     blas_path_default=None      options_file = None
49     blas_lib_path_default=None  
50     blas_libs_default=None  ############################### Build options ################################
51  # Default options and options help text  
52  # These are defaults and can be overridden using command line arguments or an options file.  default_prefix='/usr'
53  # if the options_file or ARGUMENTS do not exist then the ones listed as default here are used  mpi_flavours=('no', 'none', 'MPT', 'MPICH', 'MPICH2', 'OPENMPI', 'INTELMPI')
54  # DO NOT CHANGE THEM HERE  lapack_flavours=('none', 'clapack', 'mkl')
55  if ARGUMENTS.get('options_file',0):  
56     options_file = ARGUMENTS.get('options_file',0)  vars = Variables(options_file, ARGUMENTS)
57  else:  vars.AddVariables(
58     import socket    PathVariable('options_file', 'Path to options file', options_file, PathVariable.PathIsFile),
59     from string import ascii_letters,digits    PathVariable('prefix', 'Installation prefix', Dir('#.').abspath, PathVariable.PathIsDirCreate),
60     hostname=""    PathVariable('build_dir', 'Top-level build directory', Dir('#/build').abspath, PathVariable.PathIsDirCreate),
61     for s in socket.gethostname().split('.')[0]:    BoolVariable('verbose', 'Output full compile/link lines', False),
62        if s in ascii_letters+digits:  # Compiler/Linker options
63           hostname+=s    ('cc', 'Path to C compiler', 'default'),
64        else:    ('cxx', 'Path to C++ compiler', 'default'),
65           hostname+="_"    ('cc_flags', 'Base C/C++ compiler flags', 'default'),
66     options_file = "scons/"+hostname+"_options.py"    ('cc_optim', 'Additional C/C++ flags for a non-debug build', 'default'),
67      ('cc_debug', 'Additional C/C++ flags for a debug build', 'default'),
68  opts = Options(options_file, ARGUMENTS)    ('cc_extra', 'Extra C compiler flags', ''),
69  opts.AddOptions(    ('cxx_extra', 'Extra C++ compiler flags', ''),
70  # Where to install esys stuff    ('ld_extra', 'Extra linker flags', ''),
71    ('incinstall', 'where the esys headers will be installed', Dir('#.').abspath+'/include'),    BoolVariable('werror','Treat compiler warnings as errors', True),
72    ('libinstall', 'where the esys libraries will be installed', Dir('#.').abspath+'/lib'),    BoolVariable('debug', 'Compile with debug flags', False),
73    ('pyinstall', 'where the esys python modules will be installed', Dir('#.').abspath),    BoolVariable('openmp', 'Compile parallel version using OpenMP', False),
74    ('src_zipfile', 'the source zip file will be installed.', Dir('#.').abspath+"/release/escript_src.zip"),    ('omp_flags', 'OpenMP compiler flags', 'default'),
75    ('test_zipfile', 'the test zip file will be installed.', Dir('#.').abspath+"/release/escript_tests.zip"),    ('omp_ldflags', 'OpenMP linker flags', 'default'),
76    ('src_tarfile', 'the source tar file will be installed.', Dir('#.').abspath+"/release/escript_src.tar.gz"),  # Mandatory libraries
77    ('test_tarfile', 'the test tar file will be installed.', Dir('#.').abspath+"/release/escript_tests.tar.gz"),    ('boost_prefix', 'Prefix/Paths of boost installation', default_prefix),
78    ('examples_tarfile', 'the examples tar file will be installed.', Dir('#.').abspath+"/release/doc/escript_examples.tar.gz"),    ('boost_libs', 'Boost libraries to link with', ['boost_python-mt']),
79    ('examples_zipfile', 'the examples zip file will be installed.', Dir('#.').abspath+"/release/doc/escript_examples.zip"),  # Mandatory for tests
80    ('guide_pdf', 'name of the user guide in pdf format', Dir('#.').abspath+"/release/doc/user/guide.pdf"),    ('cppunit_prefix', 'Prefix/Paths of CppUnit installation', default_prefix),
81    ('api_epydoc', 'name of the epydoc api docs directory',Dir('#.').abspath+"/release/doc/epydoc"),    ('cppunit_libs', 'CppUnit libraries to link with', ['cppunit']),
82    ('guide_html', 'name of the directory for user guide in html format', Dir('#.').abspath+"/release/doc/user/html"),  # Optional libraries and options
83  # Compilation options    EnumVariable('mpi', 'Compile parallel version using MPI flavour', 'none', allowed_values=mpi_flavours),
84    BoolOption('dodebug', 'Do you want a debug build?', 'no'),    ('mpi_prefix', 'Prefix/Paths of MPI installation', default_prefix),
85    ('options_file', "Optional file containing preferred options. Ignored if it doesn't exist (default: scons/hostname_options.py)", options_file),    ('mpi_libs', 'MPI shared libraries to link with', ['mpi']),
86    ('cc_defines','C/C++ defines to use', None),    BoolVariable('netcdf', 'Enable netCDF file support', False),
87    ('cc_flags','C compiler flags to use (Release build)', '-O3 -std=c99 -ffast-math -fpic -Wno-unknown-pragmas'),    ('netcdf_prefix', 'Prefix/Paths of netCDF installation', default_prefix),
88    ('cc_flags_debug', 'C compiler flags to use (Debug build)', '-g -O0 -ffast-math -std=c99 -fpic -Wno-unknown-pragmas'),    ('netcdf_libs', 'netCDF libraries to link with', ['netcdf_c++', 'netcdf']),
89    ('cxx_flags', 'C++ compiler flags to use (Release build)', '--no-warn -ansi'),    BoolVariable('parmetis', 'Enable ParMETIS (requires MPI)', False),
90    ('cxx_flags_debug', 'C++ compiler flags to use (Debug build)', '--no-warn -ansi -DDOASSERT -DDOPROF'),    ('parmetis_prefix', 'Prefix/Paths of ParMETIS installation', default_prefix),
91    ('cc_flags_MPI','C compiler flags to use (Release MPI build)', '-O3 -ftz -IPF_ftlacc- -IPF_fma -fno-alias -fno-alias -c99 -w1 -fpic -wd161'),    ('parmetis_libs', 'ParMETIS libraries to link with', ['parmetis', 'metis']),
92    ('cc_flags_debug_MPI', 'C compiler flags to use (Debug MPI build)', '-g -O0 -c99 -w1 -fpic -wd161'),    BoolVariable('papi', 'Enable PAPI', False),
93    ('cxx_flags_MPI', 'C++ compiler flags to use (Release MPI build)', '-ansi -wd1563 -wd161'),    ('papi_prefix', 'Prefix/Paths to PAPI installation', default_prefix),
94    ('cxx_flags_debug_MPI', 'C++ compiler flags to use (Debug MPI build)', '-ansi -DDOASSERT -DDOPROF -wd1563 -wd161'),    ('papi_libs', 'PAPI libraries to link with', ['papi']),
95    ('ar_flags', 'Static library archiver flags to use', None),    BoolVariable('papi_instrument_solver', 'Use PAPI to instrument each iteration of the solver', False),
96    ('sys_libs', 'System libraries to link with', None),    BoolVariable('mkl', 'Enable the Math Kernel Library', False),
97    ('tar_flags','flags for zip files','-c -z'),    ('mkl_prefix', 'Prefix/Paths to MKL installation', default_prefix),
98  # MKL    ('mkl_libs', 'MKL libraries to link with', ['mkl_solver','mkl_em64t','guide','pthread']),
99    PathOption('mkl_path', 'Path to MKL includes', None),    BoolVariable('umfpack', 'Enable UMFPACK', False),
100    PathOption('mkl_lib_path', 'Path to MKL libs', None),    ('umfpack_prefix', 'Prefix/Paths to UMFPACK installation', default_prefix),
101    ('mkl_libs', 'MKL libraries to link with', None),    ('umfpack_libs', 'UMFPACK libraries to link with', ['umfpack']),
102  # SCSL    BoolVariable('boomeramg', 'Enable BoomerAMG', False),
103    PathOption('scsl_path', 'Path to SCSL includes', None),    ('boomeramg_prefix', 'Prefix/Paths to BoomerAMG installation', default_prefix),
104    PathOption('scsl_lib_path', 'Path to SCSL libs', None),    ('boomeramg_libs', 'BoomerAMG libraries to link with', ['boomeramg']),
105    ('scsl_libs', 'SCSL libraries to link with', None),    EnumVariable('lapack', 'Set LAPACK flavour', 'none', allowed_values=lapack_flavours),
106    ('scsl_libs_MPI', 'SCSL libraries to link with for MPI build', None),    ('lapack_prefix', 'Prefix/Paths to LAPACK installation', default_prefix),
107  # UMFPACK    ('lapack_libs', 'LAPACK libraries to link with', []),
108    PathOption('umf_path', 'Path to UMF includes', umf_path_default),    BoolVariable('silo', 'Enable the Silo file format in weipa', False),
109    PathOption('umf_lib_path', 'Path to UMF libs', umf_lib_path_default),    ('silo_prefix', 'Prefix/Paths to Silo installation', default_prefix),
110    PathOption('amd_lib_path', 'Path to UMF libs', amd_lib_path_default),    ('silo_libs', 'Silo libraries to link with', ['siloh5', 'hdf5']),
111    ('umf_libs', 'UMF libraries to link with', umf_libs_default),    BoolVariable('visit', 'Enable the VisIt simulation interface', False),
112  # BLAS    ('visit_prefix', 'Prefix/Paths to VisIt installation', default_prefix),
113    PathOption('blas_path', 'Path to BLAS includes', blas_path_default),    ('visit_libs', 'VisIt libraries to link with', ['simV2']),
114    PathOption('blas_lib_path', 'Path to BLAS libs', blas_lib_path_default ),    BoolVariable('vsl_random', 'Use VSL from intel for random data', False),
115    ('blas_libs', 'BLAS libraries to link with', blas_libs_default ),  # Advanced settings
116  # Python    #dudley_assemble_flags = -funroll-loops      to actually do something
117  # locations of include files for python    ('dudley_assemble_flags', 'compiler flags for some dudley optimisations', ''),
118    PathOption('python_path', 'Path to Python includes', '/usr/include/python%s.%s'%(sys.version_info[0],sys.version_info[1])),    # To enable passing function pointers through python
119    PathOption('python_lib_path', 'Path to Python libs', '/usr/lib'),    BoolVariable('iknowwhatimdoing', 'Allow non-standard C', False),
120    ('python_lib', 'Python libraries to link with', ["python%s.%s"%(sys.version_info[0],sys.version_info[1]),]),    # An option for specifying the compiler tools (see windows branch)
121  # Boost    ('tools_names', 'Compiler tools to use', ['default']),
122    PathOption('boost_path', 'Path to Boost includes', '/usr/include'),    ('env_export', 'Environment variables to be passed to tools',[]),
123    PathOption('boost_lib_path', 'Path to Boost libs', '/usr/lib'),    EnumVariable('forcelazy', 'For testing use only - set the default value for autolazy', 'leave_alone', allowed_values=('leave_alone', 'on', 'off')),
124    ('boost_lib', 'Boost libraries to link with', ['boost_python',]),    EnumVariable('forcecollres', 'For testing use only - set the default value for force resolving collective ops', 'leave_alone', allowed_values=('leave_alone', 'on', 'off')),
125  # Doc building    # finer control over library building, intel aggressive global optimisation
126  #  PathOption('doxygen_path', 'Path to Doxygen executable', None),    # works with dynamic libraries on windows.
127  #  PathOption('epydoc_path', 'Path to Epydoc executable', None),    ('build_shared', 'Build dynamic libraries only', False),
128  # PAPI    ('sys_libs', 'Extra libraries to link with', []),
129    PathOption('papi_path', 'Path to PAPI includes', None),    ('escript_opts_version', 'Version of options file (do not specify on command line)'),
130    PathOption('papi_lib_path', 'Path to PAPI libs', None),    ('SVN_VERSION', 'Do not use from options file', -2),
131    ('papi_libs', 'PAPI libraries to link with', None),    ('pythoncmd', 'which python to compile with','python'),
132  # MPI    ('usepython3', 'Is this a python3 build? (experimental)', False),
133    BoolOption('useMPI', 'Compile parallel version using MPI', 'no'),    ('pythonlibname', 'Name of the python library to link. (This is found automatically for python2.X.)', ''),
134      ('pythonlibpath', 'Path to the python library. (You should not need to set this unless your python has moved)',''),
135      ('pythonincpath','Path to python include files. (You should not need to set this unless your python has moved',''),
136      BoolVariable('BADPYTHONMACROS','Extra \#include to get around a python bug.', True),
137  )  )
138    
139  # Initialise Scons Build Environment  ##################### Create environment and help text #######################
 # check for user environment variables we are interested in  
 try:  
    python_path = os.environ['PYTHONPATH']  
 except KeyError:  
    python_path = ''  
 try:  
    path = os.environ['PATH']  
 except KeyError:  
    path = ''  
 try:  
    ld_library_path = os.environ['LD_LIBRARY_PATH']  
 except KeyError:  
    ld_library_path = ''  
140    
141  # Note: On the Altix the intel compilers are not automatically  # Intel's compiler uses regular expressions improperly and emits a warning
142  # detected by scons intelc.py script. The Altix has a different directory  # about failing to find the compilers. This warning can be safely ignored.
 # path and in some locations the "modules" facility is used to support  
 # multiple compiler versions. This forces the need to import the users PATH  
 # environment which isn't the "scons way"  
 # This doesn't impact linux and windows which will use the default compiler (g++ or msvc, or the intel compiler if it is installed on both platforms)  
 # FIXME: Perhaps a modification to intelc.py will allow better support for ia64 on altix  
   
 if os.name != "nt" and os.uname()[4]=='ia64':  
    env = Environment(ENV = {'PATH':path}, tools = ['default', 'intelc'], options = opts)  
    env['ENV']['PATH'] = path  
    env['ENV']['LD_LIBRARY_PATH'] = ld_library_path  
    env['ENV']['PYTHONPATH'] = python_path  
    if env['CXX'] == 'icpc':  
       env['LINK'] = env['CXX'] # version >=9 of intel c++ compiler requires use of icpc to link in C++ runtimes (icc does not). FIXME: this behaviour could be directly incorporated into scons intelc.py  
 elif os.name == "nt":  
    env = Environment(tools = ['default', 'intelc'], options = opts)  
    env['ENV']['PYTHONPATH'] = python_path  
 else:  
    env = Environment(tools = ['default'], options = opts)  
    env['ENV']['PATH'] = path  
    env['ENV']['LD_LIBRARY_PATH'] = ld_library_path  
    env['ENV']['PYTHONPATH'] = python_path  
143    
144  # Setup help for options  # PATH is needed so the compiler, linker and tools are found if they are not
145  Help(opts.GenerateHelpText(env))  # in default locations.
146    env = Environment(tools = ['default'], options = vars,
147                      ENV = {'PATH': os.environ['PATH']})
148                      
149    
150    #set the vars for clang
151    def mkclang(env):
152      env['CC']='clang'
153      env['CXX']='clang++'
154                      
155                      
156    if env['tools_names'] != 'default':
157        zz=env['tools_names']
158        if 'clang' in zz:
159            zz.remove('clang')
160            zz.insert(0, mkclang)
161        env = Environment(tools = ['default'] + env['tools_names'], options = vars,
162                          ENV = {'PATH' : os.environ['PATH']})
163    
164    if options_file:
165        opts_valid=False
166        if 'escript_opts_version' in env.Dictionary() and \
167            int(env['escript_opts_version']) >= REQUIRED_OPTS_VERSION:
168                opts_valid=True
169        if opts_valid:
170            print("Using options in %s." % options_file)
171        else:
172            print("\nOptions file %s" % options_file)
173            print("is outdated! Please update the file by examining one of the TEMPLATE")
174            print("files in the scons/ subdirectory and setting escript_opts_version to %d.\n"%REQUIRED_OPTS_VERSION)
175            Exit(1)
176    
177    # Generate help text (scons -h)
178    Help(vars.GenerateHelpText(env))
179    
180    # Check for superfluous options
181    if len(vars.UnknownVariables())>0:
182        for k in vars.UnknownVariables():
183            print("Unknown option '%s'" % k)
184        Exit(1)
185    
186    #################### Make sure install directories exist #####################
187    
188    env['BUILD_DIR']=Dir(env['build_dir']).abspath
189    prefix=Dir(env['prefix']).abspath
190    env['incinstall'] = os.path.join(prefix, 'include')
191    env['bininstall'] = os.path.join(prefix, 'bin')
192    env['libinstall'] = os.path.join(prefix, 'lib')
193    env['pyinstall']  = os.path.join(prefix, 'esys')
194    if not os.path.isdir(env['bininstall']):
195        os.makedirs(env['bininstall'])
196    if not os.path.isdir(env['libinstall']):
197        os.makedirs(env['libinstall'])
198    if not os.path.isdir(env['pyinstall']):
199        os.makedirs(env['pyinstall'])
200    
201    env.Append(CPPPATH = [env['incinstall']])
202    env.Append(LIBPATH = [env['libinstall']])
203    
204    ################# Fill in compiler options if not set above ##################
205    
206    if env['cc'] != 'default': env['CC']=env['cc']
207    if env['cxx'] != 'default': env['CXX']=env['cxx']
208    
209    # version >=9 of intel C++ compiler requires use of icpc to link in C++
210    # runtimes (icc does not)
211    if not IS_WINDOWS and os.uname()[4]=='ia64' and env['CXX']=='icpc':
212        env['LINK'] = env['CXX']
213    
214    # default compiler/linker options
215    cc_flags = ''
216    cc_optim = ''
217    cc_debug = ''
218    omp_flags = ''
219    omp_ldflags = ''
220    fatalwarning = '' # switch to turn warnings into errors
221    sysheaderopt = '' # how to indicate that a header is a system header
222    
223    # env['CC'] might be a full path
224    cc_name=os.path.basename(env['CC'])
225    
226    if cc_name == 'icc':
227        # Intel compiler
228        # #1875: offsetof applied to non-POD types is nonstandard (in boost)
229        cc_flags    = "-std=c99 -fPIC -w2 -wd1875 -Wno-unknown-pragmas -DBLOCKTIMER -DCORE_ID1"
230        cc_optim    = "-O3 -ftz -fno-alias -ipo -xHost"
231        cc_debug    = "-g -O0 -DDOASSERT -DDOPROF -DBOUNDS_CHECK"
232        omp_flags   = "-openmp"
233        omp_ldflags = "-openmp -openmp_report=1"
234        fatalwarning = "-Werror"
235    elif cc_name[:3] == 'gcc':
236        # GNU C on any system
237        # note that -ffast-math is not used because it breaks isnan(),
238        # see mantis #691
239        cc_flags     = "-pedantic -Wall -fPIC -Wno-unknown-pragmas -DBLOCKTIMER  -Wno-sign-compare -Wno-system-headers -Wno-long-long -Wno-strict-aliasing -finline-functions"
240        cc_optim     = "-O3"
241        cc_debug     = "-g -O0 -DDOASSERT -DDOPROF -DBOUNDS_CHECK"
242        omp_flags    = "-fopenmp"
243        omp_ldflags  = "-fopenmp"
244        fatalwarning = "-Werror"
245        sysheaderopt = "-isystem"
246    elif cc_name == 'cl':
247        # Microsoft Visual C on Windows
248        cc_flags     = "/EHsc /MD /GR /wd4068 /D_USE_MATH_DEFINES /DDLL_NETCDF"
249        cc_optim     = "/O2 /Op /W3"
250        cc_debug     = "/Od /RTCcsu /ZI /DBOUNDS_CHECK"
251        fatalwarning = "/WX"
252    elif cc_name == 'icl':
253        # Intel C on Windows
254        cc_flags     = '/EHsc /GR /MD'
255        cc_optim     = '/fast /Oi /W3 /Qssp /Qinline-factor- /Qinline-min-size=0 /Qunroll'
256        cc_debug     = '/Od /RTCcsu /Zi /Y- /debug:all /Qtrapuv'
257        omp_flags    = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
258        omp_ldflags  = '/Qvec-report0 /Qopenmp /Qopenmp-report0 /Qparallel'
259    
260    # set defaults if not otherwise specified
261    if env['cc_flags']    == 'default': env['cc_flags'] = cc_flags
262    if env['cc_optim']    == 'default': env['cc_optim'] = cc_optim
263    if env['cc_debug']    == 'default': env['cc_debug'] = cc_debug
264    if env['omp_flags']   == 'default': env['omp_flags'] = omp_flags
265    if env['omp_ldflags'] == 'default': env['omp_ldflags'] = omp_ldflags
266    if env['cc_extra']  != '': env.Append(CFLAGS = env['cc_extra'])
267    if env['cxx_extra'] != '': env.Append(CXXFLAGS = env['cxx_extra'])
268    if env['ld_extra']  != '': env.Append(LINKFLAGS = env['ld_extra'])
269    
270    if env['BADPYTHONMACROS']: env.Append(CXXFLAGS = ' -DBADPYTHONMACROS')
271    
272    if env['usepython3']:
273        env.Append(CPPDEFINES=['ESPYTHON3'])
274    
275    # set up the autolazy values
276    if env['forcelazy'] == 'on':
277        env.Append(CPPDEFINES=['FAUTOLAZYON'])
278    elif env['forcelazy'] == 'off':
279        env.Append(CPPDEFINES=['FAUTOLAZYOFF'])
280    
281    # set up the collective resolve values
282    if env['forcecollres'] == 'on':
283        env.Append(CPPDEFINES=['FRESCOLLECTON'])
284    elif env['forcecollres'] == 'off':
285        env.Append(CPPDEFINES=['FRESCOLLECTOFF'])
286    
287    # allow non-standard C if requested
288    if env['iknowwhatimdoing']:
289        env.Append(CPPDEFINES=['IKNOWWHATIMDOING'])
290    
291    # Disable OpenMP if no flags provided
292    if env['openmp'] and env['omp_flags'] == '':
293       print("OpenMP requested but no flags provided - disabling OpenMP!")
294       env['openmp'] = False
295    
296    if env['openmp']:
297        env.Append(CCFLAGS = env['omp_flags'])
298        if env['omp_ldflags'] != '': env.Append(LINKFLAGS = env['omp_ldflags'])
299    else:
300        env['omp_flags']=''
301        env['omp_ldflags']=''
302    
303    # add debug/non-debug compiler flags
304    if env['debug']:
305        env.Append(CCFLAGS = env['cc_debug'])
306    else:
307        env.Append(CCFLAGS = env['cc_optim'])
308    
309    # always add cc_flags
310    env.Append(CCFLAGS = env['cc_flags'])
311    
312    # add system libraries
313    env.AppendUnique(LIBS = env['sys_libs'])
314    
 # Add some customer builders  
 py_builder = Builder(action = scons_extensions.build_py, suffix = '.pyc', src_suffix = '.py', single_source=True)  
 env.Append(BUILDERS = {'PyCompile' : py_builder});  
315    
316  if env['PLATFORM'] == "win32":  global_revision=ARGUMENTS.get('SVN_VERSION', None)
317     runUnitTest_builder = Builder(action = scons_extensions.runUnitTest, suffix = '.passed', src_suffix='.exe', single_source=True)  if global_revision:
318        global_revision = re.sub(':.*', '', global_revision)
319        global_revision = re.sub('[^0-9]', '', global_revision)
320        if global_revision == '': global_revision='-2'
321  else:  else:
322     runUnitTest_builder = Builder(action = scons_extensions.runUnitTest, suffix = '.passed', single_source=True)    # Get the global Subversion revision number for the getVersion() method
323  env.Append(BUILDERS = {'RunUnitTest' : runUnitTest_builder});    try:
324        global_revision = os.popen('svnversion -n .').read()
325        global_revision = re.sub(':.*', '', global_revision)
326        global_revision = re.sub('[^0-9]', '', global_revision)
327        if global_revision == '': global_revision='-2'
328      except:
329        global_revision = '-1'
330    env['svn_revision']=global_revision
331    env.Append(CPPDEFINES=['SVN_VERSION='+global_revision])
332    
333    if IS_WINDOWS:
334        if not env['build_shared']:
335            env.Append(CPPDEFINES = ['ESYSUTILS_STATIC_LIB'])
336            env.Append(CPPDEFINES = ['PASO_STATIC_LIB'])
337    
338    ###################### Copy required environment vars ########################
339    
340    # Windows doesn't use LD_LIBRARY_PATH but PATH instead
341    if IS_WINDOWS:
342        LD_LIBRARY_PATH_KEY='PATH'
343        env['ENV']['LD_LIBRARY_PATH']=''
344    else:
345        LD_LIBRARY_PATH_KEY='LD_LIBRARY_PATH'
346    
347  runPyUnitTest_builder = Builder(action = scons_extensions.runPyUnitTest, suffix = '.passed', src_suffic='.py', single_source=True)  # the following env variables are exported for the unit tests
 env.Append(BUILDERS = {'RunPyUnitTest' : runPyUnitTest_builder});  
348    
349  # Convert the options which are held in environment variable into python variables for ease of handling and configure compilation options  for key in 'OMP_NUM_THREADS', 'ESCRIPT_NUM_PROCS', 'ESCRIPT_NUM_NODES':
 try:  
    incinstall = env['incinstall']  
    env.Append(CPPPATH = [incinstall,])  
 except KeyError:  
    incinstall = None    
 try:  
    libinstall = env['libinstall']  
    env.Append(LIBPATH = [libinstall,])  
    env.PrependENVPath('LD_LIBRARY_PATH', libinstall)  
    if env['PLATFORM'] == "win32":  
       env.PrependENVPath('PATH', libinstall)  
       env.PrependENVPath('PATH', env['boost_lib_path'])  
 except KeyError:  
    libinstall = None    
 try:  
    pyinstall = env['pyinstall']+'/esys' # all targets will install into pyinstall/esys but PYTHONPATH points at straight pyinstall so you go import esys.escript etc  
    env.PrependENVPath('PYTHONPATH', env['pyinstall'])  
 except KeyError:  
    pyinstall = None    
 try:  
    dodebug = env['dodebug']  
 except KeyError:  
    dodebug = None    
 try:  
    useMPI = env['useMPI']  
 except KeyError:  
    useMPI = None    
 try:  
    cc_defines = env['cc_defines']  
    env.Append(CPPDEFINES = cc_defines)  
 except KeyError:  
    pass  
 if dodebug:  
   if useMPI:  
350      try:      try:
351        flags = env['cc_flags_debug_MPI']          env['ENV'][key] = os.environ[key]
       env.Append(CCFLAGS = flags)  
352      except KeyError:      except KeyError:
353        pass          env['ENV'][key] = 1
354    else:                        
355    env_export=env['env_export']
356    env_export.extend(['ESCRIPT_NUM_THREADS','ESCRIPT_HOSTFILE','DISPLAY','XAUTHORITY','PATH','HOME','KMP_MONITOR_STACKSIZE','TMPDIR','TEMP','TMP'])
357    
358    for key in set(env_export):
359      try:      try:
360        flags = env['cc_flags_debug']          env['ENV'][key] = os.environ[key]
       env.Append(CCFLAGS = flags)  
361      except KeyError:      except KeyError:
       pass  
 else:  
   if useMPI:  
    try:  
      flags = env['cc_flags_MPI']  
      env.Append(CCFLAGS = flags)  
    except KeyError:  
       pass  
   else:  
    try:  
       flags = env['cc_flags']  
       env.Append(CCFLAGS = flags)  
    except KeyError:  
       pass  
 if dodebug:  
    if useMPI:  
      try:  
         flags = env['cxx_flags_debug_MPI']  
         env.Append(CXXFLAGS = flags)  
      except KeyError:  
         pass  
    else:  
      try:  
         flags = env['cxx_flags_debug']  
         env.Append(CXXFLAGS = flags)  
      except KeyError:  
         pass  
 else:  
    if useMPI:  
      try:  
         flags = env['cxx_flags_MPI']  
         env.Append(CXXFLAGS = flags)  
      except KeyError:  
362          pass          pass
    else:  
      try:  
         flags = env['cxx_flags']  
         env.Append(CXXFLAGS = flags)  
      except KeyError:  
         pass  
 try:  
    flags = env['ar_flags']  
    env.Append(ARFLAGS = flags)  
 except KeyError:  
    ar_flags = None    
 try:  
    sys_libs = env['sys_libs']  
 except KeyError:  
    sys_libs = ''  
363    
364  try:  try:
365     tar_flags = env['tar_flags']      env.PrependENVPath(LD_LIBRARY_PATH_KEY, os.environ[LD_LIBRARY_PATH_KEY])
    env.Replace(TARFLAGS = tar_flags)  
366  except KeyError:  except KeyError:
367     pass      pass
368    
369  try:  # these shouldn't be needed
370     includes = env['mkl_path']  #for key in 'C_INCLUDE_PATH','CPLUS_INCLUDE_PATH','LIBRARY_PATH':
371     env.Append(CPPPATH = [includes,])  #    try:
372  except KeyError:  #        env['ENV'][key] = os.environ[key]
373     pass  #    except KeyError:
374    #        pass
375    
376  try:  try:
377     lib_path = env['mkl_lib_path']      env['ENV']['PYTHONPATH'] = os.environ['PYTHONPATH']
    env.Append(LIBPATH = [lib_path,])  
378  except KeyError:  except KeyError:
379     pass      pass
380    
381  try:  ######################## Add some custom builders ############################
    mkl_libs = env['mkl_libs']  
 except KeyError:  
    mkl_libs = ''  
 try:  
    includes = env['scsl_path']  
    env.Append(CPPPATH = [includes,])  
 except KeyError:  
    pass  
 try:  
    lib_path = env['scsl_lib_path']  
    env.Append(LIBPATH = [lib_path,])  
 except KeyError:  
    pass  
 if useMPI:    
   try:  
     scsl_libs = env['scsl_libs_MPI']  
   except KeyError:  
     scsl_libs = ''  
 else:          
   try:  
     scsl_libs = env['scsl_libs']  
   except KeyError:  
     scsl_libs = ''  
382    
383  try:  if env['pythoncmd']=='python':
384     includes = env['umf_path']      py_builder = Builder(action = build_py, suffix = '.pyc', src_suffix = '.py', single_source=True)
385     env.Append(CPPPATH = [includes,])  else:
386  except KeyError:      py_builder = Builder(action = env['pythoncmd']+" scripts/py_comp.py $SOURCE $TARGET", suffix = '.pyc', src_suffix = '.py', single_source=True)
387     pass  env.Append(BUILDERS = {'PyCompile' : py_builder});
388    
389  try:  runUnitTest_builder = Builder(action = runUnitTest, suffix = '.passed', src_suffix=env['PROGSUFFIX'], single_source=True)
390     lib_path = env['umf_lib_path']  env.Append(BUILDERS = {'RunUnitTest' : runUnitTest_builder});
    env.Append(LIBPATH = [lib_path,])  
 except KeyError:  
    pass  
391    
392  try:  runPyUnitTest_builder = Builder(action = runPyUnitTest, suffix = '.passed', src_suffic='.py', single_source=True)
393     lib_path = env['amd_lib_path']  env.Append(BUILDERS = {'RunPyUnitTest' : runPyUnitTest_builder});
    env.Append(LIBPATH = [lib_path,])  
 except KeyError:  
    pass  
394    
395  try:  epstopdfbuilder = Builder(action = eps2pdf, suffix='.pdf', src_suffix='.eps', single_source=True)
396     umf_libs = env['umf_libs']  env.Append(BUILDERS = {'EpsToPDF' : epstopdfbuilder});
 except KeyError:  
    umf_libs = ''  
397    
398  try:  ############################ Dependency checks ###############################
    includes = env['blas_path']  
    env.Append(CPPPATH = [includes,])  
 except KeyError:  
    pass  
 try:  
    lib_path = env['blas_lib_path']  
    env.Append(LIBPATH = [lib_path,])  
 except KeyError:  
    pass  
 try:  
    blas_libs = env['blas_libs']  
 except KeyError:  
    blas_libs = ''  
399    
400  try:  # Create a Configure() environment to check for compilers and python
401     includes = env['boost_path']  conf = Configure(env.Clone())
    env.Append(CPPPATH = [includes,])  
 except KeyError:  
    pass  
 try:  
    lib_path = env['boost_lib_path']  
    env.Append(LIBPATH = [lib_path,])  
 except KeyError:  
    pass  
 try:  
    boost_lib = env['boost_lib']  
 except KeyError:  
    boost_lib = None    
 try:  
    includes = env['python_path']  
    env.Append(CPPPATH = [includes,])  
 except KeyError:  
    pass  
 try:  
    lib_path = env['python_lib_path']  
    env.Append(LIBPATH = [lib_path,])  
 except KeyError:  
    pass  
 try:  
    python_lib = env['python_lib']  
 except KeyError:  
    python_lib = None    
 try:  
    doxygen_path = env['doxygen_path']  
 except KeyError:  
    doxygen_path = None    
 try:  
    epydoc_path = env['epydoc_path']  
 except KeyError:  
    epydoc_path = None    
 try:  
    includes = env['papi_path']  
    env.Append(CPPPATH = [includes,])  
 except KeyError:  
    pass  
 try:  
    lib_path = env['papi_lib_path']  
    env.Append(LIBPATH = [lib_path,])  
 except KeyError:  
    pass  
 try:  
    papi_libs = env['papi_libs']  
 except KeyError:  
    papi_libs = None    
402    
403    ######## Test that the compilers work
404    
405    if 'CheckCC' in dir(conf): # exists since scons 1.1.0
406        if not conf.CheckCC():
407            print("Cannot run C compiler '%s' (check config.log)" % (env['CC']))
408            Exit(1)
409        if not conf.CheckCXX():
410            print("Cannot run C++ compiler '%s' (check config.log)" % (env['CXX']))
411            Exit(1)
412    else:
413        if not conf.CheckFunc('printf', language='c'):
414            print("Cannot run C compiler '%s' (check config.log)" % (env['CC']))
415            Exit(1)
416        if not conf.CheckFunc('printf', language='c++'):
417            print("Cannot run C++ compiler '%s' (check config.log)" % (env['CXX']))
418            Exit(1)
419    
420    if conf.CheckFunc('gethostname'):
421        conf.env.Append(CPPDEFINES = ['HAVE_GETHOSTNAME'])
422    
423    ######## Python headers & library (required)
424    
425    #First we check to see if the config file has specified
426    ##Where to find the filae. Ideally, this should be automatic
427    #But we need to deal with the case where python is not in its INSTALL
428    #Directory
429    # Use the python scons is running
430    if env['pythoncmd']=='python':
431        python_inc_path=sysconfig.get_python_inc()
432        if IS_WINDOWS:
433            python_lib_path=os.path.join(sysconfig.get_config_var('prefix'), 'libs')
434        elif env['PLATFORM']=='darwin':
435            python_lib_path=sysconfig.get_config_var('LIBPL')
436        else:
437            python_lib_path=sysconfig.get_config_var('LIBDIR')
438    
439        #python_libs=[sysconfig.get_config_var('LDLIBRARY')] # only on linux
440        if IS_WINDOWS:
441            python_libs=['python%s%s'%(sys.version_info[0], sys.version_info[1])]
442        else:
443            python_libs=['python'+sysconfig.get_python_version()]
444    
445  try:  #if we want to use a python other than the one scons is running
446     src_zipfile = env.File(env['src_zipfile'])  else:
447  except KeyError:      initstring='from __future__ import print_function;from distutils import sysconfig;'
448     src_zipfile = None        if env['pythonlibname']!='':
449  try:          python_libs=env['pythonlibname']
450     test_zipfile = env.File(env['test_zipfile'])      else:   # work it out by calling python    
451  except KeyError:          if IS_WINDOWS:
452     test_zipfile = None                cmd='print("python%s%s"%(sys.version_info[0], sys.version_info[1]))'
453  try:          else:
454     examples_zipfile = env.File(env['examples_zipfile'])              cmd='print("python"+sysconfig.get_python_version())'
455  except KeyError:          p=Popen([env['pythoncmd'], '-c', initstring+cmd], stdout=PIPE)
456     examples_zipfile = None            python_libs=p.stdout.readline()
457            if env['usepython3']:       # This is to convert unicode str into py2 string
458                python_libs=python_libs.encode() # If scons runs on py3 then this must be rethought
459            p.wait()
460            python_libs=python_libs.strip()
461    
462  try:    
463     src_tarfile = env.File(env['src_tarfile'])      # Now we know whether we are using python3 or not
464  except KeyError:      p=Popen([env['pythoncmd'], '-c',  initstring+'print(sysconfig.get_python_inc())'], stdout=PIPE)
465     src_tarfile = None        python_inc_path=p.stdout.readline()
466  try:      if env['usepython3']:
467     test_tarfile = env.File(env['test_tarfile'])           python_inc_path=python_inc_path.encode()
468  except KeyError:      p.wait()  
469     test_tarfile = None        python_inc_path=python_inc_path.strip()
470  try:      if IS_WINDOWS:
471     examples_tarfile = env.File(env['examples_tarfile'])          cmd="os.path.join(sysconfig.get_config_var('prefix'), 'libs')"
472  except KeyError:      elif env['PLATFORM']=='darwin':
473     examples_tarfile = None            cmd="sysconfig.get_config_var(\"LIBPL\")"
474        else:
475            cmd="sysconfig.get_config_var(\"LIBDIR\")"
476    
477        p=Popen([env['pythoncmd'], '-c', initstring+'print('+cmd+')'], stdout=PIPE)
478        python_lib_path=p.stdout.readline()
479        if env['usepython3']:
480            python_lib_path=python_lib_path.decode()
481        p.wait()
482        python_lib_path=python_lib_path.strip()
483    
484    #Check for an override from the config file.
485    #Ideally, this should be automatic
486    #But we need to deal with the case where python is not in its INSTALL
487    #Directory
488    if env['pythonlibpath']!='':
489        python_lib_path=env['pythonlibpath']
490    
491  try:  if env['pythonincpath']!='':
492     guide_pdf = env.File(env['guide_pdf'])      python_inc_path=env['pythonincpath']
 except KeyError:  
    guide_pdf = None    
493    
 try:  
    guide_html_index = env.File('index.htm',env['guide_html'])  
 except KeyError:  
    guide_html_index = None    
494    
495  try:  if sysheaderopt == '':
496     api_epydoc = env.Dir(env['api_epydoc'])      conf.env.AppendUnique(CPPPATH = [python_inc_path])
497  except KeyError:  else:
498     api_epydoc = None        conf.env.Append(CCFLAGS = [sysheaderopt, python_inc_path])
499    
500    conf.env.AppendUnique(LIBPATH = [python_lib_path])
501    conf.env.AppendUnique(LIBS = python_libs)
502    # The wrapper script needs to find the libs
503    conf.env.PrependENVPath(LD_LIBRARY_PATH_KEY, python_lib_path)
504    
505    if not conf.CheckCHeader('Python.h'):
506        print("Cannot find python include files (tried 'Python.h' in directory %s)" % (python_inc_path))
507        Exit(1)
508    if not conf.CheckFunc('Py_Exit'):
509        print("Cannot find python library method Py_Main (tried %s in directory %s)" % (python_libs, python_lib_path))
510        Exit(1)
511    
512    ## reuse conf to check for numpy header (optional)
513    if env['usepython3']:
514        # FIXME: This is until we can work out how to make the checks in python 3
515        conf.env['numpy_h']=False
516    else:
517        if conf.CheckCXXHeader(['Python.h','numpy/ndarrayobject.h']):
518            conf.env.Append(CPPDEFINES = ['HAVE_NUMPY_H'])
519            conf.env['numpy_h']=True
520        else:
521            conf.env['numpy_h']=False
522    
523    # Commit changes to environment
524    env = conf.Finish()
525    
526    ######## boost (required)
527    
528    boost_inc_path,boost_lib_path=findLibWithHeader(env, env['boost_libs'], 'boost/python.hpp', env['boost_prefix'], lang='c++')
529    if sysheaderopt == '':
530        env.AppendUnique(CPPPATH = [boost_inc_path])
531    else:
532        # This is required because we can't -isystem /usr/include since it breaks
533        # std includes
534        if os.path.normpath(boost_inc_path) == '/usr/include':
535            conf.env.Append(CCFLAGS=[sysheaderopt, os.path.join(boost_inc_path,'boost')])
536        else:
537            env.Append(CCFLAGS=[sysheaderopt, boost_inc_path])
538    
539    env.AppendUnique(LIBPATH = [boost_lib_path])
540    env.AppendUnique(LIBS = env['boost_libs'])
541    env.PrependENVPath(LD_LIBRARY_PATH_KEY, boost_lib_path)
542    
543    ######## numpy (required)
544    
545    if not detectModule(env, 'numpy'):
546        print("Cannot import numpy. If it is installed try setting your PYTHONPATH and probably %s"%LD_LIBRARY_PATH_KEY)
547        Exit(1)
548    
549    ######## CppUnit (required for tests)
550    
551    try:
552        cppunit_inc_path,cppunit_lib_path=findLibWithHeader(env, env['cppunit_libs'], 'cppunit/TestFixture.h', env['cppunit_prefix'], lang='c++')
553        env.AppendUnique(CPPPATH = [cppunit_inc_path])
554        env.AppendUnique(LIBPATH = [cppunit_lib_path])
555        env.PrependENVPath(LD_LIBRARY_PATH_KEY, cppunit_lib_path)
556        env['cppunit']=True
557    except:
558        env['cppunit']=False
559    
560    ######## sympy (optional)
561    
562    if detectModule(env, 'sympy'):
563        env['sympy'] = True
564    else:
565        print("Cannot import sympy. Symbolic toolbox and nonlinear PDEs will not be available.")
566        env['sympy'] = False
567    
568    ######## pyproj (optional)
569    
570    if detectModule(env, 'pyproj'):
571        env['pyproj'] = True
572    else:
573        print("Cannot import pyproj. Inversions may not work.")
574        env['pyproj'] = False
575    
576    ######## netCDF (optional)
577    
578    netcdf_inc_path=''
579    netcdf_lib_path=''
580    if env['netcdf']:
581        netcdf_inc_path,netcdf_lib_path=findLibWithHeader(env, env['netcdf_libs'], 'netcdf.h', env['netcdf_prefix'], lang='c++')
582        env.AppendUnique(CPPPATH = [netcdf_inc_path])
583        env.AppendUnique(LIBPATH = [netcdf_lib_path])
584        env.AppendUnique(LIBS = env['netcdf_libs'])
585        env.PrependENVPath(LD_LIBRARY_PATH_KEY, netcdf_lib_path)
586        env.Append(CPPDEFINES = ['USE_NETCDF'])
587    
588    ######## PAPI (optional)
589    
590    papi_inc_path=''
591    papi_lib_path=''
592    if env['papi']:
593        papi_inc_path,papi_lib_path=findLibWithHeader(env, env['papi_libs'], 'papi.h', env['papi_prefix'], lang='c')
594        env.AppendUnique(CPPPATH = [papi_inc_path])
595        env.AppendUnique(LIBPATH = [papi_lib_path])
596        env.AppendUnique(LIBS = env['papi_libs'])
597        env.PrependENVPath(LD_LIBRARY_PATH_KEY, papi_lib_path)
598        env.Append(CPPDEFINES = ['BLOCKPAPI'])
599    
600    ######## MKL (optional)
601    
602    mkl_inc_path=''
603    mkl_lib_path=''
604    if env['mkl']:
605        mkl_inc_path,mkl_lib_path=findLibWithHeader(env, env['mkl_libs'], 'mkl_solver.h', env['mkl_prefix'], lang='c')
606        env.AppendUnique(CPPPATH = [mkl_inc_path])
607        env.AppendUnique(LIBPATH = [mkl_lib_path])
608        env.AppendUnique(LIBS = env['mkl_libs'])
609        env.PrependENVPath(LD_LIBRARY_PATH_KEY, mkl_lib_path)
610        env.Append(CPPDEFINES = ['MKL'])
611    
612    ######## UMFPACK (optional)
613    
614    umfpack_inc_path=''
615    umfpack_lib_path=''
616    if env['umfpack']:
617        umfpack_inc_path,umfpack_lib_path=findLibWithHeader(env, env['umfpack_libs'], 'umfpack.h', env['umfpack_prefix'], lang='c')
618        env.AppendUnique(CPPPATH = [umfpack_inc_path])
619        env.AppendUnique(LIBPATH = [umfpack_lib_path])
620        env.AppendUnique(LIBS = env['umfpack_libs'])
621        env.PrependENVPath(LD_LIBRARY_PATH_KEY, umfpack_lib_path)
622        env.Append(CPPDEFINES = ['UMFPACK'])
623    
624    ######## LAPACK (optional)
625    
626    if env['lapack']=='mkl' and not env['mkl']:
627        print("mkl_lapack requires MKL!")
628        Exit(1)
629    
630    env['uselapack'] = env['lapack']!='none'
631    lapack_inc_path=''
632    lapack_lib_path=''
633    if env['uselapack']:
634        header='clapack.h'
635        if env['lapack']=='mkl':
636            env.AppendUnique(CPPDEFINES = ['MKL_LAPACK'])
637            header='mkl_lapack.h'
638        lapack_inc_path,lapack_lib_path=findLibWithHeader(env, env['lapack_libs'], header, env['lapack_prefix'], lang='c')
639        env.AppendUnique(CPPPATH = [lapack_inc_path])
640        env.AppendUnique(LIBPATH = [lapack_lib_path])
641        env.AppendUnique(LIBS = env['lapack_libs'])
642        env.Append(CPPDEFINES = ['USE_LAPACK'])
643    
644    ######## Silo (optional)
645    
646    silo_inc_path=''
647    silo_lib_path=''
648    if env['silo']:
649        silo_inc_path,silo_lib_path=findLibWithHeader(env, env['silo_libs'], 'silo.h', env['silo_prefix'], lang='c')
650        env.AppendUnique(CPPPATH = [silo_inc_path])
651        env.AppendUnique(LIBPATH = [silo_lib_path])
652        # Note that we do not add the libs since they are only needed for the
653        # weipa library and tools.
654        #env.AppendUnique(LIBS = [env['silo_libs']])
655    
656    ######## VSL random numbers (optional)
657    if env['vsl_random']:
658        env.Append(CPPDEFINES = ['MKLRANDOM'])
659    
660    ######## VisIt (optional)
661    
662    visit_inc_path=''
663    visit_lib_path=''
664    if env['visit']:
665        visit_inc_path,visit_lib_path=findLibWithHeader(env, env['visit_libs'], 'VisItControlInterface_V2.h', env['visit_prefix'], lang='c')
666        env.AppendUnique(CPPPATH = [visit_inc_path])
667        env.AppendUnique(LIBPATH = [visit_lib_path])
668    
669    ######## MPI (optional)
670    
671    if env['mpi']=='no':
672        env['mpi']='none'
673    
674    env['usempi'] = env['mpi']!='none'
675    mpi_inc_path=''
676    mpi_lib_path=''
677    if env['usempi']:
678        mpi_inc_path,mpi_lib_path=findLibWithHeader(env, env['mpi_libs'], 'mpi.h', env['mpi_prefix'], lang='c')
679        env.AppendUnique(CPPPATH = [mpi_inc_path])
680        env.AppendUnique(LIBPATH = [mpi_lib_path])
681        env.AppendUnique(LIBS = env['mpi_libs'])
682        env.PrependENVPath(LD_LIBRARY_PATH_KEY, mpi_lib_path)
683        env.Append(CPPDEFINES = ['ESYS_MPI', 'MPI_NO_CPPBIND', 'MPICH_IGNORE_CXX_SEEK'])
684        # NetCDF 4.1 defines MPI_Comm et al. if MPI_INCLUDED is not defined!
685        # On the other hand MPT and OpenMPI don't define the latter so we have to
686        # do that here
687        if env['netcdf'] and env['mpi'] in ['MPT','OPENMPI']:
688            env.Append(CPPDEFINES = ['MPI_INCLUDED'])
689    
690    ######## BOOMERAMG (optional)
691    
692    if env['mpi'] == 'none': env['boomeramg'] = False
693    
694    boomeramg_inc_path=''
695    boomeramg_lib_path=''
696    if env['boomeramg']:
697        boomeramg_inc_path,boomeramg_lib_path=findLibWithHeader(env, env['boomeramg_libs'], 'HYPRE.h', env['boomeramg_prefix'], lang='c')
698        env.AppendUnique(CPPPATH = [boomeramg_inc_path])
699        env.AppendUnique(LIBPATH = [boomeramg_lib_path])
700        env.AppendUnique(LIBS = env['boomeramg_libs'])
701        env.PrependENVPath(LD_LIBRARY_PATH_KEY, boomeramg_lib_path)
702        env.Append(CPPDEFINES = ['BOOMERAMG'])
703    
704    ######## ParMETIS (optional)
705    
706    if not env['usempi']: env['parmetis'] = False
707    
708    parmetis_inc_path=''
709    parmetis_lib_path=''
710    if env['parmetis']:
711        parmetis_inc_path,parmetis_lib_path=findLibWithHeader(env, env['parmetis_libs'], 'parmetis.h', env['parmetis_prefix'], lang='c')
712        env.AppendUnique(CPPPATH = [parmetis_inc_path])
713        env.AppendUnique(LIBPATH = [parmetis_lib_path])
714        env.AppendUnique(LIBS = env['parmetis_libs'])
715        env.PrependENVPath(LD_LIBRARY_PATH_KEY, parmetis_lib_path)
716        env.Append(CPPDEFINES = ['USE_PARMETIS'])
717    
718    ######## gmsh (optional, for tests)
719    
720    try:
721        p=Popen(['gmsh', '-info'], stderr=PIPE)
722        _,e=p.communicate()
723        if e.split().count("MPI"):
724            env['gmsh']='m'
725        else:
726            env['gmsh']='s'
727    except OSError:
728        env['gmsh']=False
729    
730    ######## PDFLaTeX (for documentation)
731    if 'PDF' in dir(env) and '.tex' in env.PDF.builder.src_suffixes(env):
732        env['pdflatex']=True
733    else:
734        env['pdflatex']=False
735    
736    ######################## Summarize our environment ###########################
737    
738    # keep some of our install paths first in the list for the unit tests
739    env.PrependENVPath(LD_LIBRARY_PATH_KEY, env['libinstall'])
740    env.PrependENVPath('PYTHONPATH', prefix)
741    env['ENV']['ESCRIPT_ROOT'] = prefix
742    
743    if not env['verbose']:
744        env['CCCOMSTR'] = "Compiling $TARGET"
745        env['CXXCOMSTR'] = "Compiling $TARGET"
746        env['SHCCCOMSTR'] = "Compiling $TARGET"
747        env['SHCXXCOMSTR'] = "Compiling $TARGET"
748        env['ARCOMSTR'] = "Linking $TARGET"
749        env['LINKCOMSTR'] = "Linking $TARGET"
750        env['SHLINKCOMSTR'] = "Linking $TARGET"
751        env['PDFLATEXCOMSTR'] = "Building $TARGET from LaTeX input $SOURCES"
752        env['BIBTEXCOMSTR'] = "Generating bibliography $TARGET"
753        env['MAKEINDEXCOMSTR'] = "Generating index $TARGET"
754        env['PDFLATEXCOMSTR'] = "Building $TARGET from LaTeX input $SOURCES"
755        #Progress(['Checking -\r', 'Checking \\\r', 'Checking |\r', 'Checking /\r'], interval=17)
756    
757    print("")
758    print("*** Config Summary (see config.log and lib/buildvars for details) ***")
759    print("Escript/Finley revision %s"%global_revision)
760    print("  Install prefix:  %s"%env['prefix'])
761    print("          Python:  %s"%sysconfig.PREFIX)
762    print("           boost:  %s"%env['boost_prefix'])
763    print("           numpy:  YES")
764    if env['usempi']:
765        print("             MPI:  YES (flavour: %s)"%env['mpi'])
766    else:
767        print("             MPI:  DISABLED")
768    if env['uselapack']:
769        print("          LAPACK:  YES (flavour: %s)"%env['lapack'])
770    else:
771        print("          LAPACK:  DISABLED")
772    d_list=[]
773    e_list=[]
774    for i in 'debug','openmp','boomeramg','mkl','netcdf','papi','parmetis','pyproj','silo','sympy','umfpack','visit','vsl_random':
775        if env[i]: e_list.append(i)
776        else: d_list.append(i)
777    for i in e_list:
778        print("%16s:  YES"%i)
779    for i in d_list:
780        print("%16s:  DISABLED"%i)
781    if env['cppunit']:
782        print("         CppUnit:  FOUND")
783    else:
784        print("         CppUnit:  NOT FOUND")
785    if env['gmsh']=='m':
786        print("            gmsh:  FOUND, MPI-ENABLED")
787    elif env['gmsh']=='s':
788        print("            gmsh:  FOUND")
789    else:
790        print("            gmsh:  NOT FOUND")
791    if env['numpy_h']:
792        print("   numpy headers:  FOUND")
793    else:
794        print("   numpy headers:  NOT FOUND")
795    print("   vsl_random:  %s"%env['vsl_random'])
796        
797    if ((fatalwarning != '') and (env['werror'])):
798        print("  Treating warnings as errors")
799    else:
800        print("  NOT treating warnings as errors")
801    print("")
802    
803    ####################### Configure the subdirectories #########################
804    
805    from grouptest import *
806    
807    TestGroups=[]
808    
809    # keep an environment without warnings-as-errors
810    dodgy_env=env.Clone()
811    
812    # now add warnings-as-errors flags. This needs to be done after configuration
813    # because the scons test files have warnings in them
814    if ((fatalwarning != '') and (env['werror'])):
815        env.Append(CCFLAGS = fatalwarning)
816    
817    Export(
818      ['env',
819       'dodgy_env',
820       'IS_WINDOWS',
821       'TestGroups'
822      ]
823    )
824    
825    env.SConscript(dirs = ['tools/escriptconvert'], variant_dir='$BUILD_DIR/$PLATFORM/tools/escriptconvert', duplicate=0)
826    env.SConscript(dirs = ['paso/src'], variant_dir='$BUILD_DIR/$PLATFORM/paso', duplicate=0)
827    env.SConscript(dirs = ['weipa/src'], variant_dir='$BUILD_DIR/$PLATFORM/weipa', duplicate=0)
828    env.SConscript(dirs = ['escript/src'], variant_dir='$BUILD_DIR/$PLATFORM/escript', duplicate=0)
829    env.SConscript(dirs = ['esysUtils/src'], variant_dir='$BUILD_DIR/$PLATFORM/esysUtils', duplicate=0)
830    env.SConscript(dirs = ['pasowrap/src'], variant_dir='$BUILD_DIR/$PLATFORM/pasowrap', duplicate=0)
831    env.SConscript(dirs = ['dudley/src'], variant_dir='$BUILD_DIR/$PLATFORM/dudley', duplicate=0)
832    env.SConscript(dirs = ['finley/src'], variant_dir='$BUILD_DIR/$PLATFORM/finley', duplicate=0)
833    env.SConscript(dirs = ['ripley/src'], variant_dir='$BUILD_DIR/$PLATFORM/ripley', duplicate=0)
834    env.SConscript(dirs = ['downunder/py_src'], variant_dir='$BUILD_DIR/$PLATFORM/downunder', duplicate=0)
835    env.SConscript(dirs = ['modellib/py_src'], variant_dir='$BUILD_DIR/$PLATFORM/modellib', duplicate=0)
836    env.SConscript(dirs = ['pycad/py_src'], variant_dir='$BUILD_DIR/$PLATFORM/pycad', duplicate=0)
837    env.SConscript(dirs = ['pythonMPI/src'], variant_dir='$BUILD_DIR/$PLATFORM/pythonMPI', duplicate=0)
838    env.SConscript(dirs = ['doc'], variant_dir='$BUILD_DIR/$PLATFORM/doc', duplicate=0)
839    env.SConscript(dirs = ['paso/profiling'], variant_dir='$BUILD_DIR/$PLATFORM/paso/profiling', duplicate=0)
840    
841    
842    ######################## Populate the buildvars file #########################
843    
844    # remove obsolete file
845    if not env['usempi']:
846        Execute(Delete(os.path.join(env['libinstall'], 'pythonMPI')))
847        Execute(Delete(os.path.join(env['libinstall'], 'pythonMPIredirect')))
848    
849    # Try to extract the boost version from version.hpp
850    boosthpp=open(os.path.join(boost_inc_path, 'boost', 'version.hpp'))
851    boostversion='unknown'
852    try:
853        for line in boosthpp:
854            ver=re.match(r'#define BOOST_VERSION (\d+)',line)
855            if ver:
856                boostversion=ver.group(1)
857    except StopIteration:
858        pass
859    boosthpp.close()
860    
861    
862    buildvars=open(os.path.join(env['libinstall'], 'buildvars'), 'w')
863    buildvars.write("svn_revision="+str(global_revision)+"\n")
864    buildvars.write("prefix="+prefix+"\n")
865    buildvars.write("cc="+env['CC']+"\n")
866    buildvars.write("cxx="+env['CXX']+"\n")
867    if env['pythoncmd']=='python':
868        buildvars.write("python="+sys.executable+"\n")
869        buildvars.write("python_version="+str(sys.version_info[0])+"."+str(sys.version_info[1])+"."+str(sys.version_info[2])+"\n")
870    else:
871        buildvars.write("python="+env['pythoncmd']+"\n")
872        p=Popen([env['pythoncmd'], '-c', 'from __future__ import print_function;import sys;print(str(sys.version_info[0])+"."+str(sys.version_info[1])+"."+str(sys.version_info[2]))'], stdout=PIPE)
873        verstring=p.stdout.readline().strip()
874        p.wait()
875        buildvars.write("python_version="+verstring+"\n")
876    buildvars.write("boost_inc_path="+boost_inc_path+"\n")
877    buildvars.write("boost_lib_path="+boost_lib_path+"\n")
878    buildvars.write("boost_version="+boostversion+"\n")
879    buildvars.write("debug=%d\n"%int(env['debug']))
880    buildvars.write("openmp=%d\n"%int(env['openmp']))
881    buildvars.write("mpi=%s\n"%env['mpi'])
882    buildvars.write("mpi_inc_path=%s\n"%mpi_inc_path)
883    buildvars.write("mpi_lib_path=%s\n"%mpi_lib_path)
884    buildvars.write("lapack=%s\n"%env['lapack'])
885    buildvars.write("vsl_random=%d\n"%int(env['vsl_random']))
886    for i in 'netcdf','parmetis','papi','mkl','umfpack','boomeramg','silo','visit':
887        buildvars.write("%s=%d\n"%(i, int(env[i])))
888        if env[i]:
889            buildvars.write("%s_inc_path=%s\n"%(i, eval(i+'_inc_path')))
890            buildvars.write("%s_lib_path=%s\n"%(i, eval(i+'_lib_path')))
891    buildvars.close()
892    
893    ################### Targets to build and install libraries ###################
894    
895    target_init = env.Command(os.path.join(env['pyinstall'],'__init__.py'), None, Touch('$TARGET'))
896    env.Alias('target_init', [target_init])
897    # delete buildvars upon cleanup
898    env.Clean('target_init', os.path.join(env['libinstall'], 'buildvars'))
899    
900    # The headers have to be installed prior to build in order to satisfy
901    # #include <paso/Common.h>
902    env.Alias('build_esysUtils', ['install_esysUtils_headers', 'build_esysUtils_lib'])
903    env.Alias('install_esysUtils', ['build_esysUtils', 'install_esysUtils_lib'])
904    
905    env.Alias('build_paso', ['install_paso_headers', 'build_paso_lib'])
906    env.Alias('install_paso', ['build_paso', 'install_paso_lib'])
907    
908    env.Alias('build_escript', ['install_escript_headers', 'build_escript_lib', 'build_escriptcpp_lib'])
909    env.Alias('install_escript', ['build_escript', 'install_escript_lib', 'install_escriptcpp_lib', 'install_escript_py'])
910    
911    env.Alias('build_pasowrap', ['install_pasowrap_headers', 'build_pasowrap_lib', 'build_pasowrapcpp_lib'])
912    env.Alias('install_pasowrap', ['build_pasowrap', 'install_pasowrap_lib', 'install_pasowrapcpp_lib', 'install_pasowrap_py'])
913    
914    env.Alias('build_dudley', ['install_dudley_headers', 'build_dudley_lib', 'build_dudleycpp_lib'])
915    env.Alias('install_dudley', ['build_dudley', 'install_dudley_lib', 'install_dudleycpp_lib', 'install_dudley_py'])
916    
917    env.Alias('build_finley', ['install_finley_headers', 'build_finley_lib', 'build_finleycpp_lib'])
918    env.Alias('install_finley', ['build_finley', 'install_finley_lib', 'install_finleycpp_lib', 'install_finley_py'])
919    
920    env.Alias('build_ripley', ['install_ripley_headers', 'build_ripley_lib', 'build_ripleycpp_lib'])
921    env.Alias('install_ripley', ['build_ripley', 'install_ripley_lib', 'install_ripleycpp_lib', 'install_ripley_py'])
922    
923    env.Alias('build_weipa', ['install_weipa_headers', 'build_weipa_lib', 'build_weipacpp_lib'])
924    env.Alias('install_weipa', ['build_weipa', 'install_weipa_lib', 'install_weipacpp_lib', 'install_weipa_py'])
925    
926    env.Alias('build_escriptreader', ['install_weipa_headers', 'build_escriptreader_lib'])
927    env.Alias('install_escriptreader', ['build_escriptreader', 'install_escriptreader_lib'])
928    
929    # Now gather all the above into some easy targets: build_all and install_all
930    build_all_list = []
931    build_all_list += ['build_esysUtils']
932    build_all_list += ['build_paso']
933    build_all_list += ['build_escript']
934    build_all_list += ['build_pasowrap']
935    build_all_list += ['build_dudley']
936    build_all_list += ['build_finley']
937    build_all_list += ['build_ripley']
938    build_all_list += ['build_weipa']
939    if not IS_WINDOWS: build_all_list += ['build_escriptreader']
940    if env['usempi']:   build_all_list += ['build_pythonMPI']
941    build_all_list += ['build_escriptconvert']
942    env.Alias('build_all', build_all_list)
943    
944    install_all_list = []
945    install_all_list += ['target_init']
946    install_all_list += ['install_esysUtils']
947    install_all_list += ['install_paso']
948    install_all_list += ['install_escript']
949    install_all_list += ['install_pasowrap']
950    install_all_list += ['install_dudley']
951    install_all_list += ['install_finley']
952    install_all_list += ['install_ripley']
953    install_all_list += ['install_weipa']
954    if not IS_WINDOWS: install_all_list += ['install_escriptreader']
955    install_all_list += ['install_downunder_py']
956    install_all_list += ['install_modellib_py']
957    install_all_list += ['install_pycad_py']
958    if env['usempi']:   install_all_list += ['install_pythonMPI']
959    install_all_list += ['install_escriptconvert']
960    env.Alias('install_all', install_all_list)
961    
962    # Default target is install
963    env.Default('install_all')
964    
965    ################## Targets to build and run the test suite ###################
966    
967    if not env['cppunit']:
968        test_msg = env.Command('.dummy.', None, '@echo "Cannot run C/C++ unit tests, CppUnit not found!";exit 1')
969        env.Alias('run_tests', test_msg)
970        env.Alias('build_tests', '')
971    env.Alias('run_tests', ['install_all'])
972    env.Alias('all_tests', ['install_all', 'run_tests', 'py_tests'])
973    env.Alias('build_full',['install_all','build_tests','build_py_tests'])
974    env.Alias('build_PasoTests','$BUILD_DIR/$PLATFORM/paso/profiling/PasoTests')
975    
976    ##################### Targets to build the documentation #####################
977    
978    env.Alias('pdfdocs',['user_pdf', 'install_pdf', 'cookbook_pdf', 'inversion_pdf'])
979    env.Alias('basedocs', ['pdfdocs','examples_tarfile', 'examples_zipfile', 'api_doxygen'])
980    env.Alias('docs', ['basedocs', 'sphinxdoc'])
981    env.Alias('release_prep', ['docs', 'install_all'])
982    env.Alias('release_prep_old', ['basedocs', 'api_epydoc', 'install_all'])
983    
984    
985    # The test scripts are always generated, this target allows us to
986    # generate the testscripts without doing a full build
987    env.Alias('testscripts',[])
988    
989    if not IS_WINDOWS:
990        try:
991            utest=open('utest.sh','w')
992            utest.write(GroupTest.makeHeader(env['PLATFORM'], prefix, False))
993            for tests in TestGroups:
994                utest.write(tests.makeString())
995            utest.close()
996            Execute(Chmod('utest.sh', 0o755))
997            print("Generated utest.sh.")
998            # This version contains only python tests - I want this to be usable
999            # From a binary only install if you have the test files
1000            utest=open('itest.sh','w')
1001            utest.write(GroupTest.makeHeader(env['PLATFORM'], prefix, True))
1002            for tests in TestGroups:
1003              if tests.exec_cmd=='$PYTHONRUNNER ':
1004                utest.write(tests.makeString())
1005            utest.close()
1006            Execute(Chmod('itest.sh', 0o755))
1007            print("Generated itest.sh.")        
1008        except IOError:
1009            print("Error attempting to write unittests file.")
1010            Exit(1)
1011    
1012        # delete utest.sh upon cleanup
1013        env.Clean('target_init', 'utest.sh')
1014        env.Clean('target_init', 'itest.sh')
1015    
1016        # Make sure that the escript wrapper is in place
1017        if not os.path.isfile(os.path.join(env['bininstall'], 'run-escript')):
1018            print("Copying escript wrapper.")
1019            Execute(Copy(os.path.join(env['bininstall'],'run-escript'), 'bin/run-escript'))
1020    
 # Zipgets  
     
 env.Default(libinstall)  
 env.Default(incinstall)  
 env.Default(pyinstall)  
 env.Alias('release_src',[ src_zipfile, src_tarfile ])    
 env.Alias('release_tests',[ test_zipfile, test_tarfile])  
 env.Alias('release_examples',[ examples_zipfile, examples_tarfile])  
 env.Alias('api_epydoc',api_epydoc)  
 env.Alias('docs',[ 'release_examples', guide_pdf, guide_html_index, api_epydoc])  
 env.Alias('release', ['release_src', 'release_tests', 'docs'])  
 env.Alias('build_tests')    # target to build all C++ tests  
 env.Alias('build_py_tests') # target to build all python tests  
 env.Alias('build_all_tests', [ 'build_tests', 'build_py_tests' ] ) # target to build all python tests  
 env.Alias('run_tests', 'build_tests')   # target to run all C++ test  
 env.Alias('py_tests', 'build_py_tests') # taget to run all released python tests  
 env.Alias('all_tests', ['run_tests', 'py_tests']) # target to run all C++ and released python tests  
   
 # Python install - esys __init__.py  
 init_target = env.Command(pyinstall+'/__init__.py', None, Touch('$TARGET'))  
 env.Alias(init_target)  
   
 # Allow sconscripts to see the env  
 Export(["env", "incinstall", "libinstall", "pyinstall", "dodebug", "mkl_libs", "scsl_libs", "umf_libs",  
     "boost_lib", "python_lib", "doxygen_path", "epydoc_path", "papi_libs",  
         "sys_libs", "test_zipfile", "src_zipfile", "test_tarfile", "src_tarfile", "examples_tarfile", "examples_zipfile",  
         "guide_pdf", "guide_html_index", "api_epydoc", "useMPI"])  
   
 # End initialisation section  
 # Begin configuration section  
 # adds this file and the scons option directore to the source tar  
 release_srcfiles=[env.File('SConstruct'),]+[ env.File(x) for x in glob.glob('scons/*.py') ]  
 release_testfiles=[env.File('README_TESTS'),]  
 env.Zip(src_zipfile, release_srcfiles)  
 env.Zip(test_zipfile, release_testfiles)  
 env.Tar(src_tarfile, release_srcfiles)  
 env.Tar(test_tarfile, release_testfiles)  
   
 # Insert new components to be build here  
 # FIXME: might be nice to replace this verbosity with a list of targets and some  
 # FIXME: nifty python to create the lengthy but very similar env.Sconscript lines  
 # Third Party libraries  
 env.SConscript(dirs = ['tools/CppUnitTest/src'], build_dir='build/$PLATFORM/tools/CppUnitTest', duplicate=0)  
 # C/C++ Libraries  
 env.SConscript(dirs = ['paso/src'], build_dir='build/$PLATFORM/paso', duplicate=0)  
 env.SConscript(dirs = ['bruce/src'], build_dir='build/$PLATFORM/bruce', duplicate=0)  
 env.SConscript(dirs = ['escript/src'], build_dir='build/$PLATFORM/escript', duplicate=0)  
 env.SConscript(dirs = ['esysUtils/src'], build_dir='build/$PLATFORM/esysUtils', duplicate=0)  
 env.SConscript(dirs = ['finley/src'], build_dir='build/$PLATFORM/finley', duplicate=0)  
 env.SConscript(dirs = ['modellib/py_src'], build_dir='build/$PLATFORM/modellib', duplicate=0)  
 env.SConscript(dirs = ['doc'], build_dir='build/$PLATFORM/doc', duplicate=0)  
 env.SConscript(dirs = ['pyvisi/py_src'], build_dir='build/$PLATFORM/pyvisi', duplicate=0)  
   
 # added by Ben Cumming  
 env.SConscript(dirs = ['pythonMPI/src'], build_dir='build/$PLATFORM/pythonMPI', duplicate=0)  
 #env.SConscript(dirs = ['../test'], build_dir='../test/build', duplicate=0)  

Legend:
Removed from v.805  
changed lines
  Added in v.4249

  ViewVC Help
Powered by ViewVC 1.1.26