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