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