xref: /petsc/config/PETSc/Configure.py (revision f8a5e270dc6f937d143bafaf8aed84a16ca8a628)
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.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"')
417
418    if self.framework.argDB['with-single-library']:
419      # overrides the values set in conf/variables
420      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
421      self.addMakeMacro('SHLIBS','libpetsc')
422      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
423      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
424      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
425      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
426      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.PETSC_WITH_EXTERNAL_LIB)
427      self.addDefine('USE_SINGLE_LIBRARY', '1')
428      if self.sharedlibraries.useShared:
429        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
430        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
431        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
432        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
433        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
434        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
435        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
436        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
437        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
438        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
439        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
440      else:
441        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
442        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
443        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
444        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
445        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
446        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
447        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
448        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
449        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
450        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
451        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
452
453    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
454      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
455
456# add a makefile endtry for display
457    if self.framework.argDB['with-display']:
458      self.addMakeMacro('DISPLAY',self.framework.argDB['with-display'])
459
460    # add a makefile entry for configure options
461    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
462    return
463
464  def dumpConfigInfo(self):
465    import time
466    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
467    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
468    fd.close()
469    return
470
471  def dumpMachineInfo(self):
472    import platform
473    import time
474    import script
475    def escape(s):
476      return s.replace('"',r'\"').replace(r'\ ',r'\\ ')
477    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
478    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
479    fd.write('\"-----------------------------------------\\n\"\n')
480    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
481    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
482    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir)))
483    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch)))
484    fd.write('\"-----------------------------------------\\n\";\n')
485    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
486    self.setCompilers.pushLanguage(self.languages.clanguage)
487    fd.write('\"Using C compiler: %s %s \\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
488    self.setCompilers.popLanguage()
489    if hasattr(self.compilers, 'FC'):
490      self.setCompilers.pushLanguage('FC')
491      fd.write('\"Using Fortran compiler: %s %s  %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
492      self.setCompilers.popLanguage()
493    fd.write('\"-----------------------------------------\\n\";\n')
494    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
495    fd.write('\"Using include paths: %s\\n\"\n' % (escape(self.PETSC_CC_INCLUDES).replace(self.petscdir.dir,self.installdir.petscDir).replace(self.arch.arch,self.installdir.petscArch)))
496    fd.write('\"-----------------------------------------\\n\";\n')
497    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
498    self.setCompilers.pushLanguage(self.languages.clanguage)
499    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
500    self.setCompilers.popLanguage()
501    if hasattr(self.compilers, 'FC'):
502      self.setCompilers.pushLanguage('FC')
503      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
504      self.setCompilers.popLanguage()
505    fd.write('\"Using libraries: %s%s -L%s %s %s\\n\"\n' % (escape(self.setCompilers.CSharedLinkerFlag), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(self.petsclib), escape(self.PETSC_EXTERNAL_LIB_BASIC)))
506    fd.write('\"-----------------------------------------\\n\";\n')
507    fd.close()
508    return
509
510  def dumpCMakeConfig(self):
511    '''
512    Writes configuration-specific values to ${PETSC_ARCH}/lib/petsc/conf/PETScBuildInternal.cmake.
513    This file is private to PETSc and should not be included by third parties
514    (a suitable file can be produced later by CMake, but this is not it).
515    '''
516    def cmakeset(fd,key,val=True):
517      if val == True: val = 'YES'
518      if val == False: val = 'NO'
519      fd.write('set (' + key + ' ' + val + ')\n')
520    def ensurelist(a):
521      if isinstance(a,list):
522        return a
523      else:
524        return [a]
525    def libpath(lib):
526      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
527      if not isinstance(lib,str): return ''
528      if lib.startswith('-L'): return lib[2:]
529      if lib.startswith('-R'): return lib[2:]
530      if lib.startswith('-Wl,-rpath,'):
531        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
532        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
533        # corresponding library.
534        return lib[len('-Wl,-rpath,'):]
535      if lib.startswith('-'): return ''
536      return os.path.dirname(lib)
537    def cleanlib(lib):
538      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
539      if not isinstance(lib,str): return ''
540      if lib.startswith('-l'):  return lib[2:]
541      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
542      lib = os.path.splitext(os.path.basename(lib))[0]
543      if lib.startswith('lib'): return lib[3:]
544      return lib
545    def nub(lst):
546      'Return a list containing the first occurrence of each unique element'
547      unique = []
548      for elem in lst:
549        if elem not in unique and elem != '':
550          unique.append(elem)
551      return unique
552    try: reversed # reversed was added in Python-2.4
553    except NameError:
554      def reversed(lst): return lst[::-1]
555    def nublast(lst):
556      'Return a list containing the last occurrence of each unique entry in a list'
557      return reversed(nub(reversed(lst)))
558    def cmakeexpand(varname):
559      return r'"${' + varname + r'}"'
560    def uniqextend(lst,new):
561      for x in ensurelist(new):
562        if x not in lst:
563          lst.append(x)
564    def notstandardinclude(path):
565      return path not in '/usr/include'.split() # /usr/local/include is not automatically included on FreeBSD
566    def writeMacroDefinitions(fd):
567      if self.mpi.usingMPIUni:
568        cmakeset(fd,'PETSC_HAVE_MPIUNI')
569      for pkg in self.framework.packages:
570        if pkg.useddirectly:
571          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE.replace('-','_'))
572        for pair in pkg.defines.items():
573          if pair[0].startswith('HAVE_') and pair[1]:
574            cmakeset(fd, self.framework.getFullDefineName(pkg, pair[0]), pair[1])
575      for name,val in self.functions.defines.items():
576        cmakeset(fd,'PETSC_'+name,val)
577      for dct in [self.defines, self.libraryoptions.defines]:
578        for k,v in dct.items():
579          if k.startswith('USE_'):
580            cmakeset(fd,'PETSC_' + k, v)
581      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
582      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
583      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
584      if hasattr(self.compilers, 'FC'):
585        cmakeset(fd,'PETSC_HAVE_FORTRAN')
586        if self.compilers.fortranIsF90:
587          cmakeset(fd,'PETSC_USING_F90')
588        if self.compilers.fortranIsF2003:
589          cmakeset(fd,'PETSC_USING_F2003')
590      if hasattr(self.compilers, 'CXX'):
591        cmakeset(fd,'PETSC_HAVE_CXX')
592      if self.sharedlibraries.useShared:
593        cmakeset(fd,'BUILD_SHARED_LIBS')
594    def writeBuildFlags(fd):
595      def extendby(lib):
596        libs = ensurelist(lib)
597        lib_paths.extend(map(libpath,libs))
598        lib_libs.extend(map(cleanlib,libs))
599      lib_paths = []
600      lib_libs  = []
601      includes  = []
602      libvars   = []
603      for pkg in self.framework.packages:
604        if pkg.linkedbypetsc:
605          extendby(pkg.lib)
606          uniqextend(includes,pkg.include)
607      extendby(self.libraries.math)
608      extendby(self.libraries.rt)
609      extendby(self.compilers.flibs)
610      extendby(self.compilers.cxxlibs)
611      extendby(self.compilers.LIBS.split())
612      for libname in nublast(lib_libs):
613        libvar = 'PETSC_' + libname.upper() + '_LIB'
614        addpath = ''
615        for lpath in nublast(lib_paths):
616          addpath += '"' + str(lpath) + '" '
617        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
618        libvars.append(libvar)
619      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
620      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
621      includes = filter(notstandardinclude,includes)
622      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',includes)) + ')\n')
623    fd = open(os.path.join(self.arch.arch,'lib','petsc','conf','PETScBuildInternal.cmake'), 'w')
624    writeMacroDefinitions(fd)
625    writeBuildFlags(fd)
626    fd.close()
627    return
628
629  def dumpCMakeLists(self):
630    import sys
631    if sys.version_info >= (2,4):
632      import cmakegen
633      try:
634        cmakegen.main(self.petscdir.dir, log=self.framework.log)
635      except (OSError), e:
636        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
637    else:
638      self.framework.logPrint('Skipping cmakegen due to old python version: ' +str(sys.version_info) )
639
640  def cmakeBoot(self):
641    import sys
642    self.cmakeboot_success = False
643    if sys.version_info >= (2,4) and hasattr(self.cmake,'cmake'):
644      oldRead = self.argDB.readonly
645      self.argDB.readonly = True
646      try:
647        import cmakeboot
648        self.cmakeboot_success = cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
649      except (OSError), e:
650        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
651      except (ImportError, KeyError), e:
652        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
653      self.argDB.readonly = oldRead
654      if self.cmakeboot_success:
655        if hasattr(self.compilers, 'FC') and self.compilers.fortranIsF90 and not self.setCompilers.fortranModuleOutputFlag:
656          self.framework.logPrint('CMake configured successfully, but could not be used by default because of missing fortranModuleOutputFlag\n')
657        else:
658          self.framework.logPrint('CMake configured successfully, using as default build\n')
659          self.addMakeMacro('PETSC_BUILD_USING_CMAKE',1)
660      else:
661        self.framework.logPrint('CMake configuration was unsuccessful\n')
662    else:
663      self.framework.logPrint('Skipping cmakeboot due to old python version: ' +str(sys.version_info) )
664    return
665
666  def configurePrefetch(self):
667    '''Sees if there are any prefetch functions supported'''
668    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
669      self.addDefine('Prefetch(a,b,c)', ' ')
670      return
671    self.pushLanguage(self.languages.clanguage)
672    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
673      # The Intel Intrinsics manual [1] specifies the prototype
674      #
675      #   void _mm_prefetch(char const *a, int sel);
676      #
677      # but other vendors seem to insist on using subtly different
678      # prototypes, including void* for the pointer, and an enum for
679      # sel.  These are both reasonable changes, but negatively impact
680      # portability.
681      #
682      # [1] http://software.intel.com/file/6373
683      self.addDefine('HAVE_XMMINTRIN_H', 1)
684      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
685      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
686      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
687      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
688      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
689    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
690      self.addDefine('HAVE_XMMINTRIN_H', 1)
691      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
692      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
693      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
694      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
695      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
696    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
697      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
698      #
699      #   The value of rw is a compile-time constant one or zero; one
700      #   means that the prefetch is preparing for a write to the memory
701      #   address and zero, the default, means that the prefetch is
702      #   preparing for a read. The value locality must be a compile-time
703      #   constant integer between zero and three. A value of zero means
704      #   that the data has no temporal locality, so it need not be left
705      #   in the cache after the access. A value of three means that the
706      #   data has a high degree of temporal locality and should be left
707      #   in all levels of cache possible. Values of one and two mean,
708      #   respectively, a low or moderate degree of temporal locality.
709      #
710      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
711      # hints.  Using macros for these values in necessary since some
712      # compilers require an enum.
713      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
714      self.addDefine('PREFETCH_HINT_NTA', '0')
715      self.addDefine('PREFETCH_HINT_T0',  '3')
716      self.addDefine('PREFETCH_HINT_T1',  '2')
717      self.addDefine('PREFETCH_HINT_T2',  '1')
718    else:
719      self.addDefine('Prefetch(a,b,c)', ' ')
720    self.popLanguage()
721
722  def configureAtoll(self):
723    '''Checks if atoll exists'''
724    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")'):
725       self.addDefine('HAVE_ATOLL', '1')
726
727  def configureUnused(self):
728    '''Sees if __attribute((unused)) is supported'''
729    if self.framework.argDB['with-ios']:
730      self.addDefine('UNUSED', ' ')
731      return
732    self.pushLanguage(self.languages.clanguage)
733    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'):
734      self.addDefine('UNUSED', '__attribute((unused))')
735    else:
736      self.addDefine('UNUSED', ' ')
737    self.popLanguage()
738
739  def configureIsatty(self):
740    '''Check if the Unix C function isatty() works correctly
741       Actually just assumes it does not work correctly on batch systems'''
742    if not self.framework.argDB['with-batch']:
743      self.addDefine('USE_ISATTY',1)
744
745  def configureDeprecated(self):
746    '''Check if __attribute((deprecated)) is supported'''
747    self.pushLanguage(self.languages.clanguage)
748    ## Recent versions of gcc and clang support __attribute((deprecated("string argument"))), which is very useful, but
749    ## Intel has conspired to make a supremely environment-sensitive compiler.  The Intel compiler looks at the gcc
750    ## executable in the environment to determine the language compatibility that it should attempt to emulate.  Some
751    ## important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g.,
752    ## 4.7).  Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc
753    ## found in the default user environment is older and does not support the argument.  If GCC and Intel were cool
754    ## like Clang and supported __has_attribute, we could avoid configure tests entirely, but they don't.  And that is
755    ## why we can't have nice things.
756    #
757    # if self.checkCompile("""__attribute((deprecated("Why you shouldn't use myfunc"))) static int myfunc(void) { return 1;}""", ''):
758    #   self.addDefine('DEPRECATED(why)', '__attribute((deprecated(why)))')
759    if self.checkCompile("""__attribute((deprecated)) static int myfunc(void) { return 1;}""", ''):
760      self.addDefine('DEPRECATED(why)', '__attribute((deprecated))')
761    else:
762      self.addDefine('DEPRECATED(why)', ' ')
763    self.popLanguage()
764
765  def configureAlign(self):
766    '''Check if __attribute(align) is supported'''
767    filename = 'conftestalign'
768    includes = '''
769#include <sys/types.h>
770#if STDC_HEADERS
771#include <stdlib.h>
772#include <stdio.h>
773#include <stddef.h>
774#endif\n'''
775    body     = '''
776struct mystruct {int myint;} __attribute((aligned(16)));
777FILE *f = fopen("'''+filename+'''", "w");
778if (!f) exit(1);
779fprintf(f, "%lu\\n", (unsigned long)sizeof(struct mystruct));
780'''
781    if 'known-has-attribute-aligned' in self.argDB:
782      if self.argDB['known-has-attribute-aligned']:
783        size = 16
784      else:
785        size = -3
786    elif not self.argDB['with-batch']:
787      self.pushLanguage(self.languages.clanguage)
788      try:
789        if self.checkRun(includes, body) and os.path.exists(filename):
790          f    = file(filename)
791          size = int(f.read())
792          f.close()
793          os.remove(filename)
794        else:
795          size = -4
796      except:
797        size = -1
798        self.framework.logPrint('Error checking attribute(aligned)')
799      self.popLanguage()
800    else:
801      self.framework.addBatchInclude(['#include <stdlib.h>', '#include <stdio.h>', '#include <sys/types.h>','struct mystruct {int myint;} __attribute((aligned(16)));'])
802      self.framework.addBatchBody('fprintf(output, "  \'--known-has-attribute-aligned=%d\',\\n", sizeof(struct mystruct)==16);')
803      size = -2
804    if size == 16:
805      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned (size)))')
806      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
807    else:
808      self.framework.logPrint('incorrect alignment. Found alignment:'+ str(size))
809      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
810    return
811
812  def configureExpect(self):
813    '''Sees if the __builtin_expect directive is supported'''
814    self.pushLanguage(self.languages.clanguage)
815    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
816      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
817    self.popLanguage()
818
819  def configureFunctionName(self):
820    '''Sees if the compiler supports __func__ or a variant.'''
821    def getFunctionName(lang):
822      name = '"unknown"'
823      self.pushLanguage(lang)
824      for fname in ['__func__','__FUNCTION__']:
825        code = "if ("+fname+"[0] != 'm') return 1;"
826        if self.checkCompile('',code) and self.checkLink('',code):
827          name = fname
828          break
829      self.popLanguage()
830      return name
831    langs = []
832
833    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
834    if hasattr(self.compilers, 'CXX'):
835      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
836
837  def configureIntptrt(self):
838    '''Determine what to use for uintptr_t'''
839    def staticAssertSizeMatchesVoidStar(inc,typename):
840      # The declaration is an error if either array size is negative.
841      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
842      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
843                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
844    self.pushLanguage(self.languages.clanguage)
845    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
846      self.addDefine('UINTPTR_T', 'uintptr_t')
847    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
848      self.addDefine('UINTPTR_T', 'unsigned long long')
849    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
850      self.addDefine('UINTPTR_T', 'size_t')
851    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
852      self.addDefine('UINTPTR_T', 'unsigned long')
853    elif staticAssertSizeMatchesVoidStar('','unsigned'):
854      self.addDefine('UINTPTR_T', 'unsigned')
855    else:
856      raise RuntimeError('Could not find any unsigned integer type matching void*')
857    self.popLanguage()
858
859  def configureRTLDDefault(self):
860    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
861      self.addDefine('RTLD_DEFAULT','1')
862    return
863
864  def configureSolaris(self):
865    '''Solaris specific stuff'''
866    if os.path.isdir(os.path.join('/usr','ucblib')):
867      try:
868        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
869      except AttributeError:
870        flag = None
871      if flag is None:
872        self.compilers.LIBS += ' -L/usr/ucblib'
873      else:
874        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
875    return
876
877  def configureLinux(self):
878    '''Linux specific stuff'''
879    # TODO: Test for this by mallocing an odd number of floats and checking the address
880    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
881    return
882
883  def configureWin32(self):
884    '''Win32 non-cygwin specific stuff'''
885    kernel32=0
886    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
887      self.addDefine('HAVE_WINDOWS_H',1)
888      self.addDefine('HAVE_GETCOMPUTERNAME',1)
889      kernel32=1
890    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
891      self.addDefine('HAVE_WINDOWS_H',1)
892      self.addDefine('HAVE_GETCOMPUTERNAME',1)
893      kernel32=1
894    if kernel32:
895      if self.framework.argDB['with-windows-graphics']:
896        self.addDefine('USE_WINDOWS_GRAPHICS',1)
897      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
898        self.addDefine('HAVE_LOADLIBRARY',1)
899      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
900        self.addDefine('HAVE_GETPROCADDRESS',1)
901      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
902        self.addDefine('HAVE_FREELIBRARY',1)
903      if self.checkLink('#include <Windows.h>','GetLastError()'):
904        self.addDefine('HAVE_GETLASTERROR',1)
905      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
906        self.addDefine('HAVE_SETLASTERROR',1)
907      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
908        self.addDefine('USE_MICROSOFT_TIME',1)
909    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
910      self.addDefine('HAVE_GET_USER_NAME',1)
911    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
912      self.addDefine('HAVE_GET_USER_NAME',1)
913
914    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
915      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
916    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
917      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
918
919    self.types.check('int32_t', 'int')
920    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
921      self.addTypedef('int', 'uid_t')
922      self.addTypedef('int', 'gid_t')
923    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
924      self.framework.addDefine('R_OK', '04')
925      self.framework.addDefine('W_OK', '02')
926      self.framework.addDefine('X_OK', '01')
927    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
928      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
929      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
930    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
931      self.addDefine('HAVE_LARGE_INTEGER_U',1)
932
933    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
934    if self.checkCompile('#include <Windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
935      self.addDefine('HAVE_O_BINARY',1)
936
937    if self.compilers.CC.find('win32fe') >= 0:
938      self.addDefine('HAVE_WINDOWS_COMPILERS',1)
939      self.addDefine('PATH_SEPARATOR','\';\'')
940      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
941      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
942      self.addDefine('CANNOT_START_DEBUGGER',1)
943      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log)
944      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
945      (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log)
946      self.addMakeMacro('wPETSC_DIR',petscdir)
947    else:
948      self.addDefine('PATH_SEPARATOR','\':\'')
949      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
950      self.addDefine('DIR_SEPARATOR','\'/\'')
951      self.addDefine('DIR','"'+self.installdir.petscDir+'"')
952      self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir)
953    self.addDefine('ARCH','"'+self.installdir.petscArch+'"')
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('$(PETSC_DIR)','$(PETSC_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