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