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