xref: /petsc/config/PETSc/Configure.py (revision 4c1069a6f7e44f78d90b41175756006e76a04441)
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      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
802        name = '__func__'
803      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
804        name = '__FUNCTION__'
805      self.popLanguage()
806      return name
807    langs = []
808
809    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
810    if hasattr(self.compilers, 'CXX'):
811      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
812    else:
813      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
814
815  def configureIntptrt(self):
816    '''Determine what to use for uintptr_t'''
817    def staticAssertSizeMatchesVoidStar(inc,typename):
818      # The declaration is an error if either array size is negative.
819      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
820      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
821                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
822    self.pushLanguage(self.languages.clanguage)
823    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
824      self.addDefine('UINTPTR_T', 'uintptr_t')
825    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
826      self.addDefine('UINTPTR_T', 'unsigned long long')
827    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
828      self.addDefine('UINTPTR_T', 'size_t')
829    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
830      self.addDefine('UINTPTR_T', 'unsigned long')
831    elif staticAssertSizeMatchesVoidStar('','unsigned'):
832      self.addDefine('UINTPTR_T', 'unsigned')
833    else:
834      raise RuntimeError('Could not find any unsigned integer type matching void*')
835    self.popLanguage()
836
837  def configureRTLDDefault(self):
838    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
839      self.addDefine('RTLD_DEFAULT','1')
840    return
841
842  def configureSolaris(self):
843    '''Solaris specific stuff'''
844    if os.path.isdir(os.path.join('/usr','ucblib')):
845      try:
846        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
847      except AttributeError:
848        flag = None
849      if flag is None:
850        self.compilers.LIBS += ' -L/usr/ucblib'
851      else:
852        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
853    return
854
855  def configureLinux(self):
856    '''Linux specific stuff'''
857    # TODO: Test for this by mallocing an odd number of floats and checking the address
858    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
859    return
860
861  def configureWin32(self):
862    '''Win32 non-cygwin specific stuff'''
863    kernel32=0
864    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
865      self.addDefine('HAVE_WINDOWS_H',1)
866      self.addDefine('HAVE_GETCOMPUTERNAME',1)
867      kernel32=1
868    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
869      self.addDefine('HAVE_WINDOWS_H',1)
870      self.addDefine('HAVE_GETCOMPUTERNAME',1)
871      kernel32=1
872    if kernel32:
873      if self.framework.argDB['with-windows-graphics']:
874        self.addDefine('USE_WINDOWS_GRAPHICS',1)
875      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
876        self.addDefine('HAVE_LOADLIBRARY',1)
877      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
878        self.addDefine('HAVE_GETPROCADDRESS',1)
879      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
880        self.addDefine('HAVE_FREELIBRARY',1)
881      if self.checkLink('#include <Windows.h>','GetLastError()'):
882        self.addDefine('HAVE_GETLASTERROR',1)
883      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
884        self.addDefine('HAVE_SETLASTERROR',1)
885      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
886        self.addDefine('USE_MICROSOFT_TIME',1)
887    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
888      self.addDefine('HAVE_GET_USER_NAME',1)
889    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
890      self.addDefine('HAVE_GET_USER_NAME',1)
891
892    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
893      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
894    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
895      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
896
897    self.types.check('int32_t', 'int')
898    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
899      self.addTypedef('int', 'uid_t')
900      self.addTypedef('int', 'gid_t')
901    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
902      self.framework.addDefine('R_OK', '04')
903      self.framework.addDefine('W_OK', '02')
904      self.framework.addDefine('X_OK', '01')
905    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
906      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
907      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
908    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
909      self.addDefine('HAVE_LARGE_INTEGER_U',1)
910
911    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
912    if self.checkCompile('#include <Windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
913      self.addDefine('HAVE_O_BINARY',1)
914
915    if self.compilers.CC.find('win32fe') >= 0:
916      self.addDefine('PATH_SEPARATOR','\';\'')
917      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
918      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
919      self.addDefine('CANNOT_START_DEBUGGER',1)
920      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.petscdir.dir, log = self.log)
921      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
922    else:
923      self.addDefine('PATH_SEPARATOR','\':\'')
924      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
925      self.addDefine('DIR_SEPARATOR','\'/\'')
926      self.addDefine('DIR', '"'+self.petscdir.dir+'"')
927
928    return
929
930#-----------------------------------------------------------------------------------------------------
931  def configureCygwinBrokenPipe(self):
932    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
933    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
934    if config.setCompilers.Configure.isCygwin(self.log):
935      import platform
936      import re
937      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
938      m=r.match(platform.release())
939      major=int(m.group(1))
940      minor=int(m.group(2))
941      subminor=int(m.group(3))
942      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
943        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
944    return
945
946#-----------------------------------------------------------------------------------------------------
947  def configureDefaultArch(self):
948    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
949    if self.framework.argDB['with-default-arch']:
950      fd = file(conffile, 'w')
951      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
952      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
953      fd.write('include '+os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','petscvariables')+'\n')
954      fd.close()
955      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
956    elif os.path.isfile(conffile):
957      try:
958        os.unlink(conffile)
959      except:
960        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
961    return
962
963#-----------------------------------------------------------------------------------------------------
964  def configureScript(self):
965    '''Output a script in the conf directory which will reproduce the configuration'''
966    import nargs
967    import sys
968    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
969    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
970    if 'with-clean' in args:
971      del args['with-clean']
972    if 'configModules' in args:
973      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
974        del args['configModules']
975    if 'optionsModule' in args:
976      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
977        del args['optionsModule']
978    if not 'PETSC_ARCH' in args:
979      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
980    f = file(scriptName, 'w')
981    f.write('#!'+sys.executable+'\n')
982    f.write('if __name__ == \'__main__\':\n')
983    f.write('  import sys\n')
984    f.write('  import os\n')
985    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
986    f.write('  import configure\n')
987    # pretty print repr(args.values())
988    f.write('  configure_options = [\n')
989    for itm in sorted(args.values()):
990      f.write('    \''+str(itm)+'\',\n')
991    f.write('  ]\n')
992    f.write('  configure.petsc_configure(configure_options)\n')
993    f.close()
994    try:
995      os.chmod(scriptName, 0775)
996    except OSError, e:
997      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
998    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
999    return
1000
1001  def configureInstall(self):
1002    '''Setup the directories for installation'''
1003    if self.framework.argDB['prefix']:
1004      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
1005                                              '-@echo "'+self.installdir.installSudo+'make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
1006                                              '-@echo "========================================="'])
1007    else:
1008      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
1009                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
1010                                              '-@echo "========================================="'])
1011      return
1012
1013  def configureGCOV(self):
1014    if self.framework.argDB['with-gcov']:
1015      self.addDefine('USE_GCOV','1')
1016    return
1017
1018  def configureFortranFlush(self):
1019    if hasattr(self.compilers, 'FC'):
1020      for baseName in ['flush','flush_']:
1021        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
1022          self.addDefine('HAVE_'+baseName.upper(), 1)
1023          return
1024
1025  def configureViewFromOptions(self):
1026    if not self.framework.argDB['with-viewfromoptions']:
1027      self.addDefine('SKIP_VIEWFROMOPTIONS',1)
1028
1029  def postProcessPackages(self):
1030    postPackages=[]
1031    for i in self.framework.packages:
1032      if hasattr(i,'postProcess'): postPackages.append(i)
1033    if postPackages:
1034      # ctetgen needs petsc conf files. so attempt to create them early
1035      self.framework.dumpConfFiles()
1036      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
1037      for i in postPackages:
1038        if i.name.upper() in ['PFLOTRAN']:
1039          i.postProcess()
1040          postPackages.remove(i)
1041      for i in postPackages: i.postProcess()
1042      for i in postPackages:
1043        if i.installedpetsc:
1044          self.installed = 1
1045          break
1046    return
1047
1048  def configure(self):
1049    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
1050      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
1051    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
1052      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
1053    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
1054      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')
1055    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)):
1056      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
1057    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
1058    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
1059    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
1060    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
1061    if self.libraries.math is None:
1062      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
1063    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
1064      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
1065    self.executeTest(self.configureRTLDDefault)
1066    self.executeTest(self.configurePrefetch)
1067    self.executeTest(self.configureUnused)
1068    self.executeTest(self.configureDeprecated)
1069    self.executeTest(self.configureIsatty)
1070    self.executeTest(self.configureExpect);
1071    self.executeTest(self.configureAlign);
1072    self.executeTest(self.configureFunctionName);
1073    self.executeTest(self.configureIntptrt);
1074    self.executeTest(self.configureSolaris)
1075    self.executeTest(self.configureLinux)
1076    self.executeTest(self.configureWin32)
1077    self.executeTest(self.configureCygwinBrokenPipe)
1078    self.executeTest(self.configureDefaultArch)
1079    self.executeTest(self.configureScript)
1080    self.executeTest(self.configureInstall)
1081    self.executeTest(self.configureGCOV)
1082    self.executeTest(self.configureFortranFlush)
1083    self.executeTest(self.configureAtoll)
1084    self.executeTest(self.configureViewFromOptions)
1085    # dummy rules, always needed except for remote builds
1086    self.addMakeRule('remote','')
1087    self.addMakeRule('remoteclean','')
1088
1089    self.Dump()
1090    self.dumpConfigInfo()
1091    self.dumpMachineInfo()
1092    self.dumpCMakeConfig()
1093    self.dumpCMakeLists()
1094    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
1095    self.framework.storeSubstitutions(self.framework.argDB)
1096    self.framework.argDB['configureCache'] = cPickle.dumps(self.framework)
1097    self.framework.argDB.save(force = True)
1098    self.cmakeBoot()
1099    self.DumpPkgconfig()
1100    self.DumpModule()
1101    self.postProcessPackages()
1102    self.framework.log.write('================================================================================\n')
1103    self.logClear()
1104    return
1105