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