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