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