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