xref: /petsc/config/PETSc/Configure.py (revision c688d0420b4e513ff34944d1e1ad7d4e50aafa8d)
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
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 entry for configure options
442    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
443    return
444
445  def dumpConfigInfo(self):
446    import time
447    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
448    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
449    fd.close()
450    return
451
452  def dumpMachineInfo(self):
453    import platform
454    import time
455    import script
456    def escape(s):
457      return s.replace('"',r'\"').replace(r'\ ',r'\\ ')
458    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
459    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
460    fd.write('\"-----------------------------------------\\n\"\n')
461    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
462    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
463    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.petscdir.dir)))
464    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.arch.arch)))
465    fd.write('\"-----------------------------------------\\n\";\n')
466    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
467    self.setCompilers.pushLanguage(self.languages.clanguage)
468    fd.write('\"Using C compiler: %s %s ${COPTFLAGS} ${CFLAGS}\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
469    self.setCompilers.popLanguage()
470    if hasattr(self.compilers, 'FC'):
471      self.setCompilers.pushLanguage('FC')
472      fd.write('\"Using Fortran compiler: %s %s ${FOPTFLAGS} ${FFLAGS} %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
473      self.setCompilers.popLanguage()
474    fd.write('\"-----------------------------------------\\n\";\n')
475    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
476    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)))
477    fd.write('\"-----------------------------------------\\n\";\n')
478    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
479    self.setCompilers.pushLanguage(self.languages.clanguage)
480    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
481    self.setCompilers.popLanguage()
482    if hasattr(self.compilers, 'FC'):
483      self.setCompilers.pushLanguage('FC')
484      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
485      self.setCompilers.popLanguage()
486    if self.framework.argDB['with-single-library']:
487      petsclib = '-lpetsc'
488    else:
489      petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
490    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)))
491    fd.write('\"-----------------------------------------\\n\";\n')
492    fd.close()
493    return
494
495  def dumpCMakeConfig(self):
496    '''
497    Writes configuration-specific values to ${PETSC_ARCH}/lib/petsc/conf/PETScBuildInternal.cmake.
498    This file is private to PETSc and should not be included by third parties
499    (a suitable file can be produced later by CMake, but this is not it).
500    '''
501    def cmakeset(fd,key,val=True):
502      if val == True: val = 'YES'
503      if val == False: val = 'NO'
504      fd.write('set (' + key + ' ' + val + ')\n')
505    def ensurelist(a):
506      if isinstance(a,list):
507        return a
508      else:
509        return [a]
510    def libpath(lib):
511      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
512      if not isinstance(lib,str): return ''
513      if lib.startswith('-L'): return lib[2:]
514      if lib.startswith('-R'): return lib[2:]
515      if lib.startswith('-Wl,-rpath,'):
516        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
517        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
518        # corresponding library.
519        return lib[len('-Wl,-rpath,'):]
520      if lib.startswith('-'): return ''
521      return os.path.dirname(lib)
522    def cleanlib(lib):
523      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
524      if not isinstance(lib,str): return ''
525      if lib.startswith('-l'):  return lib[2:]
526      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
527      lib = os.path.splitext(os.path.basename(lib))[0]
528      if lib.startswith('lib'): return lib[3:]
529      return lib
530    def nub(lst):
531      'Return a list containing the first occurrence of each unique element'
532      unique = []
533      for elem in lst:
534        if elem not in unique and elem != '':
535          unique.append(elem)
536      return unique
537    try: reversed # reversed was added in Python-2.4
538    except NameError:
539      def reversed(lst): return lst[::-1]
540    def nublast(lst):
541      'Return a list containing the last occurrence of each unique entry in a list'
542      return reversed(nub(reversed(lst)))
543    def cmakeexpand(varname):
544      return r'"${' + varname + r'}"'
545    def uniqextend(lst,new):
546      for x in ensurelist(new):
547        if x not in lst:
548          lst.append(x)
549    def notstandardinclude(path):
550      return path not in '/usr/include'.split() # /usr/local/include is not automatically included on FreeBSD
551    def writeMacroDefinitions(fd):
552      if self.mpi.usingMPIUni:
553        cmakeset(fd,'PETSC_HAVE_MPIUNI')
554      for pkg in self.framework.packages:
555        if pkg.useddirectly:
556          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE.replace('-','_'))
557        for pair in pkg.defines.items():
558          if pair[0].startswith('HAVE_') and pair[1]:
559            cmakeset(fd, self.framework.getFullDefineName(pkg, pair[0]), pair[1])
560      for name,val in self.functions.defines.items():
561        cmakeset(fd,'PETSC_'+name,val)
562      for dct in [self.defines, self.libraryoptions.defines]:
563        for k,v in dct.items():
564          if k.startswith('USE_'):
565            cmakeset(fd,'PETSC_' + k, v)
566      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
567      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
568      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
569      if hasattr(self.compilers, 'FC'):
570        cmakeset(fd,'PETSC_HAVE_FORTRAN')
571        if self.compilers.fortranIsF90:
572          cmakeset(fd,'PETSC_USING_F90')
573        if self.compilers.fortranIsF2003:
574          cmakeset(fd,'PETSC_USING_F2003')
575      if hasattr(self.compilers, 'CXX'):
576        cmakeset(fd,'PETSC_HAVE_CXX')
577      if self.sharedlibraries.useShared:
578        cmakeset(fd,'BUILD_SHARED_LIBS')
579    def writeBuildFlags(fd):
580      def extendby(lib):
581        libs = ensurelist(lib)
582        lib_paths.extend(map(libpath,libs))
583        lib_libs.extend(map(cleanlib,libs))
584      lib_paths = []
585      lib_libs  = []
586      includes  = []
587      libvars   = []
588      for pkg in self.framework.packages:
589        if pkg.linkedbypetsc:
590          extendby(pkg.lib)
591          uniqextend(includes,pkg.include)
592      extendby(self.libraries.math)
593      extendby(self.libraries.rt)
594      extendby(self.compilers.flibs)
595      extendby(self.compilers.cxxlibs)
596      extendby(self.compilers.LIBS.split())
597      for libname in nublast(lib_libs):
598        libvar = 'PETSC_' + libname.upper() + '_LIB'
599        addpath = ''
600        for lpath in nublast(lib_paths):
601          addpath += '"' + str(lpath) + '" '
602        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
603        libvars.append(libvar)
604      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
605      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
606      includes = filter(notstandardinclude,includes)
607      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',includes)) + ')\n')
608    fd = open(os.path.join(self.arch.arch,'lib','petsc','conf','PETScBuildInternal.cmake'), 'w')
609    writeMacroDefinitions(fd)
610    writeBuildFlags(fd)
611    fd.close()
612    return
613
614  def dumpCMakeLists(self):
615    import sys
616    if sys.version_info >= (2,4):
617      import cmakegen
618      try:
619        cmakegen.main(self.petscdir.dir, log=self.framework.log)
620      except (OSError), e:
621        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
622    else:
623      self.framework.logPrint('Skipping cmakegen due to old python version: ' +str(sys.version_info) )
624
625  def cmakeBoot(self):
626    import sys
627    self.cmakeboot_success = False
628    if sys.version_info >= (2,4) and hasattr(self.cmake,'cmake'):
629      oldRead = self.argDB.readonly
630      self.argDB.readonly = True
631      try:
632        import cmakeboot
633        self.cmakeboot_success = cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
634      except (OSError), e:
635        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
636      except (ImportError, KeyError), e:
637        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
638      self.argDB.readonly = oldRead
639      if self.cmakeboot_success:
640        if hasattr(self.compilers, 'FC') and self.compilers.fortranIsF90 and not self.setCompilers.fortranModuleOutputFlag:
641          self.framework.logPrint('CMake configured successfully, but could not be used by default because of missing fortranModuleOutputFlag\n')
642        else:
643          self.framework.logPrint('CMake configured successfully, using as default build\n')
644          self.addMakeMacro('PETSC_BUILD_USING_CMAKE',1)
645      else:
646        self.framework.logPrint('CMake configuration was unsuccessful\n')
647    else:
648      self.framework.logPrint('Skipping cmakeboot due to old python version: ' +str(sys.version_info) )
649    return
650
651  def configurePrefetch(self):
652    '''Sees if there are any prefetch functions supported'''
653    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
654      self.addDefine('Prefetch(a,b,c)', ' ')
655      return
656    self.pushLanguage(self.languages.clanguage)
657    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
658      # The Intel Intrinsics manual [1] specifies the prototype
659      #
660      #   void _mm_prefetch(char const *a, int sel);
661      #
662      # but other vendors seem to insist on using subtly different
663      # prototypes, including void* for the pointer, and an enum for
664      # sel.  These are both reasonable changes, but negatively impact
665      # portability.
666      #
667      # [1] http://software.intel.com/file/6373
668      self.addDefine('HAVE_XMMINTRIN_H', 1)
669      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
670      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
671      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
672      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
673      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
674    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
675      self.addDefine('HAVE_XMMINTRIN_H', 1)
676      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
677      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
678      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
679      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
680      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
681    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
682      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
683      #
684      #   The value of rw is a compile-time constant one or zero; one
685      #   means that the prefetch is preparing for a write to the memory
686      #   address and zero, the default, means that the prefetch is
687      #   preparing for a read. The value locality must be a compile-time
688      #   constant integer between zero and three. A value of zero means
689      #   that the data has no temporal locality, so it need not be left
690      #   in the cache after the access. A value of three means that the
691      #   data has a high degree of temporal locality and should be left
692      #   in all levels of cache possible. Values of one and two mean,
693      #   respectively, a low or moderate degree of temporal locality.
694      #
695      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
696      # hints.  Using macros for these values in necessary since some
697      # compilers require an enum.
698      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
699      self.addDefine('PREFETCH_HINT_NTA', '0')
700      self.addDefine('PREFETCH_HINT_T0',  '3')
701      self.addDefine('PREFETCH_HINT_T1',  '2')
702      self.addDefine('PREFETCH_HINT_T2',  '1')
703    else:
704      self.addDefine('Prefetch(a,b,c)', ' ')
705    self.popLanguage()
706
707  def configureAtoll(self):
708    '''Checks if atoll exists'''
709    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")'):
710       self.addDefine('HAVE_ATOLL', '1')
711
712  def configureUnused(self):
713    '''Sees if __attribute((unused)) is supported'''
714    if self.framework.argDB['with-ios']:
715      self.addDefine('UNUSED', ' ')
716      return
717    self.pushLanguage(self.languages.clanguage)
718    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'):
719      self.addDefine('UNUSED', '__attribute((unused))')
720    else:
721      self.addDefine('UNUSED', ' ')
722    self.popLanguage()
723
724  def configureIsatty(self):
725    '''Check if the Unix C function isatty() works correctly
726       Actually just assumes it does not work correctly on batch systems'''
727    if not self.framework.argDB['with-batch']:
728      self.addDefine('USE_ISATTY',1)
729
730  def configureDeprecated(self):
731    '''Check if __attribute((deprecated)) is supported'''
732    self.pushLanguage(self.languages.clanguage)
733    ## Recent versions of gcc and clang support __attribute((deprecated("string argument"))), which is very useful, but
734    ## Intel has conspired to make a supremely environment-sensitive compiler.  The Intel compiler looks at the gcc
735    ## executable in the environment to determine the language compatibility that it should attempt to emulate.  Some
736    ## important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g.,
737    ## 4.7).  Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc
738    ## found in the default user environment is older and does not support the argument.  If GCC and Intel were cool
739    ## like Clang and supported __has_attribute, we could avoid configure tests entirely, but they don't.  And that is
740    ## why we can't have nice things.
741    #
742    # if self.checkCompile("""__attribute((deprecated("Why you shouldn't use myfunc"))) static int myfunc(void) { return 1;}""", ''):
743    #   self.addDefine('DEPRECATED(why)', '__attribute((deprecated(why)))')
744    if self.checkCompile("""__attribute((deprecated)) static int myfunc(void) { return 1;}""", ''):
745      self.addDefine('DEPRECATED(why)', '__attribute((deprecated))')
746    else:
747      self.addDefine('DEPRECATED(why)', ' ')
748    self.popLanguage()
749
750  def configureAlign(self):
751    '''Check if __attribute(align) is supported'''
752    filename = 'conftestalign'
753    includes = '''
754#include <sys/types.h>
755#if STDC_HEADERS
756#include <stdlib.h>
757#include <stdio.h>
758#include <stddef.h>
759#endif\n'''
760    body     = '''
761struct mystruct {int myint;} __attribute((aligned(16)));
762FILE *f = fopen("'''+filename+'''", "w");
763if (!f) exit(1);
764fprintf(f, "%lu\\n", (unsigned long)sizeof(struct mystruct));
765'''
766    if 'known-has-attribute-aligned' in self.argDB:
767      if self.argDB['known-has-attribute-aligned']:
768        size = 16
769      else:
770        size = -3
771    elif not self.argDB['with-batch']:
772      self.pushLanguage(self.languages.clanguage)
773      try:
774        if self.checkRun(includes, body) and os.path.exists(filename):
775          f    = file(filename)
776          size = int(f.read())
777          f.close()
778          os.remove(filename)
779        else:
780          size = -4
781      except:
782        size = -1
783        self.framework.logPrint('Error checking attribute(aligned)')
784      self.popLanguage()
785    else:
786      self.framework.addBatchInclude(['#include <stdlib.h>', '#include <stdio.h>', '#include <sys/types.h>','struct mystruct {int myint;} __attribute((aligned(16)));'])
787      self.framework.addBatchBody('fprintf(output, "  \'--known-has-attribute-aligned=%d\',\\n", sizeof(struct mystruct)==16);')
788      size = -2
789    if size == 16:
790      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned (size)))')
791      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
792    else:
793      self.framework.logPrint('incorrect alignment. Found alignment:'+ str(size))
794      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
795    return
796
797  def configureExpect(self):
798    '''Sees if the __builtin_expect directive is supported'''
799    self.pushLanguage(self.languages.clanguage)
800    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
801      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
802    self.popLanguage()
803
804  def configureFunctionName(self):
805    '''Sees if the compiler supports __func__ or a variant.  Falls back
806    on __FUNCT__ which PETSc source defines, but most users do not, thus
807    stack traces through user code are better when the compiler's
808    variant is used.'''
809    def getFunctionName(lang):
810      name = '__FUNCT__'
811      self.pushLanguage(lang)
812      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
813        name = '__func__'
814      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
815        name = '__FUNCTION__'
816      self.popLanguage()
817      return name
818    langs = []
819
820    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
821    if hasattr(self.compilers, 'CXX'):
822      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
823    else:
824      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
825
826  def configureIntptrt(self):
827    '''Determine what to use for uintptr_t'''
828    def staticAssertSizeMatchesVoidStar(inc,typename):
829      # The declaration is an error if either array size is negative.
830      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
831      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
832                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
833    self.pushLanguage(self.languages.clanguage)
834    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
835      self.addDefine('UINTPTR_T', 'uintptr_t')
836    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
837      self.addDefine('UINTPTR_T', 'unsigned long long')
838    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
839      self.addDefine('UINTPTR_T', 'size_t')
840    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
841      self.addDefine('UINTPTR_T', 'unsigned long')
842    elif staticAssertSizeMatchesVoidStar('','unsigned'):
843      self.addDefine('UINTPTR_T', 'unsigned')
844    else:
845      raise RuntimeError('Could not find any unsigned integer type matching void*')
846    self.popLanguage()
847
848  def configureRTLDDefault(self):
849    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
850      self.addDefine('RTLD_DEFAULT','1')
851    return
852
853  def configureSolaris(self):
854    '''Solaris specific stuff'''
855    if os.path.isdir(os.path.join('/usr','ucblib')):
856      try:
857        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
858      except AttributeError:
859        flag = None
860      if flag is None:
861        self.compilers.LIBS += ' -L/usr/ucblib'
862      else:
863        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
864    return
865
866  def configureLinux(self):
867    '''Linux specific stuff'''
868    # TODO: Test for this by mallocing an odd number of floats and checking the address
869    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
870    return
871
872  def configureWin32(self):
873    '''Win32 non-cygwin specific stuff'''
874    kernel32=0
875    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
876      self.addDefine('HAVE_WINDOWS_H',1)
877      self.addDefine('HAVE_GETCOMPUTERNAME',1)
878      kernel32=1
879    elif self.libraries.add('kernel32','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    if kernel32:
884      if self.framework.argDB['with-windows-graphics']:
885        self.addDefine('USE_WINDOWS_GRAPHICS',1)
886      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
887        self.addDefine('HAVE_LOADLIBRARY',1)
888      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
889        self.addDefine('HAVE_GETPROCADDRESS',1)
890      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
891        self.addDefine('HAVE_FREELIBRARY',1)
892      if self.checkLink('#include <Windows.h>','GetLastError()'):
893        self.addDefine('HAVE_GETLASTERROR',1)
894      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
895        self.addDefine('HAVE_SETLASTERROR',1)
896      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
897        self.addDefine('USE_MICROSOFT_TIME',1)
898    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
899      self.addDefine('HAVE_GET_USER_NAME',1)
900    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
901      self.addDefine('HAVE_GET_USER_NAME',1)
902
903    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
904      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
905    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
906      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
907
908    self.types.check('int32_t', 'int')
909    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
910      self.addTypedef('int', 'uid_t')
911      self.addTypedef('int', 'gid_t')
912    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
913      self.framework.addDefine('R_OK', '04')
914      self.framework.addDefine('W_OK', '02')
915      self.framework.addDefine('X_OK', '01')
916    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
917      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
918      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
919    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
920      self.addDefine('HAVE_LARGE_INTEGER_U',1)
921
922    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
923    if self.checkCompile('#include <Windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
924      self.addDefine('HAVE_O_BINARY',1)
925
926    if self.compilers.CC.find('win32fe') >= 0:
927      self.addDefine('PATH_SEPARATOR','\';\'')
928      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
929      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
930      self.addDefine('CANNOT_START_DEBUGGER',1)
931      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.petscdir.dir, log = self.log)
932      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
933    else:
934      self.addDefine('PATH_SEPARATOR','\':\'')
935      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
936      self.addDefine('DIR_SEPARATOR','\'/\'')
937      self.addDefine('DIR', '"'+self.petscdir.dir+'"')
938
939    return
940
941#-----------------------------------------------------------------------------------------------------
942  def configureCygwinBrokenPipe(self):
943    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
944    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
945    if config.setCompilers.Configure.isCygwin(self.log):
946      import platform
947      import re
948      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
949      m=r.match(platform.release())
950      major=int(m.group(1))
951      minor=int(m.group(2))
952      subminor=int(m.group(3))
953      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
954        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
955    return
956
957#-----------------------------------------------------------------------------------------------------
958  def configureDefaultArch(self):
959    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
960    if self.framework.argDB['with-default-arch']:
961      fd = file(conffile, 'w')
962      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
963      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
964      fd.write('include '+os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','petscvariables')+'\n')
965      fd.close()
966      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
967    elif os.path.isfile(conffile):
968      try:
969        os.unlink(conffile)
970      except:
971        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
972    return
973
974#-----------------------------------------------------------------------------------------------------
975  def configureScript(self):
976    '''Output a script in the conf directory which will reproduce the configuration'''
977    import nargs
978    import sys
979    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
980    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
981    if 'with-clean' in args:
982      del args['with-clean']
983    if 'configModules' in args:
984      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
985        del args['configModules']
986    if 'optionsModule' in args:
987      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
988        del args['optionsModule']
989    if not 'PETSC_ARCH' in args:
990      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
991    f = file(scriptName, 'w')
992    f.write('#!'+sys.executable+'\n')
993    f.write('if __name__ == \'__main__\':\n')
994    f.write('  import sys\n')
995    f.write('  import os\n')
996    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
997    f.write('  import configure\n')
998    # pretty print repr(args.values())
999    f.write('  configure_options = [\n')
1000    for itm in sorted(args.values()):
1001      f.write('    \''+str(itm)+'\',\n')
1002    f.write('  ]\n')
1003    f.write('  configure.petsc_configure(configure_options)\n')
1004    f.close()
1005    try:
1006      os.chmod(scriptName, 0775)
1007    except OSError, e:
1008      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
1009    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
1010    return
1011
1012  def configureInstall(self):
1013    '''Setup the directories for installation'''
1014    if self.framework.argDB['prefix']:
1015      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
1016                                              '-@echo "'+self.installdir.installSudo+'make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
1017                                              '-@echo "========================================="'])
1018    else:
1019      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
1020                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
1021                                              '-@echo "========================================="'])
1022      return
1023
1024  def configureGCOV(self):
1025    if self.framework.argDB['with-gcov']:
1026      self.addDefine('USE_GCOV','1')
1027    return
1028
1029  def configureFortranFlush(self):
1030    if hasattr(self.compilers, 'FC'):
1031      for baseName in ['flush','flush_']:
1032        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
1033          self.addDefine('HAVE_'+baseName.upper(), 1)
1034          return
1035
1036  def configureViewFromOptions(self):
1037    if not self.framework.argDB['with-viewfromoptions']:
1038      self.addDefine('SKIP_VIEWFROMOPTIONS',1)
1039
1040  def postProcessPackages(self):
1041    postPackages=[]
1042    for i in self.framework.packages:
1043      if hasattr(i,'postProcess'): postPackages.append(i)
1044    if postPackages:
1045      # ctetgen needs petsc conf files. so attempt to create them early
1046      self.framework.dumpConfFiles()
1047      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
1048      for i in postPackages:
1049        if i.name.upper() in ['PFLOTRAN']:
1050          i.postProcess()
1051          postPackages.remove(i)
1052      for i in postPackages: i.postProcess()
1053      for i in postPackages:
1054        if i.installedpetsc:
1055          self.installed = 1
1056          break
1057    return
1058
1059  def configure(self):
1060    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
1061      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
1062    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
1063      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
1064    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
1065      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')
1066    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)):
1067      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
1068    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
1069    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
1070    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
1071    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
1072    if self.libraries.math is None:
1073      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
1074    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
1075      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
1076    self.executeTest(self.configureRTLDDefault)
1077    self.executeTest(self.configurePrefetch)
1078    self.executeTest(self.configureUnused)
1079    self.executeTest(self.configureDeprecated)
1080    self.executeTest(self.configureIsatty)
1081    self.executeTest(self.configureExpect);
1082    self.executeTest(self.configureAlign);
1083    self.executeTest(self.configureFunctionName);
1084    self.executeTest(self.configureIntptrt);
1085    self.executeTest(self.configureSolaris)
1086    self.executeTest(self.configureLinux)
1087    self.executeTest(self.configureWin32)
1088    self.executeTest(self.configureCygwinBrokenPipe)
1089    self.executeTest(self.configureDefaultArch)
1090    self.executeTest(self.configureScript)
1091    self.executeTest(self.configureInstall)
1092    self.executeTest(self.configureGCOV)
1093    self.executeTest(self.configureFortranFlush)
1094    self.executeTest(self.configureAtoll)
1095    self.executeTest(self.configureViewFromOptions)
1096    # dummy rules, always needed except for remote builds
1097    self.addMakeRule('remote','')
1098    self.addMakeRule('remoteclean','')
1099
1100    self.Dump()
1101    self.dumpConfigInfo()
1102    self.dumpMachineInfo()
1103    self.dumpCMakeConfig()
1104    self.dumpCMakeLists()
1105    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
1106    self.framework.storeSubstitutions(self.framework.argDB)
1107    self.framework.argDB['configureCache'] = cPickle.dumps(self.framework)
1108    self.framework.argDB.save(force = True)
1109    self.cmakeBoot()
1110    self.DumpPkgconfig()
1111    self.DumpModule()
1112    self.postProcessPackages()
1113    self.framework.log.write('================================================================================\n')
1114    self.logClear()
1115    return
1116