xref: /petsc/config/PETSc/Configure.py (revision 2e0aa6f095b7ddcaec754bc09276df3f6c1ffe42)
1import config.base
2
3import os
4import sys
5import re
6import cPickle
7import string
8
9# The sorted() builtin is not available with python-2.3
10try: sorted
11except NameError:
12  def sorted(lst):
13    lst.sort()
14    return lst
15
16class Configure(config.base.Configure):
17  def __init__(self, framework):
18    config.base.Configure.__init__(self, framework)
19    self.headerPrefix = 'PETSC'
20    self.substPrefix  = 'PETSC'
21    self.installed = 0 # 1 indicates that Configure itself has already compiled and installed PETSc
22    return
23
24  def __str2__(self):
25    desc = []
26    if not self.installed:
27      desc.append('xxx=========================================================================xxx')
28      if self.make.getMakeMacro('MAKE_IS_GNUMAKE'):
29        build_type = 'gnumake build'
30      elif self.getMakeMacro('PETSC_BUILD_USING_CMAKE'):
31        build_type = 'cmake build'
32      else:
33        build_type = 'legacy build'
34      desc.append(' Configure stage complete. Now build PETSc libraries with (%s):' % build_type)
35      desc.append('   make PETSC_DIR='+self.petscdir.dir+' PETSC_ARCH='+self.arch.arch+' all')
36      desc.append('xxx=========================================================================xxx')
37    else:
38      desc.append('xxx=========================================================================xxx')
39      desc.append(' Installation complete. You do not need to run make to compile or install the software')
40      desc.append('xxx=========================================================================xxx')
41    return '\n'.join(desc)+'\n'
42
43  def setupHelp(self, help):
44    import nargs
45    help.addArgument('PETSc',  '-prefix=<dir>',                   nargs.Arg(None, '', 'Specifiy location to install PETSc (eg. /usr/local)'))
46    help.addArgument('PETSc',  '-with-prefetch=<bool>',           nargs.ArgBool(None, 1,'Enable checking for prefetch instructions'))
47    help.addArgument('Windows','-with-windows-graphics=<bool>',   nargs.ArgBool(None, 1,'Enable check for Windows Graphics'))
48    help.addArgument('PETSc', '-with-default-arch=<bool>',        nargs.ArgBool(None, 1, 'Allow using the last configured arch without setting PETSC_ARCH'))
49    help.addArgument('PETSc','-with-single-library=<bool>',       nargs.ArgBool(None, 1,'Put all PETSc code into the single -lpetsc library'))
50    help.addArgument('PETSc','-with-fortran-bindings=<bool>',     nargs.ArgBool(None, 1,'Build PETSc fortran bindings in the library and corresponding module files'))
51    help.addArgument('PETSc', '-with-ios=<bool>',              nargs.ArgBool(None, 0, 'Build an iPhone/iPad version of PETSc library'))
52    help.addArgument('PETSc', '-with-xsdk-defaults', nargs.ArgBool(None, 0, 'Set the following as defaults for the xSDK standard: --enable-debug=1, --enable-shared=1, --with-precision=double, --with-index-size=32, locate blas/lapack automatically'))
53    help.addArgument('PETSc', '-known-has-attribute-aligned=<bool>',nargs.ArgBool(None, None, 'Indicates __attribute((aligned(16)) directive works (the usual test will be skipped)'))
54    help.addArgument('PETSc', '-with-display=<x11display>',       nargs.Arg(None, '', 'Specifiy DISPLAY env variable for use with matlab test)'))
55    return
56
57  def registerPythonFile(self,filename,directory):
58    ''' Add a python file to the framework and registers its headerprefix, ... externalpackagedir
59        directory is the directory where the file relative to the BuildSystem or config path in python notation with . '''
60    (utilityName, ext) = os.path.splitext(filename)
61    if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__':
62      if directory: directory = directory+'.'
63      utilityObj                             = self.framework.require(directory+utilityName, self)
64      utilityObj.headerPrefix                = self.headerPrefix
65      utilityObj.archProvider                = self.arch
66      utilityObj.languageProvider            = self.languages
67      utilityObj.installDirProvider          = self.installdir
68      utilityObj.externalPackagesDirProvider = self.externalpackagesdir
69      utilityObj.precisionProvider           = self.scalartypes
70      utilityObj.indexProvider               = self.indexTypes
71      setattr(self, utilityName.lower(), utilityObj)
72      return utilityObj
73    return None
74
75  def setupDependencies(self, framework):
76    config.base.Configure.setupDependencies(self, framework)
77    self.programs      = framework.require('config.programs',           self)
78    self.setCompilers  = framework.require('config.setCompilers',       self)
79    self.compilers     = framework.require('config.compilers',          self)
80    self.arch          = framework.require('PETSc.options.arch',        self.setCompilers)
81    self.petscdir      = framework.require('PETSc.options.petscdir',    self.arch)
82    self.installdir    = framework.require('PETSc.options.installDir',  self)
83    self.scalartypes   = framework.require('PETSc.options.scalarTypes', self)
84    self.indexTypes    = framework.require('PETSc.options.indexTypes',  self)
85    self.languages     = framework.require('PETSc.options.languages',   self.setCompilers)
86    self.indexTypes    = framework.require('PETSc.options.indexTypes',  self.compilers)
87    self.compilers     = framework.require('config.compilers',          self)
88    self.types         = framework.require('config.types',              self)
89    self.headers       = framework.require('config.headers',            self)
90    self.functions     = framework.require('config.functions',          self)
91    self.libraries     = framework.require('config.libraries',          self)
92    self.atomics       = framework.require('config.atomics',            self)
93    self.make          = framework.require('config.packages.make',      self)
94    self.blasLapack    = framework.require('config.packages.BlasLapack',self)
95    self.cmake         = framework.require('config.packages.cmake',self)
96    self.externalpackagesdir = framework.require('PETSc.options.externalpackagesdir',self)
97    self.mpi           = framework.require('config.packages.MPI',self)
98
99    for utility in sorted(os.listdir(os.path.join('config','PETSc','options'))):
100      self.registerPythonFile(utility,'PETSc.options')
101
102    for utility in sorted(os.listdir(os.path.join('config','BuildSystem','config','utilities'))):
103      self.registerPythonFile(utility,'config.utilities')
104
105    for package in sorted(os.listdir(os.path.join('config', 'BuildSystem', 'config', 'packages'))):
106      obj = self.registerPythonFile(package,'config.packages')
107      if obj:
108        obj.archProvider                = self.framework.requireModule(obj.archProvider, obj)
109        obj.languageProvider            = self.framework.requireModule(obj.languageProvider, obj)
110        obj.installDirProvider          = self.framework.requireModule(obj.installDirProvider, obj)
111        obj.externalPackagesDirProvider = self.framework.requireModule(obj.externalPackagesDirProvider, obj)
112        obj.precisionProvider           = self.framework.requireModule(obj.precisionProvider, obj)
113        obj.indexProvider               = self.framework.requireModule(obj.indexProvider, obj)
114
115    # Force blaslapack and opencl to depend on scalarType so precision is set before BlasLapack is built
116    framework.require('PETSc.options.scalarTypes', self.f2cblaslapack)
117    framework.require('PETSc.options.scalarTypes', self.fblaslapack)
118    framework.require('PETSc.options.scalarTypes', self.blaslapack)
119    framework.require('PETSc.options.scalarTypes', self.opencl)
120
121    self.programs.headerPrefix   = self.headerPrefix
122    self.compilers.headerPrefix  = self.headerPrefix
123    self.types.headerPrefix      = self.headerPrefix
124    self.headers.headerPrefix    = self.headerPrefix
125    self.functions.headerPrefix  = self.headerPrefix
126    self.libraries.headerPrefix  = self.headerPrefix
127
128    # Look for any user provided --download-xxx=directory packages
129    for arg in sys.argv:
130      if arg.startswith('--download-') and arg.find('=') > -1:
131        pname = arg[11:arg.find('=')]
132        if not hasattr(self,pname):
133          dname = os.path.dirname(arg[arg.find('=')+1:])
134          if os.path.isdir(dname) and not os.path.isfile(os.path.join(dname,pname+'.py')):
135            self.framework.logPrint('User is registering a new package: '+arg)
136            sys.path.append(dname)
137            self.registerPythonFile(pname+'.py','')
138
139    # test for a variety of basic headers and functions
140    headersC = map(lambda name: name+'.h', ['setjmp','dos', 'endian', 'fcntl', 'float', 'io', 'limits', 'malloc', 'pwd', 'search', 'strings',
141                                            'unistd', 'sys/sysinfo', 'machine/endian', 'sys/param', 'sys/procfs', 'sys/resource',
142                                            'sys/systeminfo', 'sys/times', 'sys/utsname','string', 'stdlib',
143                                            'sys/socket','sys/wait','netinet/in','netdb','Direct','time','Ws2tcpip','sys/types',
144                                            'WindowsX', 'cxxabi','float','ieeefp','stdint','sched','pthread','inttypes','immintrin','zmmintrin'])
145    functions = ['access', '_access', 'clock', 'drand48', 'getcwd', '_getcwd', 'getdomainname', 'gethostname',
146                 'gettimeofday', 'getwd', 'memalign', 'mkstemp', 'popen', 'PXFGETARG', 'rand', 'getpagesize',
147                 'readlink', 'realpath',  'sigaction', 'signal', 'sigset', 'usleep', 'sleep', '_sleep', 'socket',
148                 'times', 'gethostbyname', 'uname','snprintf','_snprintf','lseek','_lseek','time','fork','stricmp',
149                 'strcasecmp', 'bzero', 'dlopen', 'dlsym', 'dlclose', 'dlerror','get_nprocs','sysctlbyname',
150                 '_set_output_format','_mkdir']
151    libraries1 = [(['socket', 'nsl'], 'socket'), (['fpe'], 'handle_sigfpes')]
152    self.headers.headers.extend(headersC)
153    self.functions.functions.extend(functions)
154    self.libraries.libraries.extend(libraries1)
155
156    return
157
158  def DumpPkgconfig(self):
159    ''' Create a pkg-config file '''
160    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig')):
161      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig'))
162    fd = open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig','PETSc.pc'),'w')
163    cflags_inc = ['-I${includedir}']
164    if self.framework.argDB['prefix']:
165      fd.write('prefix='+self.installdir.dir+'\n')
166    else:
167      fd.write('prefix='+os.path.join(self.petscdir.dir, self.arch.arch)+'\n')
168      cflags_inc.append('-I' + os.path.join(self.petscdir.dir, 'include'))
169    fd.write('exec_prefix=${prefix}\n')
170    fd.write('includedir=${prefix}/include\n')
171    fd.write('libdir=${prefix}/lib\n')
172
173    self.setCompilers.pushLanguage('C')
174    fd.write('ccompiler='+self.setCompilers.getCompiler()+'\n')
175    fd.write('cflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
176    fd.write('cflags_dep='+self.compilers.dependenciesGenerationFlag.get('C','')+'\n')
177    fd.write('ldflag_rpath='+self.setCompilers.CSharedLinkerFlag+'\n')
178    self.setCompilers.popLanguage()
179    if hasattr(self.compilers, 'C++'):
180      self.setCompilers.pushLanguage('C++')
181      fd.write('cxxcompiler='+self.setCompilers.getCompiler()+'\n')
182      fd.write('cxxflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
183      self.setCompilers.popLanguage()
184    if hasattr(self.compilers, 'FC'):
185      self.setCompilers.pushLanguage('FC')
186      fd.write('fcompiler='+self.setCompilers.getCompiler()+'\n')
187      fd.write('fflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
188      self.setCompilers.popLanguage()
189
190    fd.write('\n')
191    fd.write('Name: PETSc\n')
192    fd.write('Description: Library to solve ODEs and algebraic equations\n')
193    fd.write('Version: %s\n' % self.petscdir.version)
194    fd.write('Cflags: ' + ' '.join([self.setCompilers.CPPFLAGS] + cflags_inc) + '\n')
195    fd.write('Libs: '+self.libraries.toStringNoDupes(['-L${libdir}', self.petsclib], with_rpath=False)+'\n')
196    # Remove RPATH flags from library list.  User can add them using
197    # pkg-config --variable=ldflag_rpath and pkg-config --libs-only-L
198    fd.write('Libs.private: '+self.libraries.toStringNoDupes([f for f in self.packagelibs+self.complibs if not f.startswith(self.setCompilers.CSharedLinkerFlag)], with_rpath=False)+'\n')
199
200    fd.close()
201    return
202
203  def DumpModule(self):
204    ''' Create a module file '''
205    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules')):
206      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules'))
207    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc')):
208      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc'))
209    if self.framework.argDB['prefix']:
210      installdir  = self.installdir.dir
211      installarch = ''
212      installpath = os.path.join(installdir,'bin')
213    else:
214      installdir  = self.petscdir.dir
215      installarch = self.arch.arch
216      installpath = os.path.join(installdir,installarch,'bin')+':'+os.path.join(installdir,'bin')
217    fd = open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc',self.petscdir.version),'w')
218    fd.write('''\
219#%%Module
220
221proc ModulesHelp { } {
222    puts stderr "This module sets the path and environment variables for petsc-%s"
223    puts stderr "     see http://www.mcs.anl.gov/petsc/ for more information      "
224    puts stderr ""
225}
226module-whatis "PETSc - Portable, Extensible Toolkit for Scientific Computation"
227
228set petsc_dir   "%s"
229set petsc_arch  "%s"
230
231setenv PETSC_ARCH "$petsc_arch"
232setenv PETSC_DIR "$petsc_dir"
233prepend-path PATH "%s"
234''' % (self.petscdir.version, installdir, installarch, installpath))
235    fd.close()
236    return
237
238  def Dump(self):
239    ''' Actually put the values into the configuration files '''
240    # eventually everything between -- should be gone
241    if self.mpi.usingMPIUni:
242      #
243      # Remove any MPI/MPICH include files that may have been put here by previous runs of ./configure
244      self.executeShellCommand('rm -rf  '+os.path.join(self.petscdir.dir,self.arch.arch,'include','mpi*')+' '+os.path.join(self.petscdir.dir,self.arch.arch,'include','opa*'), log = self.log)
245
246    self.setCompilers.pushLanguage('C')
247    compiler = self.setCompilers.getCompiler()
248    if compiler.endswith('mpicc') or compiler.endswith('mpiicc'):
249      try:
250        output   = self.executeShellCommand(compiler + ' -show', log = self.log)[0]
251        compiler = output.split(' ')[0]
252        self.addDefine('MPICC_SHOW','"'+output.strip().replace('\n','\\\\n')+'"')
253      except:
254        self.addDefine('MPICC_SHOW','"Unavailable"')
255    else:
256      self.addDefine('MPICC_SHOW','"Unavailable"')
257    self.setCompilers.popLanguage()
258#-----------------------------------------------------------------------------------------------------
259
260    # Sometimes we need C compiler, even if built with C++
261    self.setCompilers.pushLanguage('C')
262    self.addMakeMacro('CC_FLAGS',self.setCompilers.getCompilerFlags())
263    self.setCompilers.popLanguage()
264
265    # And sometimes we need a C++ compiler even when PETSc is built with C
266    if hasattr(self.compilers, 'CXX'):
267      self.setCompilers.pushLanguage('Cxx')
268      self.addDefine('HAVE_CXX','1')
269      self.addMakeMacro('CXX_FLAGS',self.setCompilers.getCompilerFlags())
270      cxx_linker = self.setCompilers.getLinker()
271      self.addMakeMacro('CXX_LINKER',cxx_linker)
272      self.addMakeMacro('CXX_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
273      self.setCompilers.popLanguage()
274
275    # C preprocessor values
276    self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS)
277
278    # compiler values
279    self.setCompilers.pushLanguage(self.languages.clanguage)
280    self.addMakeMacro('PCC',self.setCompilers.getCompiler())
281    self.addMakeMacro('PCC_FLAGS',self.setCompilers.getCompilerFlags())
282    self.setCompilers.popLanguage()
283    # .o or .obj
284    self.addMakeMacro('CC_SUFFIX','o')
285
286    # executable linker values
287    self.setCompilers.pushLanguage(self.languages.clanguage)
288    pcc_linker = self.setCompilers.getLinker()
289    self.addMakeMacro('PCC_LINKER',pcc_linker)
290    self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
291    self.setCompilers.popLanguage()
292    # '' for Unix, .exe for Windows
293    self.addMakeMacro('CC_LINKER_SUFFIX','')
294
295    if hasattr(self.compilers, 'FC'):
296      if self.framework.argDB['with-fortran-bindings']:
297        self.addDefine('HAVE_FORTRAN','1')
298      self.setCompilers.pushLanguage('FC')
299      # need FPPFLAGS in config/setCompilers
300      self.addMakeMacro('FPP_FLAGS',self.setCompilers.CPPFLAGS)
301
302      # compiler values
303      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
304      self.setCompilers.popLanguage()
305      # .o or .obj
306      self.addMakeMacro('FC_SUFFIX','o')
307
308      # executable linker values
309      self.setCompilers.pushLanguage('FC')
310      # Cannot have NAG f90 as the linker - so use pcc_linker as fc_linker
311      fc_linker = self.setCompilers.getLinker()
312      if config.setCompilers.Configure.isNAG(fc_linker, self.log):
313        self.addMakeMacro('FC_LINKER',pcc_linker)
314      else:
315        self.addMakeMacro('FC_LINKER',fc_linker)
316      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
317      # apple requires this shared library linker flag on SOME versions of the os
318      if self.setCompilers.getLinkerFlags().find('-Wl,-commons,use_dylibs') > -1:
319        self.addMakeMacro('DARWIN_COMMONS_USE_DYLIBS',' -Wl,-commons,use_dylibs ')
320      self.setCompilers.popLanguage()
321
322      # F90 Modules
323      if self.setCompilers.fortranModuleIncludeFlag:
324        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
325      else: # for non-f90 compilers like g77
326        self.addMakeMacro('FC_MODULE_FLAG', '-I')
327      if self.setCompilers.fortranModuleIncludeFlag:
328        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
329    else:
330      self.addMakeMacro('FC','')
331
332    if hasattr(self.compilers, 'CUDAC'):
333      self.setCompilers.pushLanguage('CUDA')
334      self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags())
335      self.setCompilers.popLanguage()
336
337    # shared library linker values
338    self.setCompilers.pushLanguage(self.languages.clanguage)
339    # need to fix BuildSystem to collect these separately
340    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
341    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
342    self.setCompilers.popLanguage()
343    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
344    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
345    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
346      self.addMakeMacro('SL_LINKER_SUFFIX', '')
347      self.addDefine('SLSUFFIX','""')
348    else:
349      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
350      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
351
352    self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}')
353
354#-----------------------------------------------------------------------------------------------------
355
356    # CONLY or CPP. We should change the PETSc makefiles to do this better
357    if self.languages.clanguage == 'C': lang = 'CONLY'
358    else: lang = 'CXXONLY'
359    self.addMakeMacro('PETSC_LANGUAGE',lang)
360
361    # real or complex
362    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
363    # double or float
364    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
365
366    if self.framework.argDB['with-batch']:
367      self.addMakeMacro('PETSC_WITH_BATCH','1')
368
369    # Test for compiler-specific macros that need to be defined.
370    if self.setCompilers.isCrayVector('CC', self.log):
371      self.addDefine('HAVE_CRAY_VECTOR','1')
372
373#-----------------------------------------------------------------------------------------------------
374    if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket') and self.headers.haveHeader('netinet/in.h'):
375      self.addDefine('USE_SOCKET_VIEWER','1')
376      if self.checkCompile('#include <sys/socket.h>','setsockopt(0,SOL_SOCKET,SO_REUSEADDR,0,0)'):
377        self.addDefine('HAVE_SO_REUSEADDR','1')
378
379#-----------------------------------------------------------------------------------------------------
380    # print include and lib for makefiles
381    self.framework.packages.reverse()
382    petscincludes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')]
383    petscincludes_install = [os.path.join(self.installdir.dir, 'include')] if self.framework.argDB['prefix'] else petscincludes
384    includes = []
385    self.packagelibs = []
386    for i in self.framework.packages:
387      if i.useddirectly:
388        self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
389      if not isinstance(i.lib, list):
390        i.lib = [i.lib]
391      if i.linkedbypetsc: self.packagelibs.extend(i.lib)
392      self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib))
393      if hasattr(i,'include'):
394        if not isinstance(i.include,list):
395          i.include = [i.include]
396        includes.extend(i.include)
397        self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include))
398    if self.framework.argDB['with-single-library']:
399      self.petsclib = '-lpetsc'
400    else:
401      self.petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
402    self.complibs = self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split()
403    self.PETSC_WITH_EXTERNAL_LIB = self.libraries.toStringNoDupes(['-L${PETSC_DIR}/${PETSC_ARCH}/lib', self.petsclib]+self.packagelibs+self.complibs)
404    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(self.packagelibs+self.complibs)
405    if self.framework.argDB['prefix'] and self.setCompilers.CSharedLinkerFlag not in ['-L']:
406      string.replace(self.PETSC_EXTERNAL_LIB_BASIC,self.setCompilers.CSharedLinkerFlag+os.path.join(self.petscdir.dir,self.arch.arch,'lib'),self.setCompilers.CSharedLinkerFlag+os.path.join(self.installdir.dir,'lib'))
407
408    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.PETSC_EXTERNAL_LIB_BASIC)
409    allincludes = petscincludes + includes
410    allincludes_install = petscincludes_install + includes
411    self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(allincludes)
412    self.PETSC_CC_INCLUDES_INSTALL = self.headers.toStringNoDupes(allincludes_install)
413    self.addMakeMacro('PETSC_CC_INCLUDES',self.PETSC_CC_INCLUDES)
414    self.addMakeMacro('PETSC_CC_INCLUDES_INSTALL', self.PETSC_CC_INCLUDES_INSTALL)
415    if hasattr(self.compilers, 'FC'):
416      def modinc(includes):
417        return includes if self.compilers.fortranIsF90 else []
418      self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(allincludes,modinc(allincludes)))
419      self.addMakeMacro('PETSC_FC_INCLUDES_INSTALL',self.headers.toStringNoDupes(allincludes_install,modinc(allincludes_install)))
420
421    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"')
422
423    if self.framework.argDB['with-single-library']:
424      # overrides the values set in conf/variables
425      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
426      self.addMakeMacro('SHLIBS','libpetsc')
427      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
428      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
429      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
430      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
431      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.PETSC_WITH_EXTERNAL_LIB)
432      self.addDefine('USE_SINGLE_LIBRARY', '1')
433      if self.sharedlibraries.useShared:
434        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
435        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
436        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
437        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
438        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
439        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
440        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
441        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
442        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
443        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
444        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
445      else:
446        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
447        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
448        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
449        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
450        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
451        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
452        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
453        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
454        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
455        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
456        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
457
458    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
459      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
460
461# add a makefile endtry for display
462    if self.framework.argDB['with-display']:
463      self.addMakeMacro('DISPLAY',self.framework.argDB['with-display'])
464
465    # add a makefile entry for configure options
466    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
467    return
468
469  def dumpConfigInfo(self):
470    import time
471    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
472    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
473    fd.close()
474    return
475
476  def dumpMachineInfo(self):
477    import platform
478    import datetime
479    import time
480    import script
481    def escape(s):
482      return s.replace('"',r'\"').replace(r'\ ',r'\\ ')
483    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
484    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
485    fd.write('\"-----------------------------------------\\n\"\n')
486    buildhost = platform.node()
487    if os.environ.get('SOURCE_DATE_EPOCH'):
488      buildhost = "reproducible"
489    buildtime = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
490    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (buildtime, buildhost))
491    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
492    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir)))
493    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch)))
494    fd.write('\"-----------------------------------------\\n\";\n')
495    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
496    self.setCompilers.pushLanguage(self.languages.clanguage)
497    fd.write('\"Using C compiler: %s %s \\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
498    self.setCompilers.popLanguage()
499    if hasattr(self.compilers, 'FC'):
500      self.setCompilers.pushLanguage('FC')
501      fd.write('\"Using Fortran compiler: %s %s  %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
502      self.setCompilers.popLanguage()
503    fd.write('\"-----------------------------------------\\n\";\n')
504    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
505    fd.write('\"Using include paths: %s\\n\"\n' % (escape(self.PETSC_CC_INCLUDES_INSTALL.replace('${PETSC_DIR}', self.installdir.petscDir))))
506    fd.write('\"-----------------------------------------\\n\";\n')
507    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
508    self.setCompilers.pushLanguage(self.languages.clanguage)
509    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
510    self.setCompilers.popLanguage()
511    if hasattr(self.compilers, 'FC'):
512      self.setCompilers.pushLanguage('FC')
513      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
514      self.setCompilers.popLanguage()
515    fd.write('\"Using libraries: %s%s -L%s %s %s\\n\"\n' % (escape(self.setCompilers.CSharedLinkerFlag), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(self.petsclib), escape(self.PETSC_EXTERNAL_LIB_BASIC)))
516    fd.write('\"-----------------------------------------\\n\";\n')
517    fd.close()
518    return
519
520  def dumpCMakeConfig(self):
521    '''
522    Writes configuration-specific values to ${PETSC_ARCH}/lib/petsc/conf/PETScBuildInternal.cmake.
523    This file is private to PETSc and should not be included by third parties
524    (a suitable file can be produced later by CMake, but this is not it).
525    '''
526    def cmakeset(fd,key,val=True):
527      if val == True: val = 'YES'
528      if val == False: val = 'NO'
529      fd.write('set (' + key + ' ' + val + ')\n')
530    def ensurelist(a):
531      if isinstance(a,list):
532        return a
533      else:
534        return [a]
535    def libpath(lib):
536      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
537      if not isinstance(lib,str): return ''
538      if lib.startswith('-L'): return lib[2:]
539      if lib.startswith('-R'): return lib[2:]
540      if lib.startswith('-Wl,-rpath,'):
541        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
542        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
543        # corresponding library.
544        return lib[len('-Wl,-rpath,'):]
545      if lib.startswith('-'): return ''
546      return os.path.dirname(lib)
547    def cleanlib(lib):
548      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
549      if not isinstance(lib,str): return ''
550      if lib.startswith('-l'):  return lib[2:]
551      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
552      lib = os.path.splitext(os.path.basename(lib))[0]
553      if lib.startswith('lib'): return lib[3:]
554      return lib
555    def nub(lst):
556      'Return a list containing the first occurrence of each unique element'
557      unique = []
558      for elem in lst:
559        if elem not in unique and elem != '':
560          unique.append(elem)
561      return unique
562    try: reversed # reversed was added in Python-2.4
563    except NameError:
564      def reversed(lst): return lst[::-1]
565    def nublast(lst):
566      'Return a list containing the last occurrence of each unique entry in a list'
567      return reversed(nub(reversed(lst)))
568    def cmakeexpand(varname):
569      return r'"${' + varname + r'}"'
570    def uniqextend(lst,new):
571      for x in ensurelist(new):
572        if x not in lst:
573          lst.append(x)
574    def notstandardinclude(path):
575      return path not in '/usr/include'.split() # /usr/local/include is not automatically included on FreeBSD
576    def writeMacroDefinitions(fd):
577      if self.mpi.usingMPIUni:
578        cmakeset(fd,'PETSC_HAVE_MPIUNI')
579      for pkg in self.framework.packages:
580        if pkg.useddirectly:
581          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE.replace('-','_'))
582        for pair in pkg.defines.items():
583          if pair[0].startswith('HAVE_') and pair[1]:
584            cmakeset(fd, self.framework.getFullDefineName(pkg, pair[0]), pair[1])
585      for name,val in self.functions.defines.items():
586        cmakeset(fd,'PETSC_'+name,val)
587      for dct in [self.defines, self.libraryoptions.defines]:
588        for k,v in dct.items():
589          if k.startswith('USE_'):
590            cmakeset(fd,'PETSC_' + k, v)
591      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
592      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
593      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
594      if hasattr(self.compilers, 'FC'):
595        cmakeset(fd,'PETSC_HAVE_FORTRAN')
596        if self.compilers.fortranIsF90:
597          cmakeset(fd,'PETSC_USING_F90')
598        if self.compilers.fortranIsF2003:
599          cmakeset(fd,'PETSC_USING_F2003')
600      if hasattr(self.compilers, 'CXX'):
601        cmakeset(fd,'PETSC_HAVE_CXX')
602      if self.sharedlibraries.useShared:
603        cmakeset(fd,'BUILD_SHARED_LIBS')
604    def writeBuildFlags(fd):
605      def extendby(lib):
606        libs = ensurelist(lib)
607        lib_paths.extend(map(libpath,libs))
608        lib_libs.extend(map(cleanlib,libs))
609      lib_paths = []
610      lib_libs  = []
611      includes  = []
612      libvars   = []
613      for pkg in self.framework.packages:
614        if pkg.linkedbypetsc:
615          extendby(pkg.lib)
616          uniqextend(includes,pkg.include)
617      extendby(self.libraries.math)
618      extendby(self.libraries.rt)
619      extendby(self.compilers.flibs)
620      extendby(self.compilers.cxxlibs)
621      extendby(self.compilers.LIBS.split())
622      for libname in nublast(lib_libs):
623        libvar = 'PETSC_' + libname.upper() + '_LIB'
624        addpath = ''
625        for lpath in nublast(lib_paths):
626          addpath += '"' + str(lpath) + '" '
627        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
628        libvars.append(libvar)
629      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
630      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
631      includes = filter(notstandardinclude,includes)
632      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',includes)) + ')\n')
633    fd = open(os.path.join(self.arch.arch,'lib','petsc','conf','PETScBuildInternal.cmake'), 'w')
634    writeMacroDefinitions(fd)
635    writeBuildFlags(fd)
636    fd.close()
637    return
638
639  def dumpCMakeLists(self):
640    import sys
641    if sys.version_info >= (2,4):
642      import cmakegen
643      try:
644        cmakegen.main(self.petscdir.dir, log=self.framework.log)
645      except (OSError) as e:
646        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
647    else:
648      self.framework.logPrint('Skipping cmakegen due to old python version: ' +str(sys.version_info) )
649
650  def cmakeBoot(self):
651    import sys
652    self.cmakeboot_success = False
653    if sys.version_info >= (2,4) and hasattr(self.cmake,'cmake'):
654      oldRead = self.argDB.readonly
655      self.argDB.readonly = True
656      try:
657        import cmakeboot
658        self.cmakeboot_success = cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
659      except (OSError) as e:
660        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
661      except (ImportError, KeyError) as e:
662        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
663      self.argDB.readonly = oldRead
664      if self.cmakeboot_success:
665        if hasattr(self.compilers, 'FC') and self.compilers.fortranIsF90 and not self.setCompilers.fortranModuleOutputFlag:
666          self.framework.logPrint('CMake configured successfully, but could not be used by default because of missing fortranModuleOutputFlag\n')
667        else:
668          self.framework.logPrint('CMake configured successfully, using as default build\n')
669          self.addMakeMacro('PETSC_BUILD_USING_CMAKE',1)
670      else:
671        self.framework.logPrint('CMake configuration was unsuccessful\n')
672    else:
673      self.framework.logPrint('Skipping cmakeboot due to old python version: ' +str(sys.version_info) )
674    return
675
676  def configurePrefetch(self):
677    '''Sees if there are any prefetch functions supported'''
678    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
679      self.addDefine('Prefetch(a,b,c)', ' ')
680      return
681    self.pushLanguage(self.languages.clanguage)
682    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
683      # The Intel Intrinsics manual [1] specifies the prototype
684      #
685      #   void _mm_prefetch(char const *a, int sel);
686      #
687      # but other vendors seem to insist on using subtly different
688      # prototypes, including void* for the pointer, and an enum for
689      # sel.  These are both reasonable changes, but negatively impact
690      # portability.
691      #
692      # [1] http://software.intel.com/file/6373
693      self.addDefine('HAVE_XMMINTRIN_H', 1)
694      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
695      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
696      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
697      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
698      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
699    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
700      self.addDefine('HAVE_XMMINTRIN_H', 1)
701      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
702      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
703      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
704      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
705      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
706    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
707      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
708      #
709      #   The value of rw is a compile-time constant one or zero; one
710      #   means that the prefetch is preparing for a write to the memory
711      #   address and zero, the default, means that the prefetch is
712      #   preparing for a read. The value locality must be a compile-time
713      #   constant integer between zero and three. A value of zero means
714      #   that the data has no temporal locality, so it need not be left
715      #   in the cache after the access. A value of three means that the
716      #   data has a high degree of temporal locality and should be left
717      #   in all levels of cache possible. Values of one and two mean,
718      #   respectively, a low or moderate degree of temporal locality.
719      #
720      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
721      # hints.  Using macros for these values in necessary since some
722      # compilers require an enum.
723      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
724      self.addDefine('PREFETCH_HINT_NTA', '0')
725      self.addDefine('PREFETCH_HINT_T0',  '3')
726      self.addDefine('PREFETCH_HINT_T1',  '2')
727      self.addDefine('PREFETCH_HINT_T2',  '1')
728    else:
729      self.addDefine('Prefetch(a,b,c)', ' ')
730    self.popLanguage()
731
732  def configureAtoll(self):
733    '''Checks if atoll exists'''
734    if self.checkLink('#define _POSIX_C_SOURCE 200112L\n#include <stdlib.h>','long v = atoll("25")') or self.checkLink ('#include <stdlib.h>','long v = atoll("25")'):
735       self.addDefine('HAVE_ATOLL', '1')
736
737  def configureUnused(self):
738    '''Sees if __attribute((unused)) is supported'''
739    if self.framework.argDB['with-ios']:
740      self.addDefine('UNUSED', ' ')
741      return
742    self.pushLanguage(self.languages.clanguage)
743    if self.checkLink('__attribute((unused)) static int myfunc(__attribute((unused)) void *name){ return 1;}', 'int i = 0;\nint j = myfunc(&i);\ntypedef void* atype;\n__attribute((unused))  atype a;\n'):
744      self.addDefine('UNUSED', '__attribute((unused))')
745    else:
746      self.addDefine('UNUSED', ' ')
747    self.popLanguage()
748
749  def configureIsatty(self):
750    '''Check if the Unix C function isatty() works correctly
751       Actually just assumes it does not work correctly on batch systems'''
752    if not self.framework.argDB['with-batch']:
753      self.addDefine('USE_ISATTY',1)
754
755  def configureDeprecated(self):
756    '''Check if __attribute((deprecated)) is supported'''
757    self.pushLanguage(self.languages.clanguage)
758    ## Recent versions of gcc and clang support __attribute((deprecated("string argument"))), which is very useful, but
759    ## Intel has conspired to make a supremely environment-sensitive compiler.  The Intel compiler looks at the gcc
760    ## executable in the environment to determine the language compatibility that it should attempt to emulate.  Some
761    ## important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g.,
762    ## 4.7).  Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc
763    ## found in the default user environment is older and does not support the argument.  If GCC and Intel were cool
764    ## like Clang and supported __has_attribute, we could avoid configure tests entirely, but they don't.  And that is
765    ## why we can't have nice things.
766    #
767    # if self.checkCompile("""__attribute((deprecated("Why you shouldn't use myfunc"))) static int myfunc(void) { return 1;}""", ''):
768    #   self.addDefine('DEPRECATED(why)', '__attribute((deprecated(why)))')
769    if self.checkCompile("""__attribute((deprecated)) static int myfunc(void) { return 1;}""", ''):
770      self.addDefine('DEPRECATED(why)', '__attribute((deprecated))')
771    else:
772      self.addDefine('DEPRECATED(why)', ' ')
773    self.popLanguage()
774
775  def configureAlign(self):
776    '''Check if __attribute(align) is supported'''
777    filename = 'conftestalign'
778    includes = '''
779#include <sys/types.h>
780#if STDC_HEADERS
781#include <stdlib.h>
782#include <stdio.h>
783#include <stddef.h>
784#endif\n'''
785    body     = '''
786struct mystruct {int myint;} __attribute((aligned(16)));
787FILE *f = fopen("'''+filename+'''", "w");
788if (!f) exit(1);
789fprintf(f, "%lu\\n", (unsigned long)sizeof(struct mystruct));
790'''
791    if 'known-has-attribute-aligned' in self.argDB:
792      if self.argDB['known-has-attribute-aligned']:
793        size = 16
794      else:
795        size = -3
796    elif not self.argDB['with-batch']:
797      self.pushLanguage(self.languages.clanguage)
798      try:
799        if self.checkRun(includes, body) and os.path.exists(filename):
800          f    = file(filename)
801          size = int(f.read())
802          f.close()
803          os.remove(filename)
804        else:
805          size = -4
806      except:
807        size = -1
808        self.framework.logPrint('Error checking attribute(aligned)')
809      self.popLanguage()
810    else:
811      self.framework.addBatchInclude(['#include <stdlib.h>', '#include <stdio.h>', '#include <sys/types.h>','struct mystruct {int myint;} __attribute((aligned(16)));'])
812      self.framework.addBatchBody('fprintf(output, "  \'--known-has-attribute-aligned=%d\',\\n", sizeof(struct mystruct)==16);')
813      size = -2
814    if size == 16:
815      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned (size)))')
816      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
817    else:
818      self.framework.logPrint('incorrect alignment. Found alignment:'+ str(size))
819      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
820    return
821
822  def configureExpect(self):
823    '''Sees if the __builtin_expect directive is supported'''
824    self.pushLanguage(self.languages.clanguage)
825    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
826      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
827    self.popLanguage()
828
829  def configureFunctionName(self):
830    '''Sees if the compiler supports __func__ or a variant.'''
831    def getFunctionName(lang):
832      name = '"unknown"'
833      self.pushLanguage(lang)
834      for fname in ['__func__','__FUNCTION__','__extension__ __func__']:
835        code = "if ("+fname+"[0] != 'm') return 1;"
836        if self.checkCompile('',code) and self.checkLink('',code):
837          name = fname
838          break
839      self.popLanguage()
840      return name
841    langs = []
842
843    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
844    if hasattr(self.compilers, 'CXX'):
845      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
846
847  def configureIntptrt(self):
848    '''Determine what to use for uintptr_t'''
849    def staticAssertSizeMatchesVoidStar(inc,typename):
850      # The declaration is an error if either array size is negative.
851      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
852      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
853                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
854    self.pushLanguage(self.languages.clanguage)
855    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
856      self.addDefine('UINTPTR_T', 'uintptr_t')
857    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
858      self.addDefine('UINTPTR_T', 'unsigned long long')
859    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
860      self.addDefine('UINTPTR_T', 'size_t')
861    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
862      self.addDefine('UINTPTR_T', 'unsigned long')
863    elif staticAssertSizeMatchesVoidStar('','unsigned'):
864      self.addDefine('UINTPTR_T', 'unsigned')
865    else:
866      raise RuntimeError('Could not find any unsigned integer type matching void*')
867    self.popLanguage()
868
869  def configureRTLDDefault(self):
870    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
871      self.addDefine('RTLD_DEFAULT','1')
872    return
873
874  def configureSolaris(self):
875    '''Solaris specific stuff'''
876    if os.path.isdir(os.path.join('/usr','ucblib')):
877      try:
878        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
879      except AttributeError:
880        flag = None
881      if flag is None:
882        self.compilers.LIBS += ' -L/usr/ucblib'
883      else:
884        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
885    return
886
887  def configureLinux(self):
888    '''Linux specific stuff'''
889    # TODO: Test for this by mallocing an odd number of floats and checking the address
890    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
891    return
892
893  def configureWin32(self):
894    '''Win32 non-cygwin specific stuff'''
895    kernel32=0
896    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
897      self.addDefine('HAVE_WINDOWS_H',1)
898      self.addDefine('HAVE_GETCOMPUTERNAME',1)
899      kernel32=1
900    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
901      self.addDefine('HAVE_WINDOWS_H',1)
902      self.addDefine('HAVE_GETCOMPUTERNAME',1)
903      kernel32=1
904    if kernel32:
905      if self.framework.argDB['with-windows-graphics']:
906        self.addDefine('USE_WINDOWS_GRAPHICS',1)
907      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
908        self.addDefine('HAVE_LOADLIBRARY',1)
909      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
910        self.addDefine('HAVE_GETPROCADDRESS',1)
911      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
912        self.addDefine('HAVE_FREELIBRARY',1)
913      if self.checkLink('#include <Windows.h>','GetLastError()'):
914        self.addDefine('HAVE_GETLASTERROR',1)
915      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
916        self.addDefine('HAVE_SETLASTERROR',1)
917      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
918        self.addDefine('USE_MICROSOFT_TIME',1)
919    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
920      self.addDefine('HAVE_GET_USER_NAME',1)
921    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
922      self.addDefine('HAVE_GET_USER_NAME',1)
923
924    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
925      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
926    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
927      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
928
929    self.types.check('int32_t', 'int')
930    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
931      self.addTypedef('int', 'uid_t')
932      self.addTypedef('int', 'gid_t')
933    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
934      self.framework.addDefine('R_OK', '04')
935      self.framework.addDefine('W_OK', '02')
936      self.framework.addDefine('X_OK', '01')
937    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
938      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
939      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
940    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
941      self.addDefine('HAVE_LARGE_INTEGER_U',1)
942
943    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
944    if self.checkCompile('#include <Windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
945      self.addDefine('HAVE_O_BINARY',1)
946
947    if self.compilers.CC.find('win32fe') >= 0:
948      self.addDefine('HAVE_WINDOWS_COMPILERS',1)
949      self.addDefine('PATH_SEPARATOR','\';\'')
950      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
951      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
952      self.addDefine('CANNOT_START_DEBUGGER',1)
953      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log)
954      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
955      (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log)
956      self.addMakeMacro('wPETSC_DIR',petscdir)
957    else:
958      self.addDefine('PATH_SEPARATOR','\':\'')
959      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
960      self.addDefine('DIR_SEPARATOR','\'/\'')
961      self.addDefine('DIR','"'+self.installdir.petscDir+'"')
962      self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir)
963    self.addDefine('ARCH','"'+self.installdir.petscArch+'"')
964    return
965
966#-----------------------------------------------------------------------------------------------------
967  def configureCygwinBrokenPipe(self):
968    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
969    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
970    if config.setCompilers.Configure.isCygwin(self.log):
971      import platform
972      import re
973      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
974      m=r.match(platform.release())
975      major=int(m.group(1))
976      minor=int(m.group(2))
977      subminor=int(m.group(3))
978      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
979        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
980    return
981
982#-----------------------------------------------------------------------------------------------------
983  def configureDefaultArch(self):
984    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
985    if self.framework.argDB['with-default-arch']:
986      fd = file(conffile, 'w')
987      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
988      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
989      fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n')
990      fd.close()
991      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
992    elif os.path.isfile(conffile):
993      try:
994        os.unlink(conffile)
995      except:
996        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
997    return
998
999#-----------------------------------------------------------------------------------------------------
1000  def configureScript(self):
1001    '''Output a script in the conf directory which will reproduce the configuration'''
1002    import nargs
1003    import sys
1004    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
1005    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
1006    if 'with-clean' in args:
1007      del args['with-clean']
1008    if 'configModules' in args:
1009      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
1010        del args['configModules']
1011    if 'optionsModule' in args:
1012      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
1013        del args['optionsModule']
1014    if not 'PETSC_ARCH' in args:
1015      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
1016    f = file(scriptName, 'w')
1017    f.write('#!'+sys.executable+'\n')
1018    f.write('if __name__ == \'__main__\':\n')
1019    f.write('  import sys\n')
1020    f.write('  import os\n')
1021    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
1022    f.write('  import configure\n')
1023    # pretty print repr(args.values())
1024    f.write('  configure_options = [\n')
1025    for itm in sorted(args.values()):
1026      f.write('    \''+str(itm)+'\',\n')
1027    f.write('  ]\n')
1028    f.write('  configure.petsc_configure(configure_options)\n')
1029    f.close()
1030    try:
1031      os.chmod(scriptName, 0o775)
1032    except OSError as e:
1033      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
1034    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
1035    return
1036
1037  def configureInstall(self):
1038    '''Setup the directories for installation'''
1039    if self.framework.argDB['prefix']:
1040      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
1041                                              '-@echo "'+self.installdir.installSudo+'make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
1042                                              '-@echo "========================================="'])
1043    else:
1044      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
1045                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"',\
1046                                              '-@echo "========================================="'])
1047      return
1048
1049  def configureGCOV(self):
1050    if self.framework.argDB['with-gcov']:
1051      self.addDefine('USE_GCOV','1')
1052    return
1053
1054  def postProcessPackages(self):
1055    postPackages=[]
1056    for i in self.framework.packages:
1057      if hasattr(i,'postProcess'): postPackages.append(i)
1058    if postPackages:
1059      # ctetgen needs petsc conf files. so attempt to create them early
1060      self.framework.dumpConfFiles()
1061      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
1062      for i in postPackages:
1063        if i.name.upper() in ['PFLOTRAN']:
1064          i.postProcess()
1065          postPackages.remove(i)
1066      for i in postPackages: i.postProcess()
1067      for i in postPackages:
1068        if i.installedpetsc:
1069          self.installed = 1
1070          break
1071    return
1072
1073  def configure(self):
1074    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
1075      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
1076    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
1077      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
1078    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
1079      raise RuntimeError('Your --prefix '+self.framework.argDB['prefix']+' has spaces in it; this is not allowed.\n Use a --prefix that does not have spaces in it')
1080    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],os.path.join(self.petscdir.dir,self.arch.arch)):
1081      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
1082    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
1083    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
1084    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
1085    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
1086    if self.libraries.math is None:
1087      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
1088    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
1089      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
1090    self.executeTest(self.configureRTLDDefault)
1091    self.executeTest(self.configurePrefetch)
1092    self.executeTest(self.configureUnused)
1093    self.executeTest(self.configureDeprecated)
1094    self.executeTest(self.configureIsatty)
1095    self.executeTest(self.configureExpect);
1096    self.executeTest(self.configureAlign);
1097    self.executeTest(self.configureFunctionName);
1098    self.executeTest(self.configureIntptrt);
1099    self.executeTest(self.configureSolaris)
1100    self.executeTest(self.configureLinux)
1101    self.executeTest(self.configureWin32)
1102    self.executeTest(self.configureCygwinBrokenPipe)
1103    self.executeTest(self.configureDefaultArch)
1104    self.executeTest(self.configureScript)
1105    self.executeTest(self.configureInstall)
1106    self.executeTest(self.configureGCOV)
1107    self.executeTest(self.configureAtoll)
1108
1109    self.Dump()
1110    self.dumpConfigInfo()
1111    self.dumpMachineInfo()
1112    self.dumpCMakeConfig()
1113    self.dumpCMakeLists()
1114    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
1115    self.framework.storeSubstitutions(self.framework.argDB)
1116    self.framework.argDB['configureCache'] = cPickle.dumps(self.framework)
1117    self.framework.argDB.save(force = True)
1118    self.cmakeBoot()
1119    self.DumpPkgconfig()
1120    self.DumpModule()
1121    self.postProcessPackages()
1122    self.framework.log.write('================================================================================\n')
1123    self.logClear()
1124    return
1125