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