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