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