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