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