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