xref: /petsc/config/PETSc/Configure.py (revision 9b81490a800f1846a667dcbc6448a0dbbfe9b1c7)
1import config.base
2
3import os
4import sys
5import re
6import pickle
7import textwrap
8
9class Configure(config.base.Configure):
10  def __init__(self, framework):
11    config.base.Configure.__init__(self, framework)
12    self.headerPrefix = 'PETSC'
13    self.substPrefix  = 'PETSC'
14    self.installed    = 0 # 1 indicates that Configure itself has already compiled and installed PETSc
15    self.found        = 1
16    return
17
18  def __str2__(self):
19    desc = ['  Using GNU make: ' + self.make.make]
20    if self.defines.get('USE_COVERAGE'):
21      desc.extend([
22        '  Code coverage: yes',
23        '  Using code coverage executable: {}'.format(self.getMakeMacro('PETSC_COVERAGE_EXEC'))
24      ])
25    if not self.installed:
26      desc.append('xxx=========================================================================xxx')
27      desc.append(' Configure stage complete. Now build PETSc libraries with:')
28      desc.append('   %s PETSC_DIR=%s PETSC_ARCH=%s all' % (self.make.make_user, self.petscdir.dir, self.arch.arch))
29      desc.append('xxx=========================================================================xxx')
30    else:
31      desc.append('xxx=========================================================================xxx')
32      desc.append(' Installation complete. You do not need to run make to compile or install the software')
33      desc.append('xxx=========================================================================xxx')
34    desc.append('')
35    return '\n'.join(desc)
36
37  def setupHelp(self, help):
38    import nargs
39    help.addArgument('PETSc',  '-prefix=<dir>',                              nargs.Arg(None, '', 'Specifiy location to install PETSc (eg. /usr/local)'))
40    help.addArgument('PETSc',  '-with-prefetch=<bool>',                      nargs.ArgBool(None, 1,'Enable checking for prefetch instructions'))
41    help.addArgument('Windows','-with-windows-graphics=<bool>',              nargs.ArgBool(None, 1,'Enable check for Windows Graphics'))
42    help.addArgument('PETSc', '-with-default-arch=<bool>',                   nargs.ArgBool(None, 1, 'Allow using the last configured arch without setting PETSC_ARCH'))
43    help.addArgument('PETSc','-with-single-library=<bool>',                  nargs.ArgBool(None, 1,'Put all PETSc code into the single -lpetsc library'))
44    help.addArgument('PETSc','-with-fortran-bindings=<bool>',                nargs.ArgBool(None, 1,'Build PETSc fortran bindings in the library and corresponding module files'))
45    help.addArgument('PETSc', '-with-ios=<bool>',                            nargs.ArgBool(None, 0, 'Build an iPhone/iPad version of PETSc library'))
46    help.addArgument('PETSc', '-with-display=<x11display>',                  nargs.Arg(None, '', 'Specifiy DISPLAY env variable for use with matlab test)'))
47    help.addArgument('PETSc', '-with-package-scripts=<pyscripts>',           nargs.ArgFileList(None,None,'Specify configure package scripts for user provided packages'))
48    help.addArgument('PETSc', '-with-coverage=<bool>',                       nargs.ArgFuzzyBool(None, value=0, help='Enable or disable code-coverage collection'))
49    help.addArgument('PETSc', '-with-coverage-exec=<executable>',            nargs.ArgExecutable(None, value='default-auto', mustExist=0, help='Name of executable to use for post-processing coverage data, e.g. \'gcov\' or \'llvm-cov\'. Pass \'auto\' to let configure infer from compiler'))
50    help.addArgument('PETSc', '-with-tau-perfstubs=<bool>',                  nargs.ArgBool(None, 1,'Enable TAU profiler stubs'))
51    help.addArgument('PETSc', '-with-strict-petscerrorcode=<bool>',          nargs.ArgFuzzyBool(None, value=0, help='Enable strict PetscErrorCode mode, which enables additional compile-time checking for misuse of PetscErrorCode and error handling'))
52    return
53
54  def registerPythonFile(self,filename,directory):
55    ''' Add a python file to the framework and registers its headerprefix, ... externalpackagedir
56        directory is the directory where the file relative to the BuildSystem or config path in python notation with . '''
57    (utilityName, ext) = os.path.splitext(filename)
58    if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__':
59      if directory: directory = directory+'.'
60      utilityObj                             = self.framework.require(directory+utilityName, self)
61      utilityObj.headerPrefix                = self.headerPrefix
62      utilityObj.archProvider                = self.arch
63      utilityObj.languageProvider            = self.languages
64      utilityObj.installDirProvider          = self.installdir
65      utilityObj.externalPackagesDirProvider = self.externalpackagesdir
66      utilityObj.precisionProvider           = self.scalartypes
67      utilityObj.indexProvider               = self.indexTypes
68      setattr(self, utilityName.lower(), utilityObj)
69      return utilityObj
70    return None
71
72  def setupDependencies(self, framework):
73    config.base.Configure.setupDependencies(self, framework)
74    self.programs      = framework.require('config.programs',           self)
75    self.setCompilers  = framework.require('config.setCompilers',       self)
76    self.compilerFlags = framework.require('config.compilerFlags',      self)
77    self.compilers     = framework.require('config.compilers',          self)
78    self.arch          = framework.require('PETSc.options.arch',        self.setCompilers)
79    self.petscdir      = framework.require('PETSc.options.petscdir',    self.arch)
80    self.installdir    = framework.require('PETSc.options.installDir',  self)
81    self.dataFilesPath = framework.require('PETSc.options.dataFilesPath',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.indexTypes    = framework.require('PETSc.options.indexTypes',  self.compilers)
86    self.types         = framework.require('config.types',              self)
87    self.headers       = framework.require('config.headers',            self)
88    self.functions     = framework.require('config.functions',          self)
89    self.libraries     = framework.require('config.libraries',          self)
90    self.atomics       = framework.require('config.atomics',            self)
91    self.make          = framework.require('config.packages.make',      self)
92    self.blasLapack    = framework.require('config.packages.BlasLapack',self)
93    self.mpi           = framework.require('config.packages.MPI',       self)
94    self.fortran       = framework.require('config.compilersFortran',   self)
95    self.externalpackagesdir = framework.require('PETSc.options.externalpackagesdir',self)
96
97    for utility in sorted(os.listdir(os.path.join('config','PETSc','options'))):
98      self.registerPythonFile(utility,'PETSc.options')
99
100    for utility in sorted(os.listdir(os.path.join('config','BuildSystem','config','utilities'))):
101      self.registerPythonFile(utility,'config.utilities')
102
103    for package in sorted(os.listdir(os.path.join('config', 'BuildSystem', 'config', 'packages'))):
104      obj = self.registerPythonFile(package,'config.packages')
105      if obj:
106        obj.archProvider                = self.framework.requireModule(obj.archProvider, obj)
107        obj.languageProvider            = self.framework.requireModule(obj.languageProvider, obj)
108        obj.installDirProvider          = self.framework.requireModule(obj.installDirProvider, obj)
109        obj.externalPackagesDirProvider = self.framework.requireModule(obj.externalPackagesDirProvider, obj)
110        obj.precisionProvider           = self.framework.requireModule(obj.precisionProvider, obj)
111        obj.indexProvider               = self.framework.requireModule(obj.indexProvider, obj)
112
113    # Force blaslapack and opencl to depend on scalarType so precision is set before BlasLapack is built
114    framework.require('PETSc.options.scalarTypes', self.f2cblaslapack)
115    framework.require('PETSc.options.scalarTypes', self.fblaslapack)
116    framework.require('PETSc.options.scalarTypes', self.blaslapack)
117    framework.require('PETSc.options.scalarTypes', self.opencl)
118
119    self.programs.headerPrefix     = self.headerPrefix
120    self.setCompilers.headerPrefix = self.headerPrefix
121    self.compilers.headerPrefix    = self.headerPrefix
122    self.fortran.headerPrefix      = self.headerPrefix
123    self.types.headerPrefix        = self.headerPrefix
124    self.headers.headerPrefix      = self.headerPrefix
125    self.functions.headerPrefix    = self.headerPrefix
126    self.libraries.headerPrefix    = self.headerPrefix
127
128    # Register user provided package scripts
129    if 'with-package-scripts' in self.framework.argDB:
130      for script in self.framework.argDB['with-package-scripts']:
131        if os.path.splitext(script)[1] != '.py':
132          raise RuntimeError('Only python scripts compatible with configure package script format should be specified! Invalid option -with-package-scripts='+script)
133        self.framework.logPrint('User is registering a new package script: '+script)
134        dname,fname = os.path.split(script)
135        if dname: sys.path.append(dname)
136        self.registerPythonFile(fname,'')
137
138    # test for a variety of basic headers and functions
139    headersC = map(lambda name: name+'.h',['setjmp','dos','fcntl','float','io','malloc','pwd','strings',
140                                            'unistd','machine/endian','sys/param','sys/procfs','sys/resource',
141                                            'sys/systeminfo','sys/times','sys/utsname',
142                                            'sys/socket','sys/wait','netinet/in','netdb','direct','time','Ws2tcpip','sys/types',
143                                            'WindowsX','float','ieeefp','stdint','inttypes','immintrin'])
144    functions = ['access','_access','clock','drand48','getcwd','_getcwd','getdomainname','gethostname',
145                 'getwd','posix_memalign','popen','PXFGETARG','rand','getpagesize',
146                 'readlink','realpath','usleep','sleep','_sleep',
147                 'uname','snprintf','_snprintf','lseek','_lseek','time','fork','stricmp',
148                 'strcasecmp','bzero','dlopen','dlsym','dlclose','dlerror',
149                 '_set_output_format','_mkdir','socket','gethostbyname','fpresetsticky',
150                 'fpsetsticky','__gcov_dump']
151    libraries = [(['fpe'],'handle_sigfpes')]
152    librariessock = [(['socket','nsl'],'socket')]
153    self.headers.headers.extend(headersC)
154    self.functions.functions.extend(functions)
155    self.libraries.libraries.extend(libraries)
156    if not hasattr(self,'socket'):
157      self.libraries.libraries.extend(librariessock)
158    return
159
160  def DumpPkgconfig(self, petsc_pc):
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    with open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig',petsc_pc),'w') as fd:
165      cflags_inc = ['-I${includedir}']
166      if self.framework.argDB['prefix']:
167        fd.write('prefix='+self.installdir.dir+'\n')
168      else:
169        fd.write('prefix='+os.path.join(self.petscdir.dir, self.arch.arch)+'\n')
170        cflags_inc.append('-I' + os.path.join(self.petscdir.dir, 'include'))
171      fd.write('exec_prefix=${prefix}\n')
172      fd.write('includedir=${prefix}/include\n')
173      fd.write('libdir=${prefix}/lib\n')
174
175      with self.setCompilers.Language('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      if hasattr(self.compilers, 'CXX'):
181        with self.setCompilers.Language('C++'):
182          fd.write('cxxcompiler='+self.setCompilers.getCompiler()+'\n')
183          fd.write('cxxflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
184      if hasattr(self.compilers, 'FC'):
185        with self.setCompilers.Language('FC'):
186          fd.write('fcompiler='+self.setCompilers.getCompiler()+'\n')
187          fd.write('fflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
188      if hasattr(self.compilers, 'CUDAC'):
189        with self.setCompilers.Language('CUDA'):
190          fd.write('cudacompiler='+self.setCompilers.getCompiler()+'\n')
191          fd.write('cudaflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
192          p = self.framework.require('config.packages.cuda')
193          fd.write('cudalib='+self.libraries.toStringNoDupes(p.lib)+'\n')
194          fd.write('cudainclude='+self.headers.toStringNoDupes(p.include)+'\n')
195          if hasattr(self.setCompilers,'CUDA_CXX'):
196            fd.write('cuda_cxx='+self.setCompilers.CUDA_CXX+'\n')
197            fd.write('cuda_cxxflags='+self.setCompilers.CUDA_CXXFLAGS+'\n')
198
199      fd.write('\n')
200      fd.write('Name: PETSc\n')
201      fd.write('Description: Library to solve ODEs and algebraic equations\n')
202      fd.write('Version: %s\n' % self.petscdir.version)
203      fd.write('Cflags: ' + ' '.join([self.setCompilers.CPPFLAGS] + cflags_inc) + '\n')
204      fd.write('Libs: '+self.libraries.toStringNoDupes(['-L${libdir}', self.petsclib], with_rpath=False)+'\n')
205      # Remove RPATH flags from library list.  User can add them using
206      # pkg-config --variable=ldflag_rpath and pkg-config --libs-only-L
207      fd.write('Libs.private: '+self.libraries.toStringNoDupes([f for f in self.packagelibs+self.complibs if not f.startswith(self.setCompilers.CSharedLinkerFlag)], with_rpath=False)+'\n')
208    return
209
210  def DumpModule(self):
211    ''' Create a module file '''
212    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules')):
213      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules'))
214    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc')):
215      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc'))
216    if self.framework.argDB['prefix']:
217      installdir  = self.installdir.dir
218      installarch = ''
219      installpath = os.path.join(installdir,'bin')
220    else:
221      installdir  = self.petscdir.dir
222      installarch = self.arch.arch
223      installpath = os.path.join(installdir,installarch,'bin')+':'+os.path.join(installdir,'bin')
224    fd = open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc',self.petscdir.version),'w')
225    fd.write('''\
226#%%Module
227
228proc ModulesHelp { } {
229    puts stderr "This module sets the path and environment variables for petsc-%s"
230    puts stderr "     see https://petsc.org/ for more information      "
231    puts stderr ""
232}
233module-whatis "PETSc - Portable, Extensible Toolkit for Scientific Computation"
234
235set petsc_dir   "%s"
236set petsc_arch  "%s"
237
238setenv PETSC_ARCH "$petsc_arch"
239setenv PETSC_DIR "$petsc_dir"
240prepend-path PATH "%s"
241''' % (self.petscdir.version, installdir, installarch, installpath))
242    fd.close()
243    return
244
245  def Dump(self):
246    ''' Actually put the values into the configuration files '''
247    # eventually everything between -- should be gone
248    if self.mpi.usingMPIUni:
249      #
250      # Remove any MPI/MPICH include files that may have been put here by previous runs of ./configure
251      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)
252
253    self.logPrintDivider()
254    # Test for compiler-specific macros that need to be defined.
255    if self.setCompilers.isCrayVector('CC', self.log):
256      self.addDefine('HAVE_CRAY_VECTOR','1')
257
258    if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket') and self.headers.haveHeader('netinet/in.h'):
259      self.addDefine('USE_SOCKET_VIEWER','1')
260      if self.checkCompile('#include <sys/socket.h>','setsockopt(0,SOL_SOCKET,SO_REUSEADDR,0,0)'):
261        self.addDefine('HAVE_SO_REUSEADDR','1')
262
263    self.logPrintDivider()
264    self.setCompilers.pushLanguage('C')
265    compiler = self.setCompilers.getCompiler()
266    if [s for s in ['mpicc','mpiicc'] if os.path.basename(compiler).find(s)>=0]:
267      try:
268        output   = self.executeShellCommand(compiler + ' -show', log = self.log)[0]
269        compiler = output.split(' ')[0]
270        self.addDefine('MPICC_SHOW','"'+output.strip().replace('\n','\\\\n').replace('"','')+'"')
271      except:
272        self.addDefine('MPICC_SHOW','"Unavailable"')
273    else:
274      self.addDefine('MPICC_SHOW','"Unavailable"')
275    self.setCompilers.popLanguage()
276#-----------------------------------------------------------------------------------------------------
277
278    # Sometimes we need C compiler, even if built with C++
279    self.setCompilers.pushLanguage('C')
280    # do not use getCompilerFlags() because that automatically includes the CPPFLAGS so one ends up with duplication flags in makefile usage
281    self.addMakeMacro('CC_FLAGS',self.setCompilers.CFLAGS)
282    self.setCompilers.popLanguage()
283
284    # And sometimes we need a C++ compiler even when PETSc is built with C
285    if hasattr(self.compilers, 'CXX'):
286      self.setCompilers.pushLanguage('Cxx')
287      self.addDefine('HAVE_CXX','1')
288      self.addMakeMacro('CXXPP_FLAGS',self.setCompilers.CXXPPFLAGS)
289      # do not use getCompilerFlags() because that automatically includes the CXXPPFLAGS so one ends up with duplication flags in makefile usage
290      self.addMakeMacro('CXX_FLAGS',self.setCompilers.CXXFLAGS+' '+self.setCompilers.CXX_CXXFLAGS)
291      cxx_linker = self.setCompilers.getLinker()
292      self.addMakeMacro('CXX_LINKER',cxx_linker)
293      self.addMakeMacro('CXX_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
294      self.setCompilers.popLanguage()
295
296    # C preprocessor values
297    self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS)
298
299    # compiler values
300    self.setCompilers.pushLanguage(self.languages.clanguage)
301    self.addMakeMacro('PCC',self.setCompilers.getCompiler())
302    # do not use getCompilerFlags() because that automatically includes the preprocessor flags so one ends up with duplication flags in makefile usage
303    if self.languages.clanguage == 'C':
304      self.addMakeMacro('PCC_FLAGS','$(CC_FLAGS)')
305    else:
306      self.addMakeMacro('PCC_FLAGS','$(CXX_FLAGS)')
307    self.setCompilers.popLanguage()
308    # .o or .obj
309    self.addMakeMacro('CC_SUFFIX','o')
310
311    # executable linker values
312    self.setCompilers.pushLanguage(self.languages.clanguage)
313    pcc_linker = self.setCompilers.getLinker()
314    self.addMakeMacro('PCC_LINKER',pcc_linker)
315    self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
316    self.setCompilers.popLanguage()
317    # '' for Unix, .exe for Windows
318    self.addMakeMacro('CC_LINKER_SUFFIX','')
319
320    if hasattr(self.compilers, 'FC'):
321      if self.framework.argDB['with-fortran-bindings']:
322        if not self.fortran.fortranIsF90:
323          raise RuntimeError('Error! Fortran compiler "'+self.compilers.FC+'" does not support F90! PETSc fortran bindings require a F90 compiler')
324        self.addDefine('HAVE_FORTRAN','1')
325      self.setCompilers.pushLanguage('FC')
326      # need FPPFLAGS in config/setCompilers
327      self.addMakeMacro('FPP_FLAGS',self.setCompilers.FPPFLAGS)
328
329      # compiler values
330      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
331      self.setCompilers.popLanguage()
332      # .o or .obj
333      self.addMakeMacro('FC_SUFFIX','o')
334
335      # executable linker values
336      self.setCompilers.pushLanguage('FC')
337      self.addMakeMacro('FC_LINKER',self.setCompilers.getLinker())
338      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
339      self.setCompilers.popLanguage()
340
341      # F90 Modules
342      if self.setCompilers.fortranModuleIncludeFlag:
343        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
344      else: # for non-f90 compilers like g77
345        self.addMakeMacro('FC_MODULE_FLAG', '-I')
346      if self.setCompilers.fortranModuleIncludeFlag:
347        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
348    else:
349      self.addMakeMacro('FC','')
350
351    if hasattr(self.compilers, 'CUDAC'):
352      self.setCompilers.pushLanguage('CUDA')
353      self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags())
354      self.addMakeMacro('CUDAPP_FLAGS',self.setCompilers.CUDAPPFLAGS)
355      self.setCompilers.popLanguage()
356
357    if hasattr(self.compilers, 'HIPC'):
358      self.setCompilers.pushLanguage('HIP')
359      self.addMakeMacro('HIPC_FLAGS',self.setCompilers.getCompilerFlags())
360      self.addMakeMacro('HIPPP_FLAGS',self.setCompilers.HIPPPFLAGS)
361      self.setCompilers.popLanguage()
362
363    if hasattr(self.compilers, 'SYCLC'):
364      self.setCompilers.pushLanguage('SYCL')
365      self.addMakeMacro('SYCLC_FLAGS',self.setCompilers.getCompilerFlags())
366      self.addMakeMacro('SYCLPP_FLAGS',self.setCompilers.SYCLPPFLAGS)
367      self.setCompilers.popLanguage()
368
369    # shared library linker values
370    self.setCompilers.pushLanguage(self.languages.clanguage)
371    # need to fix BuildSystem to collect these separately
372    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
373    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
374    self.setCompilers.popLanguage()
375    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
376    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
377    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
378      self.addMakeMacro('SL_LINKER_SUFFIX', '')
379      self.addDefine('SLSUFFIX','""')
380    else:
381      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
382      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
383
384    self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}')
385
386#-----------------------------------------------------------------------------------------------------
387
388    # CONLY or CPP. We should change the PETSc makefiles to do this better
389    if self.languages.clanguage == 'C': lang = 'CONLY'
390    else: lang = 'CXXONLY'
391    self.addMakeMacro('PETSC_LANGUAGE',lang)
392
393    # real or complex
394    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
395    # double or float
396    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
397
398    if self.framework.argDB['with-batch']:
399      self.addMakeMacro('PETSC_WITH_BATCH','1')
400
401#-----------------------------------------------------------------------------------------------------
402    # print include and lib for makefiles
403    self.logPrintDivider()
404    self.framework.packages.reverse()
405    petscincludes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')]
406    petscincludes_install = [os.path.join(self.installdir.dir, 'include')] if self.framework.argDB['prefix'] else petscincludes
407    includes = []
408    self.packagelibs = []
409    for i in self.framework.packages:
410      if not i.required:
411        if i.devicePackage:
412          self.addDefine('HAVE_DEVICE',1)
413        self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
414      if not isinstance(i.lib, list):
415        i.lib = [i.lib]
416      if i.linkedbypetsc: self.packagelibs.extend(i.lib)
417      self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib))
418      if hasattr(i,'include'):
419        if not isinstance(i.include,list):
420          i.include = [i.include]
421        includes.extend(i.include)
422        self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include))
423    if self.framework.argDB['with-single-library']:
424      self.petsclib = '-lpetsc'
425    else:
426      self.petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
427    self.complibs = self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split()
428    self.PETSC_WITH_EXTERNAL_LIB = self.libraries.toStringNoDupes(['-L${PETSC_DIR}/${PETSC_ARCH}/lib', self.petsclib]+self.packagelibs+self.complibs)
429    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(self.packagelibs+self.complibs)
430
431    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.PETSC_EXTERNAL_LIB_BASIC)
432    allincludes = petscincludes + includes
433    allincludes_install = petscincludes_install + includes
434    self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(allincludes)
435    self.PETSC_CC_INCLUDES_INSTALL = self.headers.toStringNoDupes(allincludes_install)
436    self.addMakeMacro('PETSC_CC_INCLUDES',self.PETSC_CC_INCLUDES)
437    self.addMakeMacro('PETSC_CC_INCLUDES_INSTALL', self.PETSC_CC_INCLUDES_INSTALL)
438    if hasattr(self.compilers, 'FC'):
439      def modinc(includes):
440        return includes if self.fortran.fortranIsF90 else []
441      self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(allincludes,modinc(allincludes)))
442      self.addMakeMacro('PETSC_FC_INCLUDES_INSTALL',self.headers.toStringNoDupes(allincludes_install,modinc(allincludes_install)))
443
444    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"')
445
446    if self.framework.argDB['with-single-library']:
447      # overrides the values set in conf/variables
448      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
449      self.addMakeMacro('SHLIBS','libpetsc')
450      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
451      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
452      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
453      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
454      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.PETSC_WITH_EXTERNAL_LIB)
455      self.addDefine('USE_SINGLE_LIBRARY', '1')
456      if self.sharedlibraries.useShared:
457        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
458        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
459        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
460        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
461        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
462        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
463        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
464        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
465        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
466        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
467        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
468      else:
469        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
470        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
471        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
472        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
473        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
474        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
475        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
476        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
477        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
478        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
479        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
480
481    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
482      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
483
484# add a makefile endtry for display
485    if self.framework.argDB['with-display']:
486      self.addMakeMacro('DISPLAY',self.framework.argDB['with-display'])
487
488    # add a makefile entry for configure options
489    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
490
491    if self.framework.argDB['with-tau-perfstubs']:
492      self.addDefine('HAVE_TAU_PERFSTUBS',1)
493    return
494
495  def dumpConfigInfo(self):
496    import time
497    fd = open(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
498    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"').replace('\\ ','\\\\ ')+'";\n')
499    fd.close()
500    return
501
502  def dumpMachineInfo(self):
503    import platform
504    import datetime
505    import time
506    import script
507    def escape(s):
508      return s.replace('"',r'\"').replace(r'\ ',r'\\ ') # novermin
509    fd = open(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
510    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
511    fd.write('\"-----------------------------------------\\n\"\n')
512    buildhost = platform.node()
513    if os.environ.get('SOURCE_DATE_EPOCH'):
514      buildhost = "reproducible"
515    buildtime = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
516    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (buildtime, buildhost))
517    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
518    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir)))
519    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch)))
520    fd.write('\"-----------------------------------------\\n\";\n')
521    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
522    self.setCompilers.pushLanguage(self.languages.clanguage)
523    fd.write('\"Using C compiler: %s %s \\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
524    self.setCompilers.popLanguage()
525    if hasattr(self.compilers, 'FC'):
526      self.setCompilers.pushLanguage('FC')
527      fd.write('\"Using Fortran compiler: %s %s  %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
528      self.setCompilers.popLanguage()
529    fd.write('\"-----------------------------------------\\n\";\n')
530    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
531    fd.write('\"Using include paths: %s\\n\"\n' % (escape(self.PETSC_CC_INCLUDES_INSTALL.replace('${PETSC_DIR}', self.installdir.petscDir))))
532    fd.write('\"-----------------------------------------\\n\";\n')
533    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
534    self.setCompilers.pushLanguage(self.languages.clanguage)
535    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
536    self.setCompilers.popLanguage()
537    if hasattr(self.compilers, 'FC'):
538      self.setCompilers.pushLanguage('FC')
539      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
540      self.setCompilers.popLanguage()
541    fd.write('\"Using libraries: %s%s -L%s %s %s\\n\"\n' % (escape(self.setCompilers.CSharedLinkerFlag), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(self.petsclib), escape(self.PETSC_EXTERNAL_LIB_BASIC)))
542    fd.write('\"-----------------------------------------\\n\";\n')
543    fd.close()
544    return
545
546  def configurePrefetch(self):
547    '''Sees if there are any prefetch functions supported'''
548    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
549      self.addDefine('Prefetch(a,b,c)', ' ')
550      return
551    self.pushLanguage(self.languages.clanguage)
552    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
553      # The Intel Intrinsics manual [1] specifies the prototype
554      #
555      #   void _mm_prefetch(char const *a, int sel);
556      #
557      # but other vendors seem to insist on using subtly different
558      # prototypes, including void* for the pointer, and an enum for
559      # sel.  These are both reasonable changes, but negatively impact
560      # portability.
561      #
562      # [1] https://software.intel.com/file/6373
563      self.addDefine('HAVE_XMMINTRIN_H', 1)
564      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
565      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
566      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
567      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
568      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
569    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
570      self.addDefine('HAVE_XMMINTRIN_H', 1)
571      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
572      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
573      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
574      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
575      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
576    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
577      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
578      #
579      #   The value of rw is a compile-time constant one or zero; one
580      #   means that the prefetch is preparing for a write to the memory
581      #   address and zero, the default, means that the prefetch is
582      #   preparing for a read. The value locality must be a compile-time
583      #   constant integer between zero and three. A value of zero means
584      #   that the data has no temporal locality, so it need not be left
585      #   in the cache after the access. A value of three means that the
586      #   data has a high degree of temporal locality and should be left
587      #   in all levels of cache possible. Values of one and two mean,
588      #   respectively, a low or moderate degree of temporal locality.
589      #
590      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
591      # hints.  Using macros for these values in necessary since some
592      # compilers require an enum.
593      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
594      self.addDefine('PREFETCH_HINT_NTA', '0')
595      self.addDefine('PREFETCH_HINT_T0',  '3')
596      self.addDefine('PREFETCH_HINT_T1',  '2')
597      self.addDefine('PREFETCH_HINT_T2',  '1')
598    else:
599      self.addDefine('Prefetch(a,b,c)', ' ')
600    self.popLanguage()
601
602  def delGenFiles(self):
603    '''Delete generated files'''
604    delfile = os.path.join(self.arch.arch,'lib','petsc','conf','files')
605    try:
606      os.unlink(delfile)
607    except: pass
608
609  def configureAtoll(self):
610    '''Checks if atoll exists'''
611    if self.checkLink('#define _POSIX_C_SOURCE 200112L\n#include <stdlib.h>','long v = atoll("25");\n(void)v') or self.checkLink ('#include <stdlib.h>','long v = atoll("25");\n(void)v'):
612       self.addDefine('HAVE_ATOLL', '1')
613
614  def configureUnused(self):
615    '''Sees if __attribute((unused)) is supported'''
616    if self.framework.argDB['with-ios']:
617      self.addDefine('UNUSED', ' ')
618      return
619    self.pushLanguage(self.languages.clanguage)
620    if self.checkLink('__attribute((unused)) static int myfunc(__attribute((unused)) void *name){ return 1;}', 'int i = 0;\nint j = myfunc(&i);\n(void)j;\ntypedef void* atype;\n__attribute((unused))  atype a'):
621      self.addDefine('UNUSED', '__attribute((unused))')
622    else:
623      self.addDefine('UNUSED', ' ')
624    self.popLanguage()
625
626  def configureIsatty(self):
627    '''Check if the Unix C function isatty() works correctly
628       Actually just assumes it does not work correctly on batch systems'''
629    if not self.framework.argDB['with-batch']:
630      self.addDefine('USE_ISATTY',1)
631
632  def configureDeprecated(self):
633    '''Check if __attribute((deprecated)) is supported'''
634    def checkDeprecated(macro_base, src, is_intel):
635      '''
636      run through the various attribute deprecated combinations and define MACRO_BAS(why) to the result
637      it if it compiles.
638
639      If none of the combos work, defines MACRO_BASE(why) as empty
640      '''
641      full_macro_name = macro_base + '(why)'
642      for prefix in ('__attribute__', '__attribute','__declspec'):
643        if prefix == '__declspec':
644          # declspec does not have an extra set of brackets around the arguments
645          attr_bodies = ('deprecated(why)', 'deprecated')
646        else:
647          attr_bodies = ('(deprecated(why))', '(deprecated)')
648
649        for attr_body in attr_bodies:
650          attr_def = '{}({})'.format(prefix, attr_body)
651          test_src = '\n'.join((
652            '#define {} {}'.format(full_macro_name, attr_def),
653            src.format(macro_base + '("asdasdadsasd")')
654          ))
655          if self.checkCompile(test_src, ''):
656            self.logPrint('configureDeprecated: \'{}\' appears to work'.format(attr_def))
657            if is_intel and '(why)' in attr_body:
658              self.logPrint('configureDeprecated: Intel has conspired to make a supremely environment-sensitive compiler. The Intel compiler looks at the gcc executable in the environment to determine the language compatibility that it should attempt to emulate. Some important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g. 4.7). Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc found in the default user environment is older and does not support the argument.\n'.format(attr_def))
659              self.logPrint('*** WE WILL THEREFORE REJECT \'{}\' AND CONTINUE TESTING ***'.format(attr_def))
660              continue
661            self.addDefine(full_macro_name, attr_def)
662            return
663
664      self.addDefine(full_macro_name, ' ')
665      return
666
667    lang = self.languages.clanguage
668    with self.Language(lang):
669      is_intel = self.setCompilers.isIntel(self.getCompiler(lang=lang), self.log)
670      checkDeprecated('DEPRECATED_FUNCTION', '{} int myfunc(void) {{ return 1; }}', is_intel)
671      checkDeprecated('DEPRECATED_TYPEDEF', 'typedef int my_int {};', is_intel)
672      checkDeprecated('DEPRECATED_ENUM', 'enum E {{ oldval {}, newval }};', is_intel)
673      # I was unable to make a CPP macro that takes the old and new values as separate
674      # arguments and builds the message needed by _Pragma hence the deprecation message is
675      # handled as it is
676      if self.checkCompile('#define TEST _Pragma("GCC warning \"Testing _Pragma\"") value'):
677        self.addDefine('DEPRECATED_MACRO(why)', '_Pragma(why)')
678      else:
679        self.addDefine('DEPRECATED_MACRO(why)', ' ')
680
681  def configureAlign(self):
682    '''Check if __attribute(aligned) is supported'''
683    code = '''\
684struct mystruct {int myint;} __attribute((aligned(16)));
685char assert_aligned[(sizeof(struct mystruct)==16)*2-1];
686'''
687    self.pushLanguage(self.languages.clanguage)
688    if self.checkCompile(code):
689      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned(size)))')
690      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
691    else:
692      self.framework.logPrint('Incorrect attribute(aligned)')
693      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
694    self.popLanguage()
695    return
696
697  def configureExpect(self):
698    '''Sees if the __builtin_expect directive is supported'''
699    self.pushLanguage(self.languages.clanguage)
700    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
701      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
702    self.popLanguage()
703
704  def configureFunctionName(self):
705    '''Sees if the compiler supports __func__ or a variant.'''
706    def getFunctionName(lang):
707      name = '"unknown"'
708      self.pushLanguage(lang)
709      for fname in ['__func__','__FUNCTION__','__extension__ __func__']:
710        code = "if ("+fname+"[0] != 'm') return 1;"
711        if self.checkCompile('',code) and self.checkLink('',code):
712          name = fname
713          break
714      self.popLanguage()
715      return name
716    langs = []
717
718    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
719    if hasattr(self.compilers, 'CXX'):
720      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
721
722  def configureIntptrt(self):
723    '''Determine what to use for uintptr_t and intptr_t'''
724    def staticAssertSizeMatchesVoidStar(inc,typename):
725      # The declaration is an error if either array size is negative.
726      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
727      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
728                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
729
730    def generate_uintptr_guesses():
731      for suff in ('max', '64', '32', '16'):
732        yield '#include <stdint.h>', 'uint{}_t'.format(suff), 'PRIx{}'.format(suff.upper())
733      yield '#include <stdlib.h>\n#include <string.h>', 'size_t', 'zx'
734      yield '', 'unsigned long long', 'llx'
735      yield '', 'unsigned long', 'lx'
736      yield '', 'unsigned', 'x'
737
738    def generate_intptr_guesses():
739      for suff in ('max', '64', '32', '16'):
740        yield '#include <stdint.h>', 'int{}_t'.format(suff), 'PRIx{}'.format(suff.upper())
741      yield '', 'long long', 'llx'
742      yield '', 'long', 'lx'
743      yield '', 'int', 'x'
744
745    def check(default_typename, generator):
746      macro_name = default_typename.upper()
747      with self.Language(self.languages.clanguage):
748        if self.checkCompile(
749            '#include <stdint.h>',
750            'int x; {type_name} i = ({type_name})&x; (void)i'.format(type_name=default_typename)
751        ):
752          typename     = default_typename
753          print_format = 'PRIxPTR'
754        else:
755          for include, typename, print_format in generator():
756            if staticAssertSizeMatchesVoidStar(include, typename):
757              break
758          else:
759            raise RuntimeError('Could not find any {} type matching void*'.format(macro_name))
760      self.addDefine(macro_name         , typename)
761      self.addDefine(macro_name + '_FMT', '\"#\" ' + print_format)
762      return
763
764    check('uintptr_t', generate_uintptr_guesses)
765    check('intptr_t', generate_intptr_guesses)
766    return
767
768  def configureRTLDDefault(self):
769    '''Check for dynamic library feature'''
770    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
771      self.addDefine('HAVE_RTLD_DEFAULT','1')
772    return
773
774  def configureSolaris(self):
775    '''Solaris specific stuff'''
776    if os.path.isdir(os.path.join('/usr','ucblib')):
777      try:
778        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
779      except AttributeError:
780        flag = None
781      if flag is None:
782        self.compilers.LIBS += ' -L/usr/ucblib'
783      else:
784        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
785    return
786
787  def configureDarwin(self):
788    '''Log brew configuration for Apple systems'''
789    try:
790      self.executeShellCommand(['brew', 'config'], log = self.log)
791      self.executeShellCommand(['brew', 'info', 'gcc'], log = self.log)
792    except:
793      pass
794    return
795
796  def configureLinux(self):
797    '''Linux specific stuff'''
798    # TODO: Test for this by mallocing an odd number of floats and checking the address
799    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
800    return
801
802  def configureWin32(self):
803    '''Win32 non-cygwin specific stuff'''
804    kernel32=0
805    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'):
806      self.addDefine('HAVE_WINDOWS_H',1)
807      self.addDefine('HAVE_GETCOMPUTERNAME',1)
808      kernel32=1
809    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'):
810      self.addDefine('HAVE_WINDOWS_H',1)
811      self.addDefine('HAVE_GETCOMPUTERNAME',1)
812      kernel32=1
813    if kernel32:
814      if self.framework.argDB['with-windows-graphics']:
815        self.addDefine('USE_WINDOWS_GRAPHICS',1)
816      if self.checkLink('#include <windows.h>','LoadLibrary(0)'):
817        self.addDefine('HAVE_LOADLIBRARY',1)
818      if self.checkLink('#include <windows.h>','GetProcAddress(0,0)'):
819        self.addDefine('HAVE_GETPROCADDRESS',1)
820      if self.checkLink('#include <windows.h>','FreeLibrary(0)'):
821        self.addDefine('HAVE_FREELIBRARY',1)
822      if self.checkLink('#include <windows.h>','GetLastError()'):
823        self.addDefine('HAVE_GETLASTERROR',1)
824      if self.checkLink('#include <windows.h>','SetLastError(0)'):
825        self.addDefine('HAVE_SETLASTERROR',1)
826      if self.checkLink('#include <windows.h>\n','QueryPerformanceCounter(0);\n'):
827        self.addDefine('USE_MICROSOFT_TIME',1)
828    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'):
829      self.addDefine('HAVE_GET_USER_NAME',1)
830    elif self.libraries.add('advapi32','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'):
831      self.addDefine('HAVE_GET_USER_NAME',1)
832
833    if not self.libraries.add('User32.lib','GetDC',prototype='#include <windows.h>',call='GetDC(0);'):
834      self.libraries.add('user32','GetDC',prototype='#include <windows.h>',call='GetDC(0);')
835    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);'):
836      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);')
837
838    self.types.check('int32_t', 'int')
839    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n(void)u'):
840      self.addTypedef('int', 'uid_t')
841      self.addTypedef('int', 'gid_t')
842    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n(void)a'):
843      self.framework.addDefine('R_OK', '04')
844      self.framework.addDefine('W_OK', '02')
845      self.framework.addDefine('X_OK', '01')
846    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
847      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
848      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
849    if self.checkCompile('#include <windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
850      self.addDefine('HAVE_LARGE_INTEGER_U',1)
851
852    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
853    if self.checkCompile('#include <windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
854      self.addDefine('HAVE_O_BINARY',1)
855
856    if self.compilers.CC.find('win32fe') >= 0:
857      self.addDefine('HAVE_WINDOWS_COMPILERS',1)
858      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
859      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
860      self.addDefine('CANNOT_START_DEBUGGER',1)
861      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log)
862      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
863      (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log)
864      self.addMakeMacro('wPETSC_DIR',petscdir)
865      if self.dataFilesPath.datafilespath:
866        (datafilespath,error,status) = self.executeShellCommand('cygpath -m '+self.dataFilesPath.datafilespath, log = self.log)
867        self.addMakeMacro('DATAFILESPATH',datafilespath)
868
869    else:
870      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
871      self.addDefine('DIR_SEPARATOR','\'/\'')
872      self.addDefine('DIR','"'+self.installdir.petscDir+'"')
873      self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir)
874      if self.dataFilesPath.datafilespath:
875        self.addMakeMacro('DATAFILESPATH',self.dataFilesPath.datafilespath)
876    self.addDefine('ARCH','"'+self.installdir.petscArch+'"')
877    return
878
879  def configureCoverageForLang(self, lang, extra_coverage_flags=None, extra_debug_flags=None):
880    """
881    Check that a compiler accepts code-coverage flags. If the compiler does accept code-coverage flags
882    try to set debugging flags equivalent to -Og.
883
884    Arguments:
885    - lang: the language to check the coverage flag for
886    - extra_coverage_flags: a list of extra flags to use when checking the coverage flags
887    - extra_debug_flags: a list of extra flags to try when setting debug flags
888
889    On success:
890    - defines PETSC_USE_COVERAGE to 1
891    """
892    try:
893      import inspect
894
895      FUNC_NAME = inspect.currentframe().f_code.co_name
896    except:
897      FUNC_NAME = 'Unknown'
898
899    def log_print(msg, *args, **kwargs):
900      self.logPrint('{}(): {}'.format(FUNC_NAME, msg), *args, **kwargs)
901      return
902
903    def quoted(string):
904      return string.join(("'", "'"))
905
906    def make_flag_list(default, extra):
907      ret = [default]
908      if extra is not None:
909        assert isinstance(extra, list)
910        ret.extend(extra)
911      return ret
912
913    log_print('Checking coverage flag for language {}'.format(lang))
914
915    compiler = self.getCompiler(lang=lang)
916    if self.setCompilers.isGNU(compiler, self.log):
917      compiler_kind = 'GNU'
918    elif self.setCompilers.isClang(compiler, self.log):
919      compiler_kind = 'clang'
920    else:
921      compiler_kind = ''
922
923    if not self.argDB['with-coverage']:
924      log_print('coverage was disabled from command line or default')
925      return
926
927    # if not gnuish and we don't have a set of extra flags, bail
928    if compiler_kind not in {'GNU', 'clang'} and extra_coverage_flags is None:
929      log_print('Don\'t know how to add coverage for compiler {}. Only know how to add coverage for gnu-like compilers (either gcc or clang). Skipping it!'.format(quoted(compiler)))
930      return
931
932    coverage_flags = make_flag_list('--coverage', extra_coverage_flags)
933    log_print('Checking set of coverage flags: {}'.format(coverage_flags))
934
935    found = None
936    with self.Language(lang):
937      with self.setCompilers.Language(lang):
938        for flag in coverage_flags:
939          # the linker also needs to see the coverage flag
940          with self.setCompilers.extraCompilerFlags([flag], compilerOnly=False) as skip_flags:
941            if not skip_flags and self.checkRun():
942              # flag was accepted
943              found = flag
944              break
945
946          log_print(
947            'Compiler {} did not accept coverage flag {}'.format(quoted(compiler), quoted(flag))
948          )
949
950        if found is None:
951          log_print(
952            'Compiler {} did not accept ANY coverage flags: {}, bailing!'.format(
953              quoted(compiler), coverage_flags
954            )
955          )
956          return
957
958        # must do this exactly here since:
959        #
960        # 1. setCompilers.extraCompilerFlags() will reset the compiler flags on __exit__()
961        #    (so cannot do it in the loop)
962        # 2. we need to set the compiler flag while setCompilers.Language() is still in
963        #    effect (so cannot do it outside the with statements)
964        self.setCompilers.insertCompilerFlag(flag, False)
965
966    if not self.functions.haveFunction('__gcov_dump'):
967      self.functions.checkClassify(['__gcov_dump'])
968
969    # now check if we can override the optimization level. It is only kosher to do so if
970    # the user did not explicitly set the optimization flags (via CFLAGS, CXXFLAGS,
971    # CXXOPTFLAGS, etc). If they have done so, we sternly warn them about their lapse in
972    # judgement
973    with self.Language(lang):
974      compiler_flags = self.getCompilerFlags()
975
976    user_set          = 0
977    allowed_opt_flags = re.compile(r'|'.join((r'-O[01g]', r'-g[1-9]*')))
978    for flagsname in [self.getCompilerFlagsName(lang), self.compilerFlags.getOptionalFlagsName(lang)]:
979      if flagsname in self.argDB:
980        opt_flags = [
981          f for f in self.compilerFlags.findOptFlags(compiler_flags) if not allowed_opt_flags.match(f)
982        ]
983        if opt_flags:
984          self.logPrintWarning('Coverage requested, but optimization flag(s) {} found in {}. Coverage collection will work, but may be less accurate. Suggest removing the flag and/or using -Og (or equivalent) instead'.format(', '.join(map(quoted, opt_flags)), quoted(flagsname)))
985          user_set = 1
986          break
987
988    if not user_set:
989      debug_flags = make_flag_list('-Og', extra_debug_flags)
990      with self.setCompilers.Language(lang):
991        for flag in debug_flags:
992          try:
993            self.setCompilers.addCompilerFlag(flag)
994          except RuntimeError:
995            continue
996          break
997
998    self.addDefine('USE_COVERAGE', 1)
999    return
1000
1001  def configureCoverage(self):
1002    for LANG in ['C', 'Cxx', 'CUDA', 'HIP', 'SYCL', 'FC']:
1003      compilerName = LANG.upper() if LANG in {'Cxx', 'FC'} else LANG + 'C'
1004      if hasattr(self.setCompilers, compilerName):
1005        kwargs = {}
1006        if LANG in {'CUDA'}:
1007          # nvcc preprocesses the base file into a bunch of intermediate files, which are
1008          # then compiled by the host compiler. Why is this a problem?  Because the
1009          # generated coverage data is based on these preprocessed source files! So gcov
1010          # tries to read it later, but since its in the tmp directory it cannot. Thus we
1011          # need to keep them around (in a place we know about).
1012          nvcc_tmp_dir = os.path.join(self.petscdir.dir, self.arch.arch, 'nvcc_tmp')
1013          try:
1014            os.mkdir(nvcc_tmp_dir)
1015          except FileExistsError:
1016            pass
1017          kwargs['extra_coverage_flags'] = [
1018            '-Xcompiler --coverage -Xcompiler -fPIC --keep --keep-dir={}'.format(nvcc_tmp_dir)
1019          ]
1020          if self.kokkos.found:
1021            # yet again the kokkos nvcc_wrapper goes out of its way to be as useless as
1022            # possible. Its default arch (sm_35) is actually too low to compile kokkos,
1023            # for whatever reason this works if you dont use the --keep and --keep-dir
1024            # flags above.
1025            kwargs['extra_coverage_flags'].append('-arch=native')
1026            kwargs['extra_debug_flags'] = ['-Xcompiler -Og']
1027        self.executeTest(self.configureCoverageForLang, args=[LANG], kargs=kwargs)
1028    return
1029
1030  def configureCoverageExecutable(self):
1031    """
1032    Check that a code-coverage collecting tool exists and is on PATH.
1033
1034    On success:
1035    - Adds PETSC_COVERAGE_EXEC make macro containing the full path to the coverage tool executable.
1036
1037    Raises RuntimeError if:
1038    - User explicitly requests auto-detection of the coverage tool from command line, and this
1039      routine fails to guess the suitable tool name.
1040    - The routine fails to find the tool, and --with-coverage is true
1041    """
1042    def log_print(msg, *args, **kwargs):
1043      self.logPrint('checkCoverage: '+str(msg), *args, **kwargs)
1044      return
1045
1046    def quoted(string):
1047      return string.join(("'", "'"))
1048
1049    required         = bool(self.argDB['with-coverage'])
1050    arg_opt          = self.argDB['with-coverage-exec']
1051    use_default_path = True
1052    search_path      = ''
1053
1054    log_print('{} to find an executable'.format('REQUIRED' if required else 'NOT required'))
1055    if arg_opt in {'auto', 'default-auto', '1'}:
1056      # detect it based on the C language compiler, hopefully this does not clash!
1057      lang     = self.setCompilers.languages.clanguage
1058      compiler = self.getCompiler(lang=lang)
1059      log_print('User did not explicitly set coverage exec (got {}), trying to auto-detect based on compiler {}'.format(quoted(arg_opt), quoted(compiler)))
1060      if self.setCompilers.isGNU(compiler, self.log):
1061        compiler_version_re = re.compile(r'[gG][cC\+\-]+[0-9]* \(.+\) (\d+)\.(\d+)\.(\d+)')
1062        exec_names          = ['gcov']
1063      elif self.setCompilers.isClang(compiler, self.log):
1064        compiler_version_re = re.compile(r'clang version (\d+)\.(\d+)\.(\d+)')
1065        exec_names          = ['llvm-cov']
1066        if self.setCompilers.isDarwin(self.log):
1067          # macOS masquerades llvm-cov as just 'gcov', so we add this to the list in case
1068          # bare llvm-cov does not work
1069          exec_names.append('gcov')
1070      elif arg_opt == 'default-auto' and not required:
1071        # default-auto implies the user did not set it via command line!
1072        log_print('Could not auto-detect coverage tool for {}, not a gnuish compiler. Bailing since user did not explicitly set exec on the commandline'.format(quoted(compiler)))
1073        return
1074      else:
1075        # implies 'auto' explicitly set by user, or we were required to find
1076        # something. either way we should error
1077        raise RuntimeError('Could not auto-detect coverage tool for {}, please set coverage tool name explicitly'.format(quoted(compiler)))
1078
1079      try:
1080        compiler_version_str = self.compilerFlags.version[lang]
1081      except KeyError:
1082        compiler_version_str = 'Unknown'
1083
1084      log_print('Searching version string {} (for compiler {}) using pattern {}'.format(quoted(compiler_version_str), quoted(compiler), quoted(compiler_version_re.pattern)))
1085      compiler_version = compiler_version_re.search(compiler_version_str)
1086      if compiler_version is not None:
1087        log_print('Found major = {}, minor = {}, patch = {}'.format(compiler_version.group(1), compiler_version.group(2), compiler_version.group(3)))
1088        # form [llvm-cov-14, llvm-cov-14.0, llvm-cov, etc.]
1089        cov_exec_name = exec_names[0]
1090        exec_names    = [
1091          # llvm-cov-14
1092          '{}-{}'.format(cov_exec_name, compiler_version.group(1)),
1093           # llvm-cov-14.0
1094          '{}-{}.{}'.format(cov_exec_name, compiler_version.group(1), compiler_version.group(2))
1095        ] + exec_names
1096    else:
1097      log_print('User explicitly set coverage exec as {}'.format(quoted(arg_opt)))
1098      par_dir = os.path.dirname(arg_opt)
1099      if os.path.exists(par_dir):
1100        # arg_opt is path-like, we should only search the provided directory when we go
1101        # looking for the tool
1102        use_default_path = False
1103        search_path      = par_dir
1104      exec_names = [arg_opt]
1105
1106    make_macro_name = 'PETSC_COVERAGE_EXEC'
1107    log_print('Checking for coverage tool(s):\n{}'.format('\n'.join('- '+t for t in exec_names)))
1108    found_exec = self.getExecutables(
1109      exec_names,
1110      path=search_path, getFullPath=True, useDefaultPath=use_default_path, resultName=make_macro_name
1111    )
1112
1113    if found_exec is None:
1114      # didn't find the coverage tool
1115      if required:
1116        raise RuntimeError('Coverage tool(s) {} could not be found. Please provide explicit path to coverage tool'.format(exec_names))
1117      return
1118
1119    found_exec_name = os.path.basename(found_exec)
1120    if 'llvm-cov' in found_exec_name and 'gcov' not in found_exec_name:
1121      # llvm-cov needs to be called as 'llvm-cov gcov' to work
1122      self.addMakeMacro(make_macro_name, found_exec + ' gcov')
1123    return
1124
1125  def configureStrictPetscErrorCode(self):
1126    """
1127    Enables or disables strict PetscErrorCode checking.
1128
1129    If --with-strict-petscerrorcode = 1:
1130    - defines PETSC_USE_STRICT_PETSCERRORCODE to 1
1131
1132    Else:
1133    - deletes any prior PETSC_USE_STRICT_PETSCERRORCODE definitions (if they exist)
1134    """
1135    define_name = 'USE_STRICT_PETSCERRORCODE'
1136    if self.argDB['with-strict-petscerrorcode']:
1137      self.addDefine(define_name, 1)
1138    else:
1139      # in case it was somehow added previously
1140      self.delDefine(define_name)
1141    return
1142
1143#-----------------------------------------------------------------------------------------------------
1144  def configureCygwinBrokenPipe(self):
1145    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
1146    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
1147    if config.setCompilers.Configure.isCygwin(self.log):
1148      import platform
1149      import re
1150      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
1151      m=r.match(platform.release())
1152      major=int(m.group(1))
1153      minor=int(m.group(2))
1154      subminor=int(m.group(3))
1155      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
1156        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
1157    return
1158
1159#-----------------------------------------------------------------------------------------------------
1160  def configureDefaultArch(self):
1161    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
1162    if self.framework.argDB['with-default-arch']:
1163      fd = open(conffile, 'w')
1164      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
1165      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
1166      fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n')
1167      fd.close()
1168      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
1169    elif os.path.isfile(conffile):
1170      try:
1171        os.unlink(conffile)
1172      except:
1173        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
1174    return
1175
1176#-----------------------------------------------------------------------------------------------------
1177  def configureScript(self):
1178    '''Output a script in the conf directory which will reproduce the configuration'''
1179    import nargs
1180    import sys
1181    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
1182    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
1183    if 'with-clean' in args:
1184      del args['with-clean']
1185    if 'force' in args:
1186      del args['force']
1187    if 'configModules' in args:
1188      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
1189        del args['configModules']
1190    if 'optionsModule' in args:
1191      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
1192        del args['optionsModule']
1193    if not 'PETSC_ARCH' in args:
1194      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
1195    f = open(scriptName, 'w')
1196    f.write('#!'+sys.executable+'\n')
1197    f.write('if __name__ == \'__main__\':\n')
1198    f.write('  import sys\n')
1199    f.write('  import os\n')
1200    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
1201    f.write('  import configure\n')
1202    # pretty print repr(args.values())
1203    f.write('  configure_options = [\n')
1204    for itm in sorted(args.values()):
1205      f.write('    \''+str(itm)+'\',\n')
1206    f.write('  ]\n')
1207    f.write('  configure.petsc_configure(configure_options)\n')
1208    f.close()
1209    try:
1210      os.chmod(scriptName, 0o775)
1211    except OSError as e:
1212      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
1213    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
1214    return
1215
1216  def configureInstall(self):
1217    '''Setup the directories for installation'''
1218    if self.framework.argDB['prefix']:
1219      self.addMakeRule('print_mesg_after_build','',
1220       ['-@echo "========================================="',
1221        '-@echo "Now to install the libraries do:"',
1222        '-@echo "%s${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"' % self.installdir.installSudo,
1223        '-@echo "========================================="'])
1224    else:
1225      self.addMakeRule('print_mesg_after_build','',
1226       ['-@echo "========================================="',
1227        '-@echo "Now to check if the libraries are working do:"',
1228        '-@echo "${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"',
1229        '-@echo "========================================="'])
1230      return
1231
1232  def postProcessPackages(self):
1233    postPackages=[]
1234    for i in self.framework.packages:
1235      if hasattr(i,'postProcess'): postPackages.append(i)
1236    if postPackages:
1237      # ctetgen needs petsc conf files. so attempt to create them early
1238      self.framework.dumpConfFiles()
1239      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
1240      for i in postPackages:
1241        if i.name.upper() in ['PFLOTRAN']:
1242          i.postProcess()
1243          postPackages.remove(i)
1244      for i in postPackages: i.postProcess()
1245      for i in postPackages:
1246        if i.installedpetsc:
1247          self.installed = 1
1248          break
1249    return
1250
1251  def configure(self):
1252    if 'package-prefix-hash' in self.argDB:
1253      # turn off prefix if it was only used to for installing external packages.
1254      self.framework.argDB['prefix'] = ''
1255      self.dir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch))
1256      self.installdir.dir = self.dir
1257      self.installdir.petscDir = self.petscdir.dir
1258      self.petscDir = self.petscdir.dir
1259      self.petscArch = self.arch.arch
1260      self.addMakeMacro('PREFIXDIR',self.dir)
1261      self.confDir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch))
1262
1263    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
1264      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
1265    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
1266      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
1267    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
1268      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')
1269    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)):
1270      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
1271    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
1272    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
1273    self.framework.poisonheader    = os.path.join(self.arch.arch,'include','petscconf_poison.h')
1274    self.framework.pkgheader       = os.path.join(self.arch.arch,'include','petscpkg_version.h')
1275    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
1276    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
1277    if self.libraries.math is None:
1278      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
1279    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
1280      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
1281    self.executeTest(self.configureRTLDDefault)
1282    self.executeTest(self.configurePrefetch)
1283    self.executeTest(self.configureUnused)
1284    self.executeTest(self.configureDeprecated)
1285    self.executeTest(self.configureIsatty)
1286    self.executeTest(self.configureExpect)
1287    self.executeTest(self.configureAlign)
1288    self.executeTest(self.configureFunctionName)
1289    self.executeTest(self.configureIntptrt)
1290    self.executeTest(self.configureSolaris)
1291    self.executeTest(self.configureLinux)
1292    self.executeTest(self.configureDarwin)
1293    self.executeTest(self.configureWin32)
1294    self.executeTest(self.configureCygwinBrokenPipe)
1295    self.executeTest(self.configureDefaultArch)
1296    self.executeTest(self.configureScript)
1297    self.executeTest(self.configureInstall)
1298    self.executeTest(self.configureAtoll)
1299    self.executeTest(self.configureCoverage)
1300    self.executeTest(self.configureCoverageExecutable)
1301    self.executeTest(self.configureStrictPetscErrorCode)
1302
1303    self.Dump()
1304    self.dumpConfigInfo()
1305    self.dumpMachineInfo()
1306    self.delGenFiles()
1307    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
1308    self.framework.storeSubstitutions(self.framework.argDB)
1309    self.framework.argDB['configureCache'] = pickle.dumps(self.framework)
1310    self.framework.argDB.save(force = True)
1311    self.DumpPkgconfig('PETSc.pc')
1312    self.DumpPkgconfig('petsc.pc')
1313    self.DumpModule()
1314    self.postProcessPackages()
1315    self.framework.log.write('================================================================================\n')
1316    self.logClear()
1317    return
1318