PageRenderTime 45ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/config/BuildSystem/config/packages/BlasLapack.py

https://bitbucket.org/emconsta/petscforkeimex
Python | 575 lines | 573 code | 1 blank | 1 comment | 32 complexity | fd837d5ef7b05ad0ea77b023dece10bd MD5 | raw file
  1. from __future__ import generators
  2. import user
  3. import config.base
  4. import config.package
  5. from sourceDatabase import SourceDB
  6. import os
  7. class Configure(config.package.Package):
  8. '''FIX: This has not yet been converted to the package style'''
  9. def __init__(self, framework):
  10. config.package.Package.__init__(self, framework)
  11. self.headerPrefix = ''
  12. self.substPrefix = ''
  13. self.argDB = framework.argDB
  14. self.found = 0
  15. self.f2c = 0 # indicates either the f2c BLAS/LAPACK are used (with or without Fortran compiler) or there is no Fortran compiler (and system BLAS/LAPACK is used)
  16. self.fblaslapack = 0
  17. self.missingRoutines = []
  18. self.separateBlas = 1
  19. self.defaultPrecision = 'double'
  20. self.worksonWindows = 1
  21. self.downloadonWindows = 1
  22. def setupDependencies(self, framework):
  23. config.package.Package.setupDependencies(self, framework)
  24. self.compilerFlags = framework.require('config.compilerFlags', self)
  25. self.f2cblaslapack = framework.require('config.packages.f2cblaslapack', self)
  26. return
  27. def __str__(self):
  28. return 'BLAS/LAPACK: '+self.libraries.toString(self.lib)+'\n'
  29. def setupHelp(self, help):
  30. import nargs
  31. help.addArgument('BLAS/LAPACK', '-with-blas-lapack-dir=<dir>', nargs.ArgDir(None, None, 'Indicate the directory containing BLAS and LAPACK libraries'))
  32. help.addArgument('BLAS/LAPACK', '-with-blas-lapack-lib=<libraries: e.g. [/Users/..../liblapack.a,libblas.a,...]>',nargs.ArgLibrary(None, None, 'Indicate the library containing BLAS and LAPACK'))
  33. help.addArgument('BLAS/LAPACK', '-with-blas-lib=<libraries: e.g. [/Users/..../libblas.a,...]>', nargs.ArgLibrary(None, None, 'Indicate the library(s) containing BLAS'))
  34. help.addArgument('BLAS/LAPACK', '-with-lapack-lib=<libraries: e.g. [/Users/..../liblapack.a,...]>',nargs.ArgLibrary(None, None, 'Indicate the library(s) containing LAPACK'))
  35. help.addArgument('BLAS/LAPACK', '-download-f-blas-lapack=<no,yes,filename>', nargs.ArgDownload(None, 0, 'Automatically install a Fortran version of BLAS/LAPACK'))
  36. help.addArgument('BLAS/LAPACK', '-known-64-bit-blas-indices=<bool>', nargs.ArgBool(None, 0, 'Indicate if using 64 bit integer BLAS'))
  37. return
  38. def getDefaultPrecision(self):
  39. '''The precision of the library'''
  40. if hasattr(self, 'precisionProvider'):
  41. if hasattr(self.precisionProvider, 'precision'):
  42. return self.precisionProvider.precision
  43. return self._defaultPrecision
  44. def setDefaultPrecision(self, defaultPrecision):
  45. '''The precision of the library'''
  46. self._defaultPrecision = defaultPrecision
  47. return
  48. defaultPrecision = property(getDefaultPrecision, setDefaultPrecision, doc = 'The precision of the library')
  49. def getPrefix(self):
  50. if self.defaultPrecision == 'single': return 's'
  51. if self.defaultPrecision == 'double': return 'd'
  52. if self.defaultPrecision == 'quad': return 'q'
  53. if self.defaultPrecision == '__float128': return 'q'
  54. return 'Unknown precision'
  55. def getOtherLibs(self, foundBlas = None, blasLibrary = None, separateBlas = None):
  56. if foundBlas is None:
  57. foundBlas = self.foundBlas
  58. if blasLibrary is None:
  59. blasLibrary = self.blasLibrary
  60. if separateBlas is None:
  61. separateBlas = self.separateBlas
  62. otherLibs = []
  63. if foundBlas:
  64. if separateBlas:
  65. otherLibs += blasLibrary
  66. if self.useCompatibilityLibs:
  67. otherLibs += self.compilers.flibs
  68. return otherLibs
  69. def checkBlas(self, blasLibrary, otherLibs, fortranMangle, routine = 'dot'):
  70. '''This checks the given library for the routine, dot by default'''
  71. oldLibs = self.compilers.LIBS
  72. prototype = ''
  73. call = ''
  74. routine = self.getPrefix()+routine
  75. if fortranMangle=='stdcall':
  76. if routine=='ddot':
  77. prototype = 'double __stdcall DDOT(int*,double*,int*,double*,int*);'
  78. call = 'DDOT(0,0,0,0,0);'
  79. found = self.libraries.check(blasLibrary, routine, otherLibs = otherLibs, fortranMangle = fortranMangle, prototype = prototype, call = call)
  80. self.compilers.LIBS = oldLibs
  81. return found
  82. def checkLapack(self, lapackLibrary, otherLibs, fortranMangle, routines = ['getrs', 'geev']):
  83. oldLibs = self.compilers.LIBS
  84. found = 0
  85. prototypes = ['','']
  86. calls = ['','']
  87. for routine in range(len(routines)):
  88. routines[routine] = self.getPrefix()+routines[routine]
  89. if fortranMangle=='stdcall':
  90. if routines == ['dgetrs','dgeev']:
  91. prototypes = ['void __stdcall DGETRS(char*,int,int*,int*,double*,int*,int*,double*,int*,int*);',
  92. 'void __stdcall DGEEV(char*,int,char*,int,int*,double*,int*,double*,double*,double*,int*,double*,int*,double*,int*,int*);']
  93. calls = ['DGETRS(0,0,0,0,0,0,0,0,0,0);',
  94. 'DGEEV(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);']
  95. for routine, prototype, call in zip(routines, prototypes, calls):
  96. found = found or self.libraries.check(lapackLibrary, routine, otherLibs = otherLibs, fortranMangle = fortranMangle, prototype = prototype, call = call)
  97. if found: break
  98. self.compilers.LIBS = oldLibs
  99. return found
  100. def checkLib(self, lapackLibrary, blasLibrary = None):
  101. '''Checking for BLAS and LAPACK symbols'''
  102. #check for BLASLAPACK_STDCALL calling convention!!!!
  103. if blasLibrary is None:
  104. self.separateBlas = 0
  105. blasLibrary = lapackLibrary
  106. else:
  107. self.separateBlas = 1
  108. if not isinstance(lapackLibrary, list): lapackLibrary = [lapackLibrary]
  109. if not isinstance(blasLibrary, list): blasLibrary = [blasLibrary]
  110. foundBlas = 0
  111. foundLapack = 0
  112. self.f2c = 0
  113. self.f2cpkg = 0
  114. mangleFunc = self.compilers.fortranMangling
  115. foundBlas = self.checkBlas(blasLibrary, self.getOtherLibs(foundBlas, blasLibrary), mangleFunc,'dot')
  116. if foundBlas:
  117. foundLapack = self.checkLapack(lapackLibrary, self.getOtherLibs(foundBlas, blasLibrary), mangleFunc)
  118. if foundLapack:
  119. self.mangling = self.compilers.fortranMangling
  120. self.framework.logPrint('Found Fortran mangling on BLAS/LAPACK which is '+self.compilers.fortranMangling)
  121. else:
  122. self.framework.logPrint('Checking for no name mangling on BLAS/LAPACK')
  123. foundBlas = self.checkBlas(blasLibrary, self.getOtherLibs(foundBlas, blasLibrary), 0, 'dot')
  124. foundLapack = self.checkLapack(lapackLibrary, self.getOtherLibs(foundBlas, blasLibrary), 0, ['getrs', 'geev'])
  125. if foundBlas and foundLapack:
  126. self.framework.logPrint('Found no name mangling on BLAS/LAPACK')
  127. self.mangling = 'unchanged'
  128. self.f2c = 1
  129. else:
  130. self.framework.logPrint('Checking for underscore name mangling on BLAS/LAPACK')
  131. foundBlas = self.checkBlas(blasLibrary, self.getOtherLibs(foundBlas, blasLibrary), 0, 'dot_')
  132. foundLapack = self.checkLapack(lapackLibrary, self.getOtherLibs(foundBlas, blasLibrary), 0, ['getrs_', 'geev_'])
  133. if foundBlas and foundLapack:
  134. self.framework.logPrint('Found underscore name mangling on BLAS/LAPACK')
  135. self.mangling = 'underscore'
  136. self.f2c = 1
  137. self.f2cpkg = self.checkBlas(blasLibrary, self.getOtherLibs(foundBlas, blasLibrary), 0, 'f2cblaslapack311_id')
  138. return (foundBlas, foundLapack)
  139. def generateGuesses(self):
  140. # check that user has used the options properly
  141. if self.f2cblaslapack.found:
  142. self.f2c = 1
  143. libDir = self.f2cblaslapack.libDir
  144. f2cLibs = [os.path.join(libDir,'libf2cblas.a')]
  145. if self.libraries.math:
  146. f2cLibs = f2cLibs+self.libraries.math
  147. yield ('f2cblaslapack', f2cLibs, os.path.join(libDir,'libf2clapack.a'), 0)
  148. raise RuntimeError('--download-f2cblaslapack libraries cannot be used')
  149. if 'with-blas-lib' in self.framework.argDB and not 'with-lapack-lib' in self.framework.argDB:
  150. raise RuntimeError('If you use the --with-blas-lib=<lib> you must also use --with-lapack-lib=<lib> option')
  151. if not 'with-blas-lib' in self.framework.argDB and 'with-lapack-lib' in self.framework.argDB:
  152. raise RuntimeError('If you use the --with-lapack-lib=<lib> you must also use --with-blas-lib=<lib> option')
  153. if 'with-blas-lib' in self.framework.argDB and 'with-blas-lapack-dir' in self.framework.argDB:
  154. raise RuntimeError('You cannot set both the library containing BLAS with --with-blas-lib=<lib>\nand the directory to search with --with-blas-lapack-dir=<dir>')
  155. if 'with-blas-lapack-lib' in self.framework.argDB and 'with-blas-lapack-dir' in self.framework.argDB:
  156. raise RuntimeError('You cannot set both the library containing BLAS/LAPACK with --with-blas-lapack-lib=<lib>\nand the directory to search with --with-blas-lapack-dir=<dir>')
  157. if self.framework.argDB['download-f-blas-lapack']:
  158. self.download= ['http://ftp.mcs.anl.gov/pub/petsc/externalpackages/fblaslapack-3.1.1.tar.gz']
  159. self.downloadname = 'f-blas-lapack'
  160. self.downloadfilename = 'fblaslapack'
  161. if self.framework.argDB['download-f-blas-lapack'] == 1 or isinstance(self.framework.argDB['download-f-blas-lapack'], str):
  162. if isinstance(self.framework.argDB['download-f-blas-lapack'], str):
  163. self.download= [self.framework.argDB['download-f-blas-lapack']]
  164. self.fblaslapack = 1
  165. if not hasattr(self.compilers, 'FC'):
  166. raise RuntimeError('Cannot request f-blas-lapack without Fortran compiler, maybe you want --download-f2cblaslapack=1?')
  167. if self.defaultPrecision == '__float128':
  168. raise RuntimeError('Cannot use --download-f-blas-lapack with precision __float128, maybe you want --download-f2cblaslapack?')
  169. libdir = self.downLoadBlasLapack('f','f')
  170. yield ('Downloaded BLAS/LAPACK library', os.path.join(libdir,'libfblas.a'), os.path.join(libdir,'libflapack.a'), 1)
  171. raise RuntimeError('Could not use downloaded f-blas-lapack.')
  172. # Try specified BLASLAPACK library
  173. if 'with-blas-lapack-lib' in self.framework.argDB:
  174. yield ('User specified BLAS/LAPACK library', None, self.framework.argDB['with-blas-lapack-lib'], 1)
  175. raise RuntimeError('You set a value for --with-blas-lapack-lib=<lib>, but '+str(self.framework.argDB['with-blas-lapack-lib'])+' cannot be used\n')
  176. # Try specified BLAS and LAPACK libraries
  177. if 'with-blas-lib' in self.framework.argDB and 'with-lapack-lib' in self.framework.argDB:
  178. yield ('User specified BLAS and LAPACK libraries', self.framework.argDB['with-blas-lib'], self.framework.argDB['with-lapack-lib'], 1)
  179. raise RuntimeError('You set a value for --with-blas-lib=<lib> and --with-lapack-lib=<lib>, but '+str(self.framework.argDB['with-blas-lib'])+' and '+str(self.framework.argDB['with-lapack-lib'])+' cannot be used\n')
  180. # Try specified installation root
  181. if 'with-blas-lapack-dir' in self.framework.argDB:
  182. dir = self.framework.argDB['with-blas-lapack-dir']
  183. # error if package-dir is in externalpackages
  184. if os.path.realpath(dir).find(os.path.realpath(self.externalPackagesDir)) >=0:
  185. fakeExternalPackagesDir = dir.replace(os.path.realpath(dir).replace(os.path.realpath(self.externalPackagesDir),''),'')
  186. raise RuntimeError('Bad option: '+'--with-blas-lapack-dir='+self.framework.argDB['with-blas-lapack-dir']+'\n'+
  187. fakeExternalPackagesDir+' is reserved for --download-package scratch space. \n'+
  188. 'Do not install software in this location nor use software in this directory.')
  189. if not (len(dir) > 2 and dir[1] == ':') :
  190. dir = os.path.abspath(dir)
  191. self.framework.log.write('Looking for BLAS/LAPACK in user specified directory: '+dir+'\n')
  192. self.framework.log.write('Files and directorys in that directory:\n'+str(os.listdir(dir))+'\n')
  193. yield ('User specified installation root (HPUX)', os.path.join(dir, 'libveclib.a'), os.path.join(dir, 'liblapack.a'), 1)
  194. f2cLibs = [os.path.join(dir,'libf2cblas.a')]
  195. if self.libraries.math:
  196. f2cLibs = f2cLibs+self.libraries.math
  197. yield ('User specified installation root (F2C)', f2cLibs, os.path.join(dir, 'libf2clapack.a'), 1)
  198. yield ('User specified installation root', os.path.join(dir, 'libfblas.a'), os.path.join(dir, 'libflapack.a'), 1)
  199. # Check AMD ACML libraries
  200. yield ('User specified AMD ACML lib dir', None, os.path.join(dir,'lib','libacml.a'), 1)
  201. yield ('User specified AMD ACML lib dir', None, [os.path.join(dir,'lib','libacml.a'), os.path.join(dir,'lib','libacml_mv.a')], 1)
  202. yield ('User specified AMD ACML lib dir', None, os.path.join(dir,'lib','libacml_mp.a'), 1)
  203. yield ('User specified AMD ACML lib dir', None, [os.path.join(dir,'lib','libacml_mp.a'), os.path.join(dir,'lib','libacml_mv.a')], 1)
  204. # Check MATLAB [ILP64] MKL
  205. yield ('User specified MATLAB [ILP64] MKL Linux lib dir', None, [os.path.join(dir,'bin','glnxa64','mkl.so'), os.path.join(dir,'sys','os','glnxa64','libiomp5.so'), 'pthread'], 1)
  206. # Some new MKL 11/12 variations
  207. for libdir in [os.path.join('lib','32'),os.path.join('lib','ia32'),'32','ia32','']:
  208. if not os.path.exists(os.path.join(dir,libdir)):
  209. self.framework.logPrint('MLK Path not found.. skipping: '+os.path.join(dir,libdir))
  210. else:
  211. yield ('User specified MKL11/12 Linux32', None, [os.path.join(dir,libdir,'libmkl_intel.a'),'mkl_sequential','mkl_core','pthread','-lm'],1)
  212. for libdir in [os.path.join('lib','64'),os.path.join('lib','ia64'),os.path.join('lib','em64t'),os.path.join('lib','intel64'),'64','ia64','em64t','intel64','']:
  213. if not os.path.exists(os.path.join(dir,libdir)):
  214. self.framework.logPrint('MLK Path not found.. skipping: '+os.path.join(dir,libdir))
  215. else:
  216. yield ('User specified MKL11/12 Linux64', None, [os.path.join(dir,libdir,'libmkl_intel_lp64.a'),'mkl_sequential','mkl_core','pthread','-lm'],1)
  217. # Older Linux MKL checks
  218. yield ('User specified MKL Linux lib dir', None, [os.path.join(dir, 'libmkl_lapack.a'), 'mkl', 'guide', 'pthread'], 1)
  219. for libdir in ['32','64','em64t']:
  220. yield ('User specified MKL Linux installation root', None, [os.path.join(dir,'lib',libdir,'libmkl_lapack.a'),'mkl', 'guide', 'pthread'], 1)
  221. yield ('User specified MKL Linux-x86 lib dir', None, [os.path.join(dir, 'libmkl_lapack.a'), 'libmkl_def.a', 'guide', 'pthread'], 1)
  222. yield ('User specified MKL Linux-x86 lib dir', None, [os.path.join(dir, 'libmkl_lapack.a'), 'libmkl_def.a', 'guide', 'vml','pthread'], 1)
  223. yield ('User specified MKL Linux-ia64 lib dir', None, [os.path.join(dir, 'libmkl_lapack.a'), 'libmkl_ipf.a', 'guide', 'pthread'], 1)
  224. yield ('User specified MKL Linux-em64t lib dir', None, [os.path.join(dir, 'libmkl_lapack.a'), 'libmkl_em64t.a', 'guide', 'pthread'], 1)
  225. yield ('User specified MKL Linux-x86 installation root', None, [os.path.join(dir,'lib','32','libmkl_lapack.a'),'libmkl_def.a', 'guide', 'pthread'], 1)
  226. yield ('User specified MKL Linux-x86 installation root', None, [os.path.join(dir,'lib','32','libmkl_lapack.a'),'libmkl_def.a', 'guide', 'vml','pthread'], 1)
  227. yield ('User specified MKL Linux-ia64 installation root', None, [os.path.join(dir,'lib','64','libmkl_lapack.a'),'libmkl_ipf.a', 'guide', 'pthread'], 1)
  228. yield ('User specified MKL Linux-em64t installation root', None, [os.path.join(dir,'lib','em64t','libmkl_lapack.a'),'libmkl_em64t.a', 'guide', 'pthread'], 1)
  229. # Mac MKL check
  230. yield ('User specified MKL Mac-x86 lib dir', None, [os.path.join(dir, 'libmkl_lapack.a'), 'libmkl_ia32.a', 'guide'], 1)
  231. yield ('User specified MKL Max-x86 installation root', None, [os.path.join(dir,'Libraries','32','libmkl_lapack.a'),'libmkl_ia32.a', 'guide'], 1)
  232. yield ('User specified MKL Max-x86 installation root', None, [os.path.join(dir,'lib','32','libmkl_lapack.a'),'libmkl_ia32.a', 'guide'], 1)
  233. yield ('User specified MKL Mac-em64t lib dir', None, [os.path.join(dir, 'libmkl_lapack.a'), 'libmkl_intel_lp64.a', 'guide'], 1)
  234. yield ('User specified MKL Max-em64t installation root', None, [os.path.join(dir,'Libraries','32','libmkl_lapack.a'),'libmkl_intel_lp64.a', 'guide'], 1)
  235. yield ('User specified MKL Max-em64t installation root', None, [os.path.join(dir,'lib','32','libmkl_lapack.a'),'libmkl_intel_lp64.a', 'guide'], 1)
  236. # Check MKL on windows
  237. yield ('User specified MKL Windows lib dir', None, [os.path.join(dir, 'mkl_c_dll.lib')], 1)
  238. yield ('User specified stdcall MKL Windows lib dir', None, [os.path.join(dir, 'mkl_s_dll.lib')], 1)
  239. yield ('User specified ia64/em64t MKL Windows lib dir', None, [os.path.join(dir, 'mkl_dll.lib')], 1)
  240. yield ('User specified MKL10-32 Windows lib dir', None, [os.path.join(dir, 'mkl_intel_c_dll.lib'),'mkl_intel_thread_dll.lib','mkl_core_dll.lib','libiomp5md.lib'], 1)
  241. yield ('User specified MKL10-32 Windows stdcall lib dir', None, [os.path.join(dir, 'mkl_intel_s_dll.lib'),'mkl_intel_thread_dll.lib','mkl_core_dll.lib','libiomp5md.lib'], 1)
  242. yield ('User specified MKL10-64 Windows lib dir', None, [os.path.join(dir, 'mkl_intel_lp64_dll.lib'),'mkl_intel_thread_dll.lib','mkl_core_dll.lib','libiomp5md.lib'], 1)
  243. mkldir = os.path.join(dir, 'ia32', 'lib')
  244. yield ('User specified MKL Windows installation root', None, [os.path.join(mkldir, 'mkl_c_dll.lib')], 1)
  245. yield ('User specified stdcall MKL Windows installation root', None, [os.path.join(mkldir, 'mkl_s_dll.lib')], 1)
  246. yield ('User specified MKL10-32 Windows installation root', None, [os.path.join(mkldir, 'mkl_intel_c_dll.lib'),'mkl_intel_thread_dll.lib','mkl_core_dll.lib','libiomp5md.lib'], 1)
  247. yield ('User specified MKL10-32 Windows stdcall installation root', None, [os.path.join(mkldir, 'mkl_intel_s_dll.lib'),'mkl_intel_thread_dll.lib','mkl_core_dll.lib','libiomp5md.lib'], 1)
  248. mkldir = os.path.join(dir, 'em64t', 'lib')
  249. yield ('User specified MKL10-64 Windows installation root', None, [os.path.join(mkldir, 'mkl_intel_lp64_dll.lib'),'mkl_intel_thread_dll.lib','mkl_core_dll.lib','libiomp5md.lib'], 1)
  250. yield ('User specified em64t MKL Windows installation root', None, [os.path.join(mkldir, 'mkl_dll.lib')], 1)
  251. mkldir = os.path.join(dir, 'ia64', 'lib')
  252. yield ('User specified ia64 MKL Windows installation root', None, [os.path.join(mkldir, 'mkl_dll.lib')], 1)
  253. yield ('User specified MKL10-64 Windows installation root', None, [os.path.join(mkldir, 'mkl_intel_lp64_dll.lib'),'mkl_intel_thread_dll.lib','mkl_core_dll.lib','libiomp5md.lib'], 1)
  254. # Search for atlas
  255. yield ('User specified ATLAS Linux installation root', [os.path.join(dir, 'libcblas.a'),os.path.join(dir, 'libf77blas.a'), os.path.join(dir, 'libatlas.a')], [os.path.join(dir, 'liblapack.a')], 1)
  256. yield ('User specified ATLAS Linux installation root', [os.path.join(dir, 'libf77blas.a'), os.path.join(dir, 'libatlas.a')], [os.path.join(dir, 'liblapack.a')], 1)
  257. # Search for liblapack.a and libblas.a after the implementations with more specific name to avoid
  258. # finding these in /usr/lib despite using -L<blas-lapack-dir> while attempting to get a different library.
  259. yield ('User specified installation root', os.path.join(dir, 'libblas.a'), os.path.join(dir, 'liblapack.a'), 1)
  260. raise RuntimeError('You set a value for --with-blas-lapack-dir=<dir>, but '+self.framework.argDB['with-blas-lapack-dir']+' cannot be used\n')
  261. # IRIX locations
  262. yield ('IRIX Mathematics library', None, 'libcomplib.sgimath.a', 1)
  263. yield ('Another IRIX Mathematics library', None, 'libscs.a', 1)
  264. yield ('Compaq/Alpha Mathematics library', None, 'libcxml.a', 1)
  265. # IBM ESSL locations
  266. yield ('IBM ESSL Mathematics library', None, 'libessl.a', 1)
  267. yield ('IBM ESSL Mathematics library for Blue Gene', None, 'libesslbg.a', 2)
  268. # Portland group compiler blas and lapack
  269. if 'PGI' in os.environ and config.setCompilers.Configure.isPGI(self.setCompilers.CC):
  270. dir = os.path.join(os.environ['PGI'],'linux86','5.1','lib')
  271. yield ('User specified installation root', os.path.join(dir, 'libblas.a'), os.path.join(dir, 'liblapack.a'), 1)
  272. dir = os.path.join(os.environ['PGI'],'linux86','5.0','lib')
  273. yield ('User specified installation root', os.path.join(dir, 'libblas.a'), os.path.join(dir, 'liblapack.a'), 1)
  274. dir = os.path.join(os.environ['PGI'],'linux86','lib')
  275. yield ('User specified installation root', os.path.join(dir, 'libblas.a'), os.path.join(dir, 'liblapack.a'), 1)
  276. # Try compiler defaults
  277. yield ('Default compiler libraries', '', '', 1)
  278. yield ('Default compiler locations', 'libblas.a', 'liblapack.a', 1)
  279. yield ('HPUX', 'libveclib.a', 'liblapack.a', 1)
  280. # /usr/local/lib
  281. dir = os.path.join('/usr','local','lib')
  282. yield ('Default compiler locations /usr/local/lib', os.path.join(dir,'libblas.a'), os.path.join(dir,'liblapack.a'), 1)
  283. yield ('Default Atlas location /usr/local/lib',[os.path.join(dir, 'libcblas.a'),os.path.join(dir, 'libf77blas.a'), os.path.join(dir, 'libatlas.a')], [os.path.join(dir, 'liblapack.a')], 1)
  284. yield ('Default Atlas location /usr/local/lib',[os.path.join(dir, 'libf77blas.a'), os.path.join(dir, 'libatlas.a')], [os.path.join(dir, 'liblapack.a')], 1)
  285. yield ('Default compiler locations with G77', None, ['liblapack.a', 'libblas.a','libg2c.a'], 1)
  286. yield ('Default compiler locations with gfortran', None, ['liblapack.a', 'libblas.a','libgfortran.a'], 1)
  287. # Try MacOSX location
  288. dir = os.path.join('/Library', 'Frameworks', 'Intel_MKL.framework','Libraries','32')
  289. yield ('MacOSX with Intel MKL', None, [os.path.join(dir,'libmkl_lapack.a'),'libmkl_ia32.a','libguide.a'], 1)
  290. yield ('MacOSX BLAS/LAPACK library', None, os.path.join('/System', 'Library', 'Frameworks', 'vecLib.framework', 'vecLib'), 1)
  291. # Sun locations
  292. yield ('Sun sunperf BLAS/LAPACK library', None, ['libsunperf.a','libsunmath.a','libm.a'], 1)
  293. yield ('Sun sunperf BLAS/LAPACK library', None, ['libsunperf.a','libF77.a','libM77.a','libsunmath.a','libm.a'], 1)
  294. yield ('Sun sunperf BLAS/LAPACK library', None, ['libsunperf.a','libfui.a','libfsu.a','libsunmath.a','libm.a'], 1)
  295. # Try Microsoft Windows location
  296. for MKL_Version in [os.path.join('MKL','9.0'),os.path.join('MKL','8.1.1'),os.path.join('MKL','8.1'),os.path.join('MKL','8.0.1'),os.path.join('MKL','8.0'),'MKL72','MKL70','MKL61','MKL']:
  297. mklpath = os.path.join('/cygdrive', 'c', 'Program Files', 'Intel', MKL_Version)
  298. if not os.path.exists(mklpath):
  299. self.framework.logPrint('MLK Path not found.. skipping: '+mklpath)
  300. else:
  301. mkldir = os.path.join(mklpath, 'ia32', 'lib')
  302. yield ('Microsoft Windows, Intel MKL library', None, os.path.join(mkldir,'mkl_c_dll.lib'), 1)
  303. yield ('Microsoft Windows, Intel MKL stdcall library', None, os.path.join(mkldir,'mkl_s_dll.lib'), 1)
  304. mkldir = os.path.join(mklpath, 'em64t', 'lib')
  305. yield ('Microsoft Windows, em64t Intel MKL library', None, os.path.join(mkldir,'mkl_dll.lib'), 1)
  306. mkldir = os.path.join(mklpath, 'ia64', 'lib')
  307. yield ('Microsoft Windows, ia64 Intel MKL library', None, os.path.join(mkldir,'mkl_dll.lib'), 1)
  308. if self.framework.argDB['download-f-blas-lapack'] == 2:
  309. if not hasattr(self.compilers, 'FC'):
  310. raise RuntimeError('Cannot request f-blas-lapack without Fortran compiler, maybe you want --download-f2cblaslapack=1?')
  311. libdir = self.downLoadBlasLapack('f','f')
  312. yield ('Downloaded BLAS/LAPACK library', os.path.join(libdir,'libfblas.a'), os.path.join(libdir,'libflapack.a'), 1)
  313. return
  314. def Install(self):
  315. return self.installDir
  316. def getSharedFlag(self,cflags):
  317. for flag in ['-PIC', '-fPIC', '-KPIC', '-qpic']:
  318. if cflags.find(flag) >=0: return flag
  319. return ''
  320. def getPrecisionFlag(self,cflags):
  321. for flag in ['-m32', '-m64', '-xarch=v9','-q64']:
  322. if cflags.find(flag) >=0: return flag
  323. return ''
  324. def getWindowsNonOptFlags(self,cflags):
  325. for flag in ['-MT','-MTd','-MD','-MDd','-threads']:
  326. if cflags.find(flag) >=0: return flag
  327. return ''
  328. def checkNoOptFlag(self):
  329. flag = '-O0'
  330. if self.setCompilers.checkCompilerFlag(flag):
  331. return flag
  332. return ''
  333. def downLoadBlasLapack(self, f2c, l):
  334. if f2c == 'f':
  335. self.setCompilers.pushLanguage('FC')
  336. if config.setCompilers.Configure.isNAG(self.setCompilers.getLinker()):
  337. raise RuntimeError('Cannot compile fortran blaslapack with NAG compiler - install blas/lapack compiled with g77 instead')
  338. self.setCompilers.popLanguage()
  339. self.getInstallDir()
  340. libdir = self.libDir
  341. confdir = self.confDir
  342. blasDir = self.packageDir
  343. g = open(os.path.join(blasDir,'tmpmakefile'),'w')
  344. f = open(os.path.join(blasDir,'makefile'),'r')
  345. line = f.readline()
  346. while line:
  347. if line.startswith('CC '):
  348. cc = self.compilers.CC
  349. line = 'CC = '+cc+'\n'
  350. if line.startswith('COPTFLAGS '):
  351. self.setCompilers.pushLanguage('C')
  352. line = 'COPTFLAGS = '+self.setCompilers.getCompilerFlags()
  353. noopt = self.checkNoOptFlag()
  354. self.setCompilers.popLanguage()
  355. if line.startswith('CNOOPT'):
  356. self.setCompilers.pushLanguage('C')
  357. line = 'CNOOPT = '+noopt+ ' '+self.getSharedFlag(self.setCompilers.getCompilerFlags())+' '+self.getPrecisionFlag(self.setCompilers.getCompilerFlags())+' '+self.getWindowsNonOptFlags(self.setCompilers.getCompilerFlags())
  358. self.setCompilers.popLanguage()
  359. if line.startswith('FC '):
  360. fc = self.compilers.FC
  361. if fc.find('f90') >= 0 or fc.find('f95') >=0:
  362. import commands
  363. output = commands.getoutput(fc+' -v')
  364. if output.find('IBM') >= 0:
  365. fc = os.path.join(os.path.dirname(fc),'xlf')
  366. self.framework.log.write('Using IBM f90 compiler, switching to xlf for compiling BLAS/LAPACK\n')
  367. line = 'FC = '+fc+'\n'
  368. if line.startswith('FOPTFLAGS '):
  369. self.setCompilers.pushLanguage('FC')
  370. line = 'FOPTFLAGS = '+self.setCompilers.getCompilerFlags().replace('-Mfree','')+'\n'
  371. noopt = self.checkNoOptFlag()
  372. self.setCompilers.popLanguage()
  373. if line.startswith('FNOOPT'):
  374. self.setCompilers.pushLanguage('FC')
  375. line = 'FNOOPT = '+noopt+' '+self.getSharedFlag(self.setCompilers.getCompilerFlags())+' '+self.getPrecisionFlag(self.setCompilers.getCompilerFlags())+' '+self.getWindowsNonOptFlags(self.setCompilers.getCompilerFlags())+'\n'
  376. self.setCompilers.popLanguage()
  377. if line.startswith('AR '):
  378. line = 'AR = '+self.setCompilers.AR+'\n'
  379. if line.startswith('AR_FLAGS '):
  380. line = 'AR_FLAGS = '+self.setCompilers.AR_FLAGS+'\n'
  381. if line.startswith('LIB_SUFFIX '):
  382. line = 'LIB_SUFFIX = '+self.setCompilers.AR_LIB_SUFFIX+'\n'
  383. if line.startswith('RANLIB '):
  384. line = 'RANLIB = '+self.setCompilers.RANLIB+'\n'
  385. if line.startswith('RM '):
  386. line = 'RM = '+self.programs.RM+'\n'
  387. if line.startswith('include'):
  388. line = '\n'
  389. g.write(line)
  390. line = f.readline()
  391. f.close()
  392. g.close()
  393. if not self.installNeeded('tmpmakefile'):
  394. return libdir
  395. try:
  396. self.logPrintBox('Compiling '+l.upper()+'BLASLAPACK; this may take several minutes')
  397. output,err,ret = config.base.Configure.executeShellCommand('cd '+blasDir+' && make -f tmpmakefile cleanblaslapck cleanlib && make -f tmpmakefile', timeout=2500, log = self.framework.log)
  398. except RuntimeError, e:
  399. raise RuntimeError('Error running make on '+blasDir+': '+str(e))
  400. try:
  401. output,err,ret = config.base.Configure.executeShellCommand('cd '+blasDir+' && mv -f lib'+f2c+'blas.'+self.setCompilers.AR_LIB_SUFFIX+' lib'+f2c+'lapack.'+self.setCompilers.AR_LIB_SUFFIX+' '+ libdir, timeout=30, log = self.framework.log)
  402. except RuntimeError, e:
  403. raise RuntimeError('Error moving '+blasDir+' libraries: '+str(e))
  404. try:
  405. output,err,ret = config.base.Configure.executeShellCommand('cd '+blasDir+' && cp -f tmpmakefile '+os.path.join(self.confDir, self.name), timeout=30, log = self.framework.log)
  406. except RuntimeError, e:
  407. pass
  408. return libdir
  409. def configureLibrary(self):
  410. self.functionalBlasLapack = []
  411. self.foundBlas = 0
  412. self.foundLapack = 0
  413. for (name, blasLibrary, lapackLibrary, self.useCompatibilityLibs) in self.generateGuesses():
  414. self.framework.log.write('================================================================================\n')
  415. self.framework.log.write('Checking for a functional BLAS and LAPACK in '+name+'\n')
  416. (foundBlas, foundLapack) = self.executeTest(self.checkLib, [lapackLibrary, blasLibrary])
  417. if foundBlas: self.foundBlas = 1
  418. if foundLapack: self.foundLapack = 1
  419. if foundBlas and foundLapack:
  420. self.functionalBlasLapack.append((name, blasLibrary, lapackLibrary))
  421. if not self.framework.argDB['with-alternatives']:
  422. break
  423. # User chooses one or take first (sort by version)
  424. if self.foundBlas and self.foundLapack:
  425. name, self.blasLibrary, self.lapackLibrary = self.functionalBlasLapack[0]
  426. if not isinstance(self.blasLibrary, list): self.blasLibrary = [self.blasLibrary]
  427. if not isinstance(self.lapackLibrary, list): self.lapackLibrary = [self.lapackLibrary]
  428. self.lib = []
  429. if self.lapackLibrary[0]: self.lib.extend(self.lapackLibrary)
  430. if self.blasLibrary[0]: self.lib.extend(self.blasLibrary)
  431. self.dlib = self.lib[:]
  432. if self.useCompatibilityLibs:
  433. self.dlib.extend(self.compilers.flibs)
  434. self.framework.packages.append(self)
  435. else:
  436. if not self.foundBlas:
  437. # check for split blas/blas-dev packages
  438. import glob
  439. blib = glob.glob('/usr/lib/libblas.*')
  440. if blib != [] and not (os.path.isfile('/usr/lib/libblas.so') or os.path.isfile('/usr/lib/libblas.a')):
  441. raise RuntimeError('Incomplete BLAS install; Perhaps blas package is installed - but blas-dev/blas-devel is required?')
  442. if hasattr(self.compilers, 'FC'): C = 'f'
  443. else: C = 'c'
  444. raise RuntimeError('Could not find a functional BLAS. Run with --with-blas-lib=<lib> to indicate the library containing BLAS.\n Or --download-'+C+'-blas-lapack=1 to have one automatically downloaded and installed\n')
  445. if not self.foundLapack:
  446. # check for split blas/blas-dev packages
  447. import glob
  448. llib = glob.glob('/usr/lib/liblapack.*')
  449. if llib != [] and not (os.path.isfile('/usr/lib/liblapack.so') or os.path.isfile('/usr/lib/liblapack.a')):
  450. raise RuntimeError('Incomplete LAPACK install; Perhaps lapack package is installed - but lapack-dev/lapack-devel is required?')
  451. if hasattr(self.compilers, 'FC'): C = 'f'
  452. else: C = 'c'
  453. raise RuntimeError('Could not find a functional LAPACK. Run with --with-lapack-lib=<lib> to indicate the library containing LAPACK.\n Or --download-'+C+'-blas-lapack=1 to have one automatically downloaded and installed\n')
  454. # allow user to dictate which blas/lapack mangling to use (some blas/lapack libraries, like on Apple, provide several)
  455. if 'known-blaslapack-mangling' in self.argDB:
  456. self.mangling = self.argDB['known-blaslapack-mangling']
  457. if self.mangling == 'underscore':
  458. self.addDefine('BLASLAPACK_UNDERSCORE', 1)
  459. elif self.mangling == 'caps':
  460. self.addDefine('BLASLAPACK_CAPS', 1)
  461. elif self.mangling == 'stdcall':
  462. self.addDefine('BLASLAPACK_STDCALL', 1)
  463. self.found = 1
  464. return
  465. def checkESSL(self):
  466. '''Check for the IBM ESSL library'''
  467. if self.libraries.check(self.lapackLibrary, 'iessl'):
  468. self.addDefine('HAVE_ESSL',1)
  469. return
  470. def checkPESSL(self):
  471. '''Check for the IBM PESSL library - and error out - if used instead of ESSL'''
  472. if self.libraries.check(self.lapackLibrary, 'ipessl'):
  473. raise RuntimeError('Cannot use PESSL instead of ESSL!')
  474. return
  475. def checkMissing(self):
  476. '''Check for missing LAPACK routines'''
  477. if self.foundLapack:
  478. mangleFunc = hasattr(self.compilers, 'FC') and not self.f2c
  479. for baseName in ['trsen','gerfs','gges','tgsen','gesvd','getrf','getrs','geev','gelss','syev','syevx','sygv','sygvx','potrf','potrs','stebz','pttrf','pttrs','stein','orgqr','geqrf','gesv','hseqr','geqrf','steqr']:
  480. prefix = self.getPrefix()
  481. if self.f2c:
  482. if self.mangling == 'underscore':
  483. routine = prefix+baseName+'_'
  484. else:
  485. routine = prefix+baseName
  486. else:
  487. routine = prefix+baseName
  488. oldLibs = self.compilers.LIBS
  489. if not self.libraries.check(self.lapackLibrary, routine, otherLibs = self.getOtherLibs(), fortranMangle = mangleFunc):
  490. self.missingRoutines.append(baseName)
  491. self.addDefine('MISSING_LAPACK_'+baseName.upper(), 1)
  492. self.compilers.LIBS = oldLibs
  493. return
  494. def checklsame(self):
  495. ''' Do the BLAS/LAPACK libraries have a valid lsame() function with correction binding. Lion and xcode 4.2 do not'''
  496. routine = 'lsame';
  497. if self.f2c:
  498. if self.mangling == 'underscore':
  499. routine = routine + '_'
  500. else:
  501. routine = self.compilers.mangleFortranFunction(routine)
  502. if not self.libraries.check(self.dlib,routine,fortranMangle = 0):
  503. self.addDefine('MISSING_LAPACK_'+routine, 1)
  504. def checkForRoutine(self,routine):
  505. ''' used by other packages to see if a BLAS routine is available
  506. This is not really correct because other packages do not (usually) know about f2cblasLapack'''
  507. if self.f2c:
  508. if self.mangling == 'underscore':
  509. return self.libraries.check(self.dlib,routine+'_')
  510. else:
  511. return self.libraries.check(self.dlib,routine)
  512. else:
  513. return self.libraries.check(self.dlib,routine,fortranMangle = hasattr(self.compilers, 'FC'))
  514. def check64BitBLASIndices(self):
  515. '''Check for and use 64bit integer blas'''
  516. if 'known-64-bit-blas-indices' in self.argDB:
  517. if int(self.argDB['known-64-bit-blas-indices']):
  518. self.addDefine('HAVE_64BIT_BLAS_INDICES', 1)
  519. return
  520. def configure(self):
  521. self.executeTest(self.configureLibrary)
  522. self.executeTest(self.check64BitBLASIndices)
  523. self.executeTest(self.checkESSL)
  524. self.executeTest(self.checkPESSL)
  525. self.executeTest(self.checkMissing)
  526. self.executeTest(self.checklsame)
  527. return
  528. if __name__ == '__main__':
  529. import config.framework
  530. import sys
  531. framework = config.framework.Framework(sys.argv[1:])
  532. framework.setupLogging()
  533. framework.children.append(Configure(framework))
  534. framework.configure()
  535. framework.dumpSubstitutions()