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