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