/[escript]/trunk/site_scons/dependencies.py
ViewVC logotype

Contents of /trunk/site_scons/dependencies.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7031 - (show annotations)
Tue Nov 17 23:44:30 2020 UTC (2 years, 4 months ago) by aellery
File MIME type: text/x-python
File size: 37580 byte(s)
Bug fix. Escript now compiles with boost numpy support in Ubuntu 18.04 bionic
1
2 ##############################################################################
3 #
4 # Copyright (c) 2003-2019 by the University of Queensland
5 # http://www.uq.edu.au
6 #
7 # Primary Business: Queensland, Australia
8 # Licensed under the Apache License, version 2.0
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Development until 2012 by Earth Systems Science Computational Center (ESSCC)
12 # Development 2012-2013 by School of Earth Sciences
13 # Development from 2014 by Centre for Geoscience Computing (GeoComp)
14 # Development from 2019 by School of Earth and Environmental Sciences
15 #
16 ##############################################################################
17
18 from __future__ import print_function, division
19
20 __copyright__="""Copyright (c) 2003-2019 by the University of Queensland
21 http://www.uq.edu.au
22 Primary Business: Queensland, Australia"""
23 __license__="""Licensed under the Apache License, version 2.0
24 http://www.apache.org/licenses/LICENSE-2.0"""
25 __url__="https://launchpad.net/escript-finley"
26
27 import os, re, sys
28 from distutils import sysconfig
29 from subprocess import PIPE, Popen
30 from SCons.Script.SConscript import Configure
31 from site_init import findLibWithHeader, detectModule
32 import subprocess
33
34 REQUIRED_BOOST = (1, 46)
35
36 def CheckComplexAcos(context):
37 context.Message('Checking for working complex std::acos()... ')
38 result = context.TryRun("""
39 #include <complex>
40 int main() { std::complex<double> x(0,3.14159265359), y(1.5707963,-1.8622957);
41 return std::abs(std::acos(x)-y) < 1e-6 ? 0:-1;}
42 """, '.cpp')
43 # scons < 2.4 fix:
44 if type(result)==tuple:
45 result = result[0]
46 context.Result(result)
47 return result
48
49 def checkCompiler(env):
50 conf = Configure(env.Clone(), custom_tests = {'CheckComplexAcos': CheckComplexAcos})
51 if 'CheckCXX' in dir(conf): # exists since scons 1.1.0
52 if not conf.CheckCXX():
53 print("Cannot run C++ compiler '%s' (check config.log)" % (env['CXX']))
54 env.Exit(1)
55 else:
56 if not conf.CheckFunc('printf', language='c++'):
57 print("Cannot run C++ compiler '%s' (check config.log)" % (env['CXX']))
58 env.Exit(1)
59
60 conf.env['buildvars']['cxx']=conf.env['CXX']
61
62 if conf.CheckFunc('gethostname', language='c++'):
63 conf.env.Append(CPPDEFINES = ['HAVE_GETHOSTNAME'])
64
65 if conf.CheckCXXHeader('byteswap.h'):
66 checkhdr="""#include <byteswap.h>
67 #define SCbswap32() {int x=0;bswap_32(x);}"""
68 if conf.CheckFunc('SCbswap32', header=checkhdr, language='c++'):
69 conf.env.Append(CPPDEFINES = ['HAVE_BYTESWAP_H'])
70 if conf.CheckCXXHeader('sys/endian.h'):
71 conf.env.Append(CPPDEFINES = ['HAVE_SYS_ENDIAN_H'])
72 if conf.CheckCXXHeader('libkern/OSByteOrder.h'):
73 conf.env.Append(CPPDEFINES = ['HAVE_OSBYTEORDER_H'])
74
75 if not conf.CheckComplexAcos():
76 conf.env.Append(CPPDEFINES = ['ESYS_USE_BOOST_ACOS'])
77
78 return conf.Finish()
79
80 def get_external_python_sympy(env,bin):
81 import subprocess
82 cmd=''
83 cmd+='import sympy\n'
84 cmd+='print(sympy.__version__)\n'
85 sp=subprocess.Popen([bin, '-c', cmd], stdin=None, stderr=None, stdout=subprocess.PIPE)
86 #ver=sp.stdout.readline().strip().split('.')
87
88 import sys
89 if sys.version_info[0] >= 3:
90 ver = str(sp.stdout.readline().strip(), 'utf-8')
91 else:
92 ver = sp.stdout.readline().strip().split('.')
93
94 tmp1 = ver[0]
95 tmp2 = ver[1]
96 if tmp2 == '.':
97 tmp2 = ver[2]
98
99 if int(tmp1) == 0 and int(tmp2) < 7:
100 env['sympy'] = False
101 env['warnings'].append("sympy version is too old.")
102 env.Append(CPPDEFINES = ['ESYS_NO_SYMPY'])
103 if (int(tmp1) == 1 and int(tmp2) >= 2) or int(tmp1) >= 2:
104 env['sympy']=False
105 env['warnings'].append("escript does not support sympy version 1.2 and higher. Found version %d.%d" % (int(tmp1),int(tmp2)))
106 env.Append(CPPDEFINES = ['ESYS_NO_SYMPY'])
107
108 return env
109
110 def call_python_config(bin=None):
111 import subprocess
112 cmd=''
113 cmd+='import subprocess\n'
114 cmd+='import os\n'
115 cmd+='import sys\n'
116 cmd+='from distutils import sysconfig\n'
117 cmd+='pyversion=sysconfig.get_python_version()\n'
118 cmd+='try:\n'
119 cmd+=' sp=subprocess.Popen(["python"+pyversion+"-config","--ldflags"], stdout=subprocess.PIPE)\n'
120 cmd+='except:\n'
121 cmd+=' pythonroot=sys.exec_prefix+"/bin/"\n'
122 cmd+=' sp=subprocess.Popen([pythonroot+"python"+pyversion+"-config","--ldflags"], stdout=subprocess.PIPE)\n'
123 cmd+='d=sp.stdout.readline().split()\n'
124 cmd+="libdirs=[z[2:] for z in d if z.startswith(b'-L')]\n"
125 cmd+="libs=[z[2:] for z in d if z.startswith(b'-lpython')]\n"
126 cmd+="target=''\n"
127 cmd+="libname=''\n"
128 cmd+="for d in libdirs:\n"
129 cmd+=" for f in libs:\n"
130 cmd+=" s=os.path.join(d,b'lib'+f+b'.so')\n"
131 cmd+=" try:\n"
132 cmd+=" dummy=os.stat(s)\n"
133 cmd+=" if target=='':\n"
134 cmd+=" target=d\n"
135 cmd+=" libname=f\n"
136 cmd+=" except Exception:\n"
137 cmd+=" pass\n"
138 cmd+=" s=os.path.join(d,b'lib'+f+b'.dylib')\n"
139 cmd+=" try:\n"
140 cmd+=" dummy=os.stat(s)\n"
141 cmd+=" if target=='':\n"
142 cmd+=" target=d\n"
143 cmd+=" libname=f\n"
144 cmd+=" except Exception:\n"
145 cmd+=" pass\n"
146 if bin is None:
147 exec(cmd)
148 ver=str(sys.version_info[0])+'.'+str(sys.version_info[1])+'.'+str(sys.version_info[2])
149 return (target,libname,ver, sysconfig.get_python_inc())
150 # run an external python to get its library location
151 # yes we are starting another python just to run python?-config
152 cmd+="if 'decode' in dir(target):\n"
153 cmd+=" target=target.decode()\n"
154 cmd+=" libname=libname.decode()\n"
155 cmd+="print(target)\n"
156 cmd+="print(libname)\n"
157 cmd+="import sys\n"
158 cmd+="print(str(sys.version_info[0])+'.'+str(sys.version_info[1])+'.'+str(sys.version_info[2]))\n"
159 cmd+="print(sysconfig.get_python_inc())\n"
160 sp=subprocess.Popen([bin, '-c', cmd], stdin=None, stderr=None, stdout=subprocess.PIPE)
161 target=sp.stdout.readline().strip()
162 libname=sp.stdout.readline().strip()
163 ver=sp.stdout.readline().strip()
164 pinc=sp.stdout.readline().strip()
165 return (target, libname, ver, pinc)
166
167 def checkPython(env):
168 # First we check to see if the config file has specified
169 # where to find the file. Ideally, this should be automatic
170 # but we need to deal with the case where python is not in its INSTALL
171 # directory.
172 # Use the python scons is running
173 if env['pythoncmd'] == sys.executable:
174 if env['IS_WINDOWS']:
175 python_inc_path=sysconfig.get_python_inc()
176 python_lib_path=os.path.join(sysconfig.get_config_var('prefix'), 'libs')
177 python_libs=['python%s%s'%(sys.version_info[0], sys.version_info[1])]
178 verstring=".".join([str(i) for i in sys.version_info[:3]])
179 else:
180 (python_lib_path, python_libs,verstring, python_inc_path)=call_python_config(env['pythoncmd'])
181
182 # if we want to use a python other than the one scons is running
183 # Note: we assume scons is running python 2 in the following.
184 else:
185 if env['IS_WINDOWS']:
186 cmd = "import os, sys\n"
187 cmd += "from distutils import sysconfig\n"
188 cmd += "print(sysconfig.get_python_inc())\n"
189 cmd += "print(os.path.join(sysconfig.get_config_var('prefix'), 'libs'))\n"
190 cmd += "print('python%s%s'%(sys.version_info[0], sys.version_info[1]))\n"
191 cmd += "print('.'.join([str(i) for i in sys.version_info[:3]]))"
192 pout = subprocess.Popen([env['pythoncmd'], '-c', cmd], stdout=subprocess.PIPE).stdout.read()
193 if isinstance(pout, bytes):
194 pout = pout.decode(sys.stdout.encoding)
195 lines = pout.split('\n')
196 python_inc_path = lines[0].strip()
197 python_lib_path = lines[1].strip()
198 python_libs = [lines[2].strip()]
199 verstring = lines[3].strip()
200 else:
201 (python_lib_path, python_libs,verstring, python_inc_path)=call_python_config(env['pythoncmd'])
202
203 if sys.version_info[0] == 3:
204 if isinstance(verstring, str) is False:
205 verstring = str(verstring, 'utf-8')
206 else:
207 if isinstance(verstring, basestring) is False:
208 verstring = str(verstring, 'utf-8')
209
210 env['python_version'] = verstring
211 try:
212 ispython3 = (verstring[0] == '3')
213 except:
214 ispython3 = sys.version_info[0] == 3
215 if ispython3:
216 env.Append(CPPDEFINES=['ESPYTHON3'])
217 env['buildvars']['python_version'] = verstring
218 env['buildvars']['python'] = env['pythoncmd']
219 # Check for an override from the config file.
220 # Ideally, this should be automatic but we need to deal with the case
221 # where python is not in its INSTALL directory
222 if env['pythonlibpath'] != '':
223 python_lib_path = env['pythonlibpath']
224
225 if env['pythonincpath'] != '':
226 python_inc_path = env['pythonincpath']
227
228 if env['pythonlibname'] != '':
229 python_libs = env['pythonlibname']
230
231 conf = Configure(env.Clone())
232
233 if env['sysheaderopt'] == '':
234 conf.env.AppendUnique(CPPPATH = [python_inc_path])
235 else:
236 conf.env.Append(CCFLAGS = [env['sysheaderopt'], python_inc_path])
237
238 conf.env.AppendUnique(LIBPATH = [python_lib_path])
239 conf.env.AppendUnique(LIBS = python_libs)
240 # The wrapper script needs to find the libs
241 conf.env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], python_lib_path)
242
243 if not conf.CheckCXXHeader('Python.h'):
244 print("Cannot find python include files (tried 'Python.h' in directory %s)" % (python_inc_path))
245 env.Exit(1)
246 if not conf.CheckFunc('Py_Exit', language='c++'):
247 print("Cannot find python library method Py_Exit (tried %s in directory %s)" % (python_libs, python_lib_path))
248 env.Exit(1)
249
250 return conf.Finish()
251
252 def checkCudaVersion(env):
253 # NVCC availability is already checked in the Tool file
254 p = Popen([env['NVCC'], '-V'], stdout=PIPE)
255 out,_ = p.communicate()
256 env['nvcc_version'] = '(unknown version)'
257 for line in out.split('\n'):
258 if 'release' in line:
259 version = line[line.find('release'):].strip()
260 env['nvcc_version'] = version
261 break
262 env['buildvars']['nvcc']=env['NVCC']
263 return env
264
265 def checkBoost(env):
266 boost_inc_path,boost_lib_path=findLibWithHeader(env, env['boost_libs'], 'boost/python.hpp', env['boost_prefix'], lang='c++')
267 if env['sysheaderopt'] == '':
268 env.AppendUnique(CPPPATH = [boost_inc_path])
269 else:
270 # This is required because we can't -isystem /usr/include since it
271 # breaks std includes
272 if os.path.normpath(boost_inc_path) == '/usr/include':
273 env.Append(CCFLAGS=[env['sysheaderopt'], os.path.join(boost_inc_path,'boost')])
274 else:
275 env.Append(CCFLAGS=[env['sysheaderopt'], boost_inc_path])
276
277 env.AppendUnique(LIBPATH = [boost_lib_path])
278 env.AppendUnique(LIBS = env['boost_libs'])
279 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], boost_lib_path)
280
281 # Try to extract the boost version from version.hpp
282 boosthpp=open(os.path.join(boost_inc_path, 'boost', 'version.hpp'))
283 boostversion='unknown'
284 for line in boosthpp:
285 ver=re.match(r'#define BOOST_VERSION (\d+)',line)
286 if ver:
287 boostversion=ver.group(1)
288 boostversion = int(boostversion)
289 maj = boostversion/100000
290 minor = (boostversion/100)%1000
291 sub = boostversion % 100
292 env['boost_version'] = "%d.%d.%d"%(maj,minor,sub)
293 if maj <= REQUIRED_BOOST[0] and minor < REQUIRED_BOOST[1]:
294 print("The boost version referenced must be at least version %d.%d "%REQUIRED_BOOST + "(have %d.%d.%d)"%(maj,minor,sub))
295 env.Exit(1)
296 boosthpp.close()
297 env['buildvars']['boost_inc_path']=boost_inc_path
298 env['buildvars']['boost_lib_path']=boost_lib_path
299 env['buildvars']['boostversion']=boostversion
300
301 # Check for the boost numpy library
302 env['have_boost_numpy']=False
303 if boostversion >= 106300 and env['disable_boost_numpy'] is False:
304 try:
305 boost_numpy_inc_path,boost_numpy_lib_path=findLibWithHeader(env, env['boost_libs'], 'boost/python/numpy.hpp', env['boost_prefix'], lang='c++')
306
307 # Locate the boost numpy files
308 if env['IS_WINDOWS']:
309 # windows scons template adds boost_numpy to boost_libs
310 env.Append(CPPDEFINES=['ESYS_HAVE_BOOST_NUMPY'])
311 else:
312 p = subprocess.Popen(["ld","--verbose"], stdout=subprocess.PIPE)
313 out,err = p.communicate()
314 spath = [x[13:-3] for x in out.split() if b'SEARCH_DIR' in x]
315 spath.append(boost_lib_path)
316 p2name = ''
317 p3name = ''
318 p2res = ''
319 p3res = ''
320 for name in spath:
321 try:
322 l=os.listdir(name)
323 import sys
324 if sys.version_info[0] == 3:
325 string_type = str
326 else:
327 string_type = basestring
328 for x in l:
329 if isinstance(x,string_type):
330 if x.startswith('libboost_numpy') and x.endswith('.so'):
331 p2res = x
332 if x.startswith('libboost_numpy-py2') and x.endswith('.so'):
333 p2res = x
334 if x.startswith('libboost_numpy3') and x.endswith('.so'):
335 p3res = x
336 if x.startswith('libboost_numpy3-py3') and x.endswith('.so'):
337 p3res = x
338 else:
339 if x.startswith(b'libboost_numpy') and x.endswith(b'.so'):
340 p2res = x
341 if x.startswith(b'libboost_numpy-py2') and x.endswith(b'.so'):
342 p2res = x
343 if x.startswith(b'libboost_numpy3') and x.endswith(b'.so'):
344 p3res = x
345 if x.startswith(b'libboost_numpy3-py3') and x.endswith('.so'):
346 p3res = x
347 except OSError:
348 pass
349
350 # Pick the right one
351 if int(env['python_version'][0]) == 2:
352 libname = p2res[3:-3]
353 else:
354 libname = p3res[3:-3]
355
356 # If found, add the necessary information to env
357 if len(libname) > 0:
358 env.AppendUnique(LIBS = libname)
359 tmp=env['boost_libs']
360 env['boost_libs']=[tmp,libname]
361 env.AppendUnique(CPPPATH = [boost_numpy_inc_path])
362 env.AppendUnique(LIBPATH = [boost_numpy_lib_path])
363 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], boost_numpy_lib_path)
364 env.Append(CPPDEFINES=['ESYS_HAVE_BOOST_NUMPY'])
365 env['have_boost_numpy']=True
366
367 print("Found boost/python/numpy.hpp. Building with boost numpy support.")
368 except:
369 print("Warning: Could not find boost/python/numpy.hpp. Building without numpy support.")
370
371 # Check if the version of boost we are using is missing BOOST_BYTE_ORDER
372 if boostversion >= 107000:
373 env.Append(CPPDEFINES=['ESYS_DEPRECATED_BOOST_ENDIAN'])
374 if boostversion >= 107200:
375 env.Append(CPPDEFINES=['ESYS_MOVED_BOOST_ENDIAN'])
376
377 return env
378
379 def checkNumpy(env):
380 if not detectModule(env, 'numpy'):
381 print("Cannot import numpy. If it is installed try setting your PYTHONPATH and probably %s"%env['LD_LIBRARY_PATH_KEY'])
382 env.Exit(1)
383
384 ## check for numpy header (optional)
385 conf = Configure(env.Clone())
386 numpy_h = False
387 if conf.CheckCXXHeader(['Python.h','numpy/ndarrayobject.h']):
388 numpy_h = True
389 else:
390 conda_prefix = os.environ.get('CONDA_PREFIX')
391 if conda_prefix:
392 # make a copy of CPPPATH so it can be restored if header check fails
393 cpp_path_old = conf.env.get('CPPPATH', []).copy()
394 conf.env.Append(CPPPATH = [conda_prefix+'/Lib/site-packages/numpy/core/include'])
395 if conf.CheckCXXHeader(['Python.h','numpy/ndarrayobject.h']):
396 numpy_h = True
397 else:
398 conf.env['CPPPATH'] = cpp_path_old
399
400 conf.env['numpy_h'] = numpy_h
401 if numpy_h:
402 conf.env.Append(CPPDEFINES = ['ESYS_HAVE_NUMPY_H'])
403
404 return conf.Finish()
405
406 def checkCUDA(env):
407 try:
408 cuda_inc_path,cuda_lib_path=findLibWithHeader(env, 'cudart', 'thrust/version.h', env['cuda_prefix'], lang='c++')
409 env.AppendUnique(CPPPATH = [cuda_inc_path])
410 env.AppendUnique(LIBPATH = [cuda_lib_path])
411 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], cuda_lib_path)
412 env.Append(CPPDEFINES = ['ESYS_HAVE_CUDA'])
413 env['cuda']=True
414 except:
415 env['cuda']=False
416 return env
417
418 def checkCppUnit(env):
419 try:
420 cppunit_inc_path,cppunit_lib_path=findLibWithHeader(env, env['cppunit_libs'], 'cppunit/TestFixture.h', env['cppunit_prefix'], lang='c++')
421 env.AppendUnique(CPPPATH = [cppunit_inc_path])
422 env.AppendUnique(LIBPATH = [cppunit_lib_path])
423 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], cppunit_lib_path)
424 env['cppunit']=True
425 except:
426 env['cppunit']=False
427 return env
428
429 def checkOptionalModules(env):
430 ######## scipy
431 if not detectModule(env, 'scipy'):
432 env['warnings'].append("Cannot import scipy. NetCDF sources will not be available for inversions.")
433
434 ######## pyproj
435 if not detectModule(env, 'pyproj'):
436 env['warnings'].append("Cannot import pyproj. Inversions may not work.")
437
438 ######## gdal
439 if not detectModule(env, 'gdal'):
440 env['warnings'].append("Cannot import gdal. Inversions will not honour WKT coordinate system information.")
441
442 ######## sympy
443 if not detectModule(env, 'sympy'):
444 env['warnings'].append("Cannot import sympy. Symbolic toolbox and nonlinear PDEs will not be available.")
445 env.Append(CPPDEFINES = ['ESYS_NO_SYMPY'])
446 else:
447 if env['pythoncmd'] is not None:
448 env=get_external_python_sympy(env, env['pythoncmd'])
449 else:
450 import sympy as sp
451 import distutils.version as duv
452 spVer=sp.__version__
453 spl=spVer.split('.')
454 if duv.LooseVersion(sympy.__version__) < duv.LooseVersion('0.7'):
455 env['sympy']=False
456 env['warnings'].append("sympy version too old. Symbolic toolbox and nonlinear PDEs will not be available.")
457 env.Append(CPPDEFINES = ['ESYS_NO_SYMPY'])
458 if duv.LooseVersion(sympy.__version__) > duv.LooseVersion('1.2'):
459 env['sympy']=False
460 env['warnings'].append("escript does not support sympy version 1.2 and higher. Found %d" % duv.LooseVersion(sympy.__version__))
461 env.Append(CPPDEFINES = ['ESYS_NO_SYMPY'])
462
463 ######## gmshpy
464 env['gmshpy'] = detectModule(env, 'gmshpy')
465
466 return env
467
468 def checkForTrilinos(env):
469 trilinos_inc_path=''
470 trilinos_lib_path=''
471 if env['trilinos']:
472 havelibs = (len(env['trilinos_libs']) > 0)
473 trilinos_inc_path,trilinos_lib_path=findLibWithHeader(env,
474 env['trilinos_libs'], 'Amesos2.hpp',
475 env['trilinos_prefix'], lang='c++', try_link=havelibs)
476 env.AppendUnique(CPPPATH = [trilinos_inc_path])
477 env.AppendUnique(LIBPATH = [trilinos_lib_path])
478 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], trilinos_lib_path)
479 env['buildvars']['trilinos_inc_path']=trilinos_inc_path
480 env['buildvars']['trilinos_lib_path']=trilinos_lib_path
481 conf = Configure(env.Clone())
482
483 dependencies=['Amesos2.hpp','Amesos2_Solver_decl.hpp','BelosSolverFactory.hpp','BelosSolverManager.hpp',\
484 'BelosTFQMRIter.hpp','BelosTFQMRSolMgr.hpp','BelosTpetraAdapter.hpp','BelosTypes.hpp',\
485 'Ifpack2_Factory.hpp','Kokkos_DefaultNode.hpp',\
486 'MatrixMarket_Tpetra.hpp','MueLu_CreateTpetraPreconditioner.hpp',\
487 'Teuchos_DefaultComm.hpp','Teuchos_ParameterList.hpp',\
488 'Tpetra_CrsGraph.hpp','Tpetra_CrsMatrix.hpp', 'Tpetra_RowMatrix.hpp',\
489 'Tpetra_Vector.hpp','Trilinos_version.h']
490
491 print("Looking for the Trilinos headers...")
492 for check in dependencies:
493 print("Checking for %s... %s" % (check, "yes" if os.path.isfile(os.path.join(trilinos_inc_path,check)) else "no"))
494 if not os.path.isfile(os.path.join(trilinos_inc_path,check)):
495 print("Could not find a Trilinos header file (tried looking in directory %s)" % (trilinos_inc_path))
496 env.Exit(1)
497
498 if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_DefaultPlatform.hpp')):
499 print("Checking for %s... %s" % ('Tpetra_DefaultPlatform.hpp', "yes" if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_DefaultPlatform.hpp')) else "no"))
500 env.Append(CPPDEFINES = ['ESYS_HAVE_TPETRA_DP'])
501
502 if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_BlockCrsMatrix.hpp')):
503 print("Checking for %s... %s" % ('Tpetra_BlockCrsMatrix.hpp', "yes" if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_DefaultPlatform.hpp')) else "no"))
504 elif os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_Experimental_BlockCrsMatrix.hpp')):
505 print("Checking for %s... %s" % ('Tpetra_Experimental_BlockCrsMatrix.hpp', "yes" if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_DefaultPlatform.hpp')) else "no"))
506 env.Append(CPPDEFINES = ['ESYS_HAVE_TPETRA_EXPERIMENTAL_BLOCKCRS'])
507 else:
508 raise RuntimeError('Could not locate the Trilinos Block CRS Matrix header')
509
510 if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_BlockCrsMatrix_Helpers.hpp')):
511 print("Checking for %s... %s" % ('Tpetra_BlockCrsMatrix_Helpers.hpp', "yes" if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_DefaultPlatform.hpp')) else "no"))
512 elif os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_Experimental_BlockCrsMatrix_Helpers.hpp')):
513 print("Checking for %s... %s" % ('Tpetra_Experimental_BlockCrsMatrix_Helpers.hpp', "yes" if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_DefaultPlatform.hpp')) else "no"))
514 env.Append(CPPDEFINES = ['ESYS_HAVE_TPETRA_EXPERIMENTAL_BLOCKCRSH'])
515 else:
516 raise RuntimeError('Could not locate the Trilinos Block CRS Matrix Helpers header')
517
518 if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_BlockVector.hpp')):
519 print("Checking for %s... %s" % ('Tpetra_BlockVector.hpp', "yes" if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_DefaultPlatform.hpp')) else "no"))
520 elif os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_Experimental_BlockVector.hpp')):
521 print("Checking for %s... %s" % ('Tpetra_Experimental_BlockVector.hpp', "yes" if os.path.isfile(os.path.join(trilinos_inc_path,'Tpetra_DefaultPlatform.hpp')) else "no"))
522 env.Append(CPPDEFINES = ['ESYS_HAVE_TPETRA_EXPERIMENTAL_BLOCKV'])
523 else:
524 raise RuntimeError('Could not locate the Trilinos BlockVector header')
525
526 # Try to extract the trilinos version from Trilinos_version.h
527 versionh=open(os.path.join(trilinos_inc_path, 'Trilinos_version.h'))
528 trilinos_version='unknown'
529 env['trilinos_version']='unknown'
530 for line in versionh:
531 ver=re.match(r'#define TRILINOS_MAJOR_MINOR_VERSION (\d+)',line)
532 if ver:
533 trilinos_version=ver.group(1)
534 trilinos_version = int(trilinos_version)
535 major=int(str(trilinos_version)[:2])
536 minor=int(str(trilinos_version)[2:4])
537 tmp=int(str(trilinos_version)[4:6])
538 env['trilinos_version'] = str(major)+"."+str(minor)+"."+str(tmp)
539
540 if not havelibs:
541 packages=['Tpetra','Kokkos','Belos','Amesos2','Ifpack2','MueLu']
542 libs = []
543 for pk in packages:
544 # find out what libraries to link with...
545 makefile = os.path.join(trilinos_inc_path, 'Makefile.export.%s'%pk)
546 try:
547 for l in open(makefile, 'r').readlines():
548 if l.startswith("%s_LIBRARIES"%pk): # or l.startswith("Trilinos_TPL_LIBRARIES"):
549 lst = l.split('=')[1].strip().split()
550 lst = [e.replace('-l','',1) for e in lst]
551 libs += lst
552 elif l.startswith("%s_TPL_INCLUDE_DIRS"%pk):
553 lst = l.split('=')[1].strip().split()
554 lst = [e.replace('-I','',1) for e in lst]
555 env.AppendUnique(CPPPATH = lst)
556
557 except Exception as e:
558 raise RuntimeError('Error reading Trilinos export Makefile\n%s'%(e))
559 env['trilinos_libs'] = libs
560
561 env.Append(CPPDEFINES = ['ESYS_HAVE_TRILINOS'])
562 # env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], trilinos_lib_path)
563 # env['buildvars']['trilinos_inc_path']=trilinos_inc_path
564 # env['buildvars']['trilinos_lib_path']=trilinos_lib_path
565 env['buildvars']['trilinos']=int(env['trilinos'])
566 return env
567
568 def checkOptionalLibraries(env):
569 ######## netCDF
570 netcdf_inc_path=''
571 netcdf_lib_path=''
572 if env['netcdf']:
573 if env['netcdf']==4:
574 env.Append(CPPDEFINES = ['NETCDF4'])
575 netcdf_inc_path,netcdf_lib_path=findLibWithHeader(env, env['netcdf_libs'], 'ncVar.h', env['netcdf_prefix'], lang='c++')
576 else:
577 netcdf_inc_path,netcdf_lib_path=findLibWithHeader(env, env['netcdf_libs'], 'netcdfcpp.h', env['netcdf_prefix'], lang='c++')
578 env.AppendUnique(CPPPATH = [netcdf_inc_path])
579 env.AppendUnique(LIBPATH = [netcdf_lib_path])
580 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], netcdf_lib_path)
581 env.Append(CPPDEFINES = ['ESYS_HAVE_NETCDF'])
582 env['buildvars']['netcdf_inc_path']=netcdf_inc_path
583 env['buildvars']['netcdf_lib_path']=netcdf_lib_path
584 env['buildvars']['netcdf']=int(env['netcdf'])
585
586 ######## MKL
587 mkl_inc_path=''
588 mkl_lib_path=''
589 if env['mkl']:
590 mkl_inc_path,mkl_lib_path=findLibWithHeader(env, env['mkl_libs'], 'mkl_pardiso.h', env['mkl_prefix'], lang='c++')
591 env.AppendUnique(CPPPATH = [mkl_inc_path])
592 env.AppendUnique(LIBPATH = [mkl_lib_path])
593 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], mkl_lib_path)
594 env.Append(CPPDEFINES = ['ESYS_HAVE_MKL'])
595 env['buildvars']['mkl_inc_path']=mkl_inc_path
596 env['buildvars']['mkl_lib_path']=mkl_lib_path
597 env['buildvars']['mkl']=int(env['mkl'])
598
599 ######## UMFPACK
600 umfpack_inc_path=''
601 umfpack_lib_path=''
602 if env['umfpack']:
603 umfpack_inc_path,umfpack_lib_path=findLibWithHeader(env, env['umfpack_libs'], 'umfpack.h', env['umfpack_prefix'], lang='c++')
604 env.AppendUnique(CPPPATH = [umfpack_inc_path])
605 env.AppendUnique(LIBPATH = [umfpack_lib_path])
606 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], umfpack_lib_path)
607 env.Append(CPPDEFINES = ['ESYS_HAVE_UMFPACK'])
608 env['buildvars']['umfpack_inc_path']=umfpack_inc_path
609 env['buildvars']['umfpack_lib_path']=umfpack_lib_path
610 env['buildvars']['umfpack']=int(env['umfpack'])
611
612 ######## MUMPS
613 mumps_inc_path=''
614 mumps_lib_path=''
615 if env['mumps']:
616 mumps_inc_path,mumps_lib_path=findLibWithHeader(env, env['mumps_libs'], 'mumps_mpi.h', env['mumps_prefix'], lang='c++')
617 env.AppendUnique(CPPPATH = [mumps_inc_path])
618 env.AppendUnique(LIBPATH = [mumps_lib_path])
619 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], mumps_lib_path)
620 env.Append(CPPDEFINES = ['ESYS_HAVE_MUMPS'])
621 env['buildvars']['mumps_inc_path']=mumps_inc_path
622 env['buildvars']['mumps_lib_path']=mumps_lib_path
623 env['buildvars']['mumps']=int(env['mumps'])
624
625 ######## LAPACK
626 lapack_inc_path=''
627 lapack_lib_path=''
628 flavour = 'none'
629 env['uselapack'] = False
630 if env['lapack'] != 0:
631 # not explicitly disabled so run the checks
632 if env['longindices']:
633 # you want longindices + lapack? sorry.
634 if env['lapack'] == 1:
635 print("LAPACK requires index type = int. Set longindices to False or disable LAPACK.")
636 env.Exit(1)
637 else:
638 if env['mkl']:
639 # we detected MKL so try the MKL header+libs
640 flavour = 'mkl'
641 header = 'mkl_lapack.h'
642 prefix = env['mkl_prefix']
643 if len(env['lapack_libs']) == 0:
644 libs = env['mkl_libs']
645 else:
646 libs = env['lapack_libs']
647 else:
648 # try for clapack
649 flavour = 'clapack'
650 header = 'clapack.h'
651 prefix = env['lapack_prefix']
652 if len(env['lapack_libs']) == 0:
653 libs = ['lapack_atlas']
654 else:
655 libs = env['lapack_libs']
656
657 try:
658 lapack_inc_path,lapack_lib_path=findLibWithHeader(env, libs, header, prefix, lang='c++')
659 env['lapack_libs'] = libs
660 env['uselapack'] = True
661 env.AppendUnique(CPPPATH = [lapack_inc_path])
662 env.AppendUnique(LIBPATH = [lapack_lib_path])
663 env.Append(CPPDEFINES = ['ESYS_HAVE_LAPACK'])
664 if flavour == 'mkl':
665 env.AppendUnique(CPPDEFINES = ['ESYS_MKL_LAPACK'])
666 env['buildvars']['lapack_inc_path']=lapack_inc_path
667 env['buildvars']['lapack_lib_path']=lapack_lib_path
668 except:
669 if env['lapack'] == 1:
670 raise
671 # lapack was set to auto-detect so not a fatal error
672 flavour = 'none'
673
674 env['lapack'] = flavour
675 env['buildvars']['lapack'] = flavour
676
677 ######## Silo
678 silo_inc_path=''
679 silo_lib_path=''
680 if env['silo']:
681 silo_inc_path,silo_lib_path=findLibWithHeader(env, env['silo_libs'], 'silo.h', env['silo_prefix'], lang='c++')
682 env.AppendUnique(CPPPATH = [silo_inc_path])
683 env.AppendUnique(LIBPATH = [silo_lib_path])
684 env.Append(CPPDEFINES = ['ESYS_HAVE_SILO'])
685 env['buildvars']['silo_inc_path']=silo_inc_path
686 env['buildvars']['silo_lib_path']=silo_lib_path
687 env['buildvars']['silo']=int(env['silo'])
688
689 ######## VisIt
690 visit_inc_path=''
691 visit_lib_path=''
692 if env['visit']:
693 visit_inc_path,visit_lib_path=findLibWithHeader(env, env['visit_libs'], 'VisItControlInterface_V2.h', env['visit_prefix'], lang='c++')
694 env.AppendUnique(CPPPATH = [visit_inc_path])
695 env.AppendUnique(LIBPATH = [visit_lib_path])
696 env['buildvars']['visit_inc_path']=visit_inc_path
697 env['buildvars']['visit_lib_path']=visit_lib_path
698 env['buildvars']['visit']=int(env['visit'])
699
700 ######## MPI
701 if env['mpi']=='no':
702 env['mpi']='none'
703
704 env['usempi'] = env['mpi']!='none'
705 mpi_inc_path=''
706 mpi_lib_path=''
707 if env['usempi']:
708 mpi_inc_path,mpi_lib_path=findLibWithHeader(env, env['mpi_libs'], 'mpi.h', env['mpi_prefix'], lang='c++')
709 env.AppendUnique(CPPPATH = [mpi_inc_path])
710 env.AppendUnique(LIBPATH = [mpi_lib_path])
711 env.AppendUnique(LIBS = env['mpi_libs'])
712 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], mpi_lib_path)
713 env.Append(CPPDEFINES = ['ESYS_MPI', 'MPI_NO_CPPBIND', 'MPICH_IGNORE_CXX_SEEK'])
714 # NetCDF 4.1 defines MPI_Comm et al. if MPI_INCLUDED is not defined!
715 # On the other hand MPT and OpenMPI don't define the latter so we have
716 # to do that here
717 if env['netcdf'] and env['mpi'] in ['MPT','OPENMPI']:
718 env.Append(CPPDEFINES = ['MPI_INCLUDED'])
719
720 if env['mpi'] == 'OPENMPI':
721 # try to get version for correct launcher arguments
722 try:
723 p = Popen(['orterun', '-V'], stdout=PIPE, stderr=PIPE)
724 o,e = p.communicate()
725 try:
726 e=e.decode()
727 ver = e.split('\n')[0].split()[-1]
728 except IndexError:
729 o=o.decode()
730 ver = o.split('\n')[0].split()[-1]
731 if len(ver) > 0:
732 env['orte_version'] = ver
733 except OSError:
734 pass
735
736 env['buildvars']['mpi_inc_path']=mpi_inc_path
737 env['buildvars']['mpi_lib_path']=mpi_lib_path
738 env['buildvars']['mpi']=env['mpi']
739
740 ######## ParMETIS
741 if not env['usempi']: env['parmetis'] = False
742 parmetis_inc_path=''
743 parmetis_lib_path=''
744 if env['parmetis']:
745 parmetis_inc_path,parmetis_lib_path=findLibWithHeader(env, env['parmetis_libs'], 'parmetis.h', env['parmetis_prefix'], lang='c++')
746 env.AppendUnique(CPPPATH = [parmetis_inc_path])
747 env.AppendUnique(LIBPATH = [parmetis_lib_path])
748 env.PrependENVPath(env['LD_LIBRARY_PATH_KEY'], parmetis_lib_path)
749
750 # Try to extract the parmetis version from parmetis.h
751 header=open(os.path.join(parmetis_inc_path, 'parmetis.h')).readlines()
752 major,minor,sub = None,None,None
753 for line in header:
754 ver=re.match(r'#define PARMETIS_MAJOR_VERSION\s*(\d+)',line)
755 if ver:
756 major = int(ver.group(1))
757 continue
758 ver=re.match(r'#define PARMETIS_MINOR_VERSION\s*(\d+)',line)
759 if ver:
760 minor = int(ver.group(1))
761 continue
762 ver=re.match(r'#define PARMETIS_SUBMINOR_VERSION\s*(\d+)',line)
763 if ver:
764 sub = int(ver.group(1))
765 continue
766 if major is not None:
767 env['parmetis_version'] = "%d.%d.%d"%(major,minor,0 if sub is None else sub)
768 if env['longindices']:
769 # ParMETIS version 3.x does not support 64-bit indices
770 if major < 4:
771 print("Sorry, cannot use ParMETIS version < 4.0 with 64-bit index types. Set longindices to False or disable ParMETIS.")
772 env.Exit(1)
773 else:
774 # check if ParMETIS was built with 64-bit indices
775 conf = Configure(env.Clone())
776 idxsize=conf.CheckTypeSize('idx_t', '#include <parmetis.h>', 'C++')
777 if idxsize != 8:
778 print("Sorry, ParMETIS was not compiled with 64-bit indices. Set longindices to False or disable/rebuild ParMETIS.")
779 env.Exit(1)
780 else:
781 env['parmetis_version'] = "unknown"
782
783 env.Append(CPPDEFINES = ['ESYS_HAVE_PARMETIS'])
784 env['buildvars']['parmetis_inc_path']=parmetis_inc_path
785 env['buildvars']['parmetis_lib_path']=parmetis_lib_path
786 env['buildvars']['parmetis']=int(env['parmetis'])
787
788 ######## gmsh (for tests)
789 env['gmsh'] = False
790 if env['use_gmsh'] is True:
791 if env['IS_WINDOWS']:
792 try:
793 p=Popen(['gmsh', '-info'], stderr=PIPE)
794 _,e=p.communicate()
795 env.Append(CPPDEFINES=['ESYS_HAVE_GMSH'])
796 if e.split().count("MPI"):
797 env['gmsh']='m'
798 env.Append(CPPDEFINES=['ESYS_GMSH_MPI'])
799 else:
800 env['gmsh']='s'
801 except OSError:
802 pass
803 else:
804 which = Popen(['which', 'gmsh'], stdout=PIPE)
805 path,_ = which.communicate()
806 if which.wait() == 0:
807 cmd = ['ldd', path[:-1]]
808 if env['IS_OSX']:
809 cmd = ['otool','-L', path[:-1]]
810 try:
811 p=Popen(cmd, stdout=PIPE)
812 gmshlibs,_ = p.communicate()
813 gmshlibs.decode()
814 env.Append(CPPDEFINES=['ESYS_HAVE_GMSH'])
815 if p.returncode == 0 and 'libmpi' in gmshlibs.decode('utf-8'):
816 env['gmsh'] = 'm'
817 env.Append(CPPDEFINES=['ESYS_GMSH_MPI'])
818 else:
819 env['gmsh'] = 's'
820 except OSError:
821 pass
822
823 ######## boost::iostreams
824 if env['compressed_files']:
825 try:
826 boost_inc_path, boost_lib_path = findLibWithHeader(env, env['compression_libs'], 'boost/iostreams/filter/gzip.hpp', env['boost_prefix'], lang='c++')
827 env.Append(CPPDEFINES = ['ESYS_HAVE_BOOST_IO'])
828 except RuntimeError as e:
829 env['compressed_files'] = False
830 env['buildvars']['compressed_files']=int(env['compressed_files'])
831
832 ######## Trilinos
833 env = checkForTrilinos(env)
834 return env
835
836 def checkPDFLatex(env):
837 if 'PDF' in dir(env) and '.tex' in env.PDF.builder.src_suffixes(env):
838 env['pdflatex']=True
839 else:
840 env['pdflatex']=False
841 return env

  ViewVC Help
Powered by ViewVC 1.1.26