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