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