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