PageRenderTime 66ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

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

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