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