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