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