xref: /petsc/config/PETSc/Configure.py (revision 7d5fd1e4d9337468ad3f05b65b7facdcd2dfd2a4)
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').replace('"','')+'"')
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        self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
394      if not isinstance(i.lib, list):
395        i.lib = [i.lib]
396      if i.linkedbypetsc: self.packagelibs.extend(i.lib)
397      self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib))
398      if hasattr(i,'include'):
399        if not isinstance(i.include,list):
400          i.include = [i.include]
401        includes.extend(i.include)
402        self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include))
403    if self.framework.argDB['with-single-library']:
404      self.petsclib = '-lpetsc'
405    else:
406      self.petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
407    self.complibs = self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split()
408    self.PETSC_WITH_EXTERNAL_LIB = self.libraries.toStringNoDupes(['-L${PETSC_DIR}/${PETSC_ARCH}/lib', self.petsclib]+self.packagelibs+self.complibs)
409    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(self.packagelibs+self.complibs)
410
411    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.PETSC_EXTERNAL_LIB_BASIC)
412    allincludes = petscincludes + includes
413    allincludes_install = petscincludes_install + includes
414    self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(allincludes)
415    self.PETSC_CC_INCLUDES_INSTALL = self.headers.toStringNoDupes(allincludes_install)
416    self.addMakeMacro('PETSC_CC_INCLUDES',self.PETSC_CC_INCLUDES)
417    self.addMakeMacro('PETSC_CC_INCLUDES_INSTALL', self.PETSC_CC_INCLUDES_INSTALL)
418    if hasattr(self.compilers, 'FC'):
419      def modinc(includes):
420        return includes if self.fortran.fortranIsF90 else []
421      self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(allincludes,modinc(allincludes)))
422      self.addMakeMacro('PETSC_FC_INCLUDES_INSTALL',self.headers.toStringNoDupes(allincludes_install,modinc(allincludes_install)))
423
424    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"')
425
426    if self.framework.argDB['with-single-library']:
427      # overrides the values set in conf/variables
428      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
429      self.addMakeMacro('SHLIBS','libpetsc')
430      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
431      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
432      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
433      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
434      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.PETSC_WITH_EXTERNAL_LIB)
435      self.addDefine('USE_SINGLE_LIBRARY', '1')
436      if self.sharedlibraries.useShared:
437        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
438        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
439        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
440        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
441        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
442        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
443        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
444        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
445        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
446        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
447        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
448      else:
449        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
450        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
451        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
452        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
453        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
454        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
455        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
456        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
457        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
458        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
459        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
460
461    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
462      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
463
464# add a makefile endtry for display
465    if self.framework.argDB['with-display']:
466      self.addMakeMacro('DISPLAY',self.framework.argDB['with-display'])
467
468    # add a makefile entry for configure options
469    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
470    return
471
472  def dumpConfigInfo(self):
473    import time
474    fd = open(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
475    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"').replace('\\ ','\\\\ ')+'";\n')
476    fd.close()
477    return
478
479  def dumpMachineInfo(self):
480    import platform
481    import datetime
482    import time
483    import script
484    def escape(s):
485      return s.replace('"',r'\"').replace(r'\ ',r'\\ ') # novermin
486    fd = open(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
487    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
488    fd.write('\"-----------------------------------------\\n\"\n')
489    buildhost = platform.node()
490    if os.environ.get('SOURCE_DATE_EPOCH'):
491      buildhost = "reproducible"
492    buildtime = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
493    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (buildtime, buildhost))
494    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
495    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir)))
496    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch)))
497    fd.write('\"-----------------------------------------\\n\";\n')
498    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
499    self.setCompilers.pushLanguage(self.languages.clanguage)
500    fd.write('\"Using C compiler: %s %s \\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
501    self.setCompilers.popLanguage()
502    if hasattr(self.compilers, 'FC'):
503      self.setCompilers.pushLanguage('FC')
504      fd.write('\"Using Fortran compiler: %s %s  %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
505      self.setCompilers.popLanguage()
506    fd.write('\"-----------------------------------------\\n\";\n')
507    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
508    fd.write('\"Using include paths: %s\\n\"\n' % (escape(self.PETSC_CC_INCLUDES_INSTALL.replace('${PETSC_DIR}', self.installdir.petscDir))))
509    fd.write('\"-----------------------------------------\\n\";\n')
510    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
511    self.setCompilers.pushLanguage(self.languages.clanguage)
512    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
513    self.setCompilers.popLanguage()
514    if hasattr(self.compilers, 'FC'):
515      self.setCompilers.pushLanguage('FC')
516      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
517      self.setCompilers.popLanguage()
518    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)))
519    fd.write('\"-----------------------------------------\\n\";\n')
520    fd.close()
521    return
522
523  def configurePrefetch(self):
524    '''Sees if there are any prefetch functions supported'''
525    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
526      self.addDefine('Prefetch(a,b,c)', ' ')
527      return
528    self.pushLanguage(self.languages.clanguage)
529    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
530      # The Intel Intrinsics manual [1] specifies the prototype
531      #
532      #   void _mm_prefetch(char const *a, int sel);
533      #
534      # but other vendors seem to insist on using subtly different
535      # prototypes, including void* for the pointer, and an enum for
536      # sel.  These are both reasonable changes, but negatively impact
537      # portability.
538      #
539      # [1] https://software.intel.com/file/6373
540      self.addDefine('HAVE_XMMINTRIN_H', 1)
541      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
542      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
543      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
544      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
545      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
546    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
547      self.addDefine('HAVE_XMMINTRIN_H', 1)
548      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
549      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
550      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
551      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
552      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
553    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
554      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
555      #
556      #   The value of rw is a compile-time constant one or zero; one
557      #   means that the prefetch is preparing for a write to the memory
558      #   address and zero, the default, means that the prefetch is
559      #   preparing for a read. The value locality must be a compile-time
560      #   constant integer between zero and three. A value of zero means
561      #   that the data has no temporal locality, so it need not be left
562      #   in the cache after the access. A value of three means that the
563      #   data has a high degree of temporal locality and should be left
564      #   in all levels of cache possible. Values of one and two mean,
565      #   respectively, a low or moderate degree of temporal locality.
566      #
567      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
568      # hints.  Using macros for these values in necessary since some
569      # compilers require an enum.
570      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
571      self.addDefine('PREFETCH_HINT_NTA', '0')
572      self.addDefine('PREFETCH_HINT_T0',  '3')
573      self.addDefine('PREFETCH_HINT_T1',  '2')
574      self.addDefine('PREFETCH_HINT_T2',  '1')
575    else:
576      self.addDefine('Prefetch(a,b,c)', ' ')
577    self.popLanguage()
578
579  def delGenFiles(self):
580    '''Delete generated files'''
581    delfile = os.path.join(self.arch.arch,'lib','petsc','conf','files')
582    try:
583      os.unlink(delfile)
584    except: pass
585
586  def configureAtoll(self):
587    '''Checks if atoll exists'''
588    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")'):
589       self.addDefine('HAVE_ATOLL', '1')
590
591  def configureUnused(self):
592    '''Sees if __attribute((unused)) is supported'''
593    if self.framework.argDB['with-ios']:
594      self.addDefine('UNUSED', ' ')
595      return
596    self.pushLanguage(self.languages.clanguage)
597    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'):
598      self.addDefine('UNUSED', '__attribute((unused))')
599    else:
600      self.addDefine('UNUSED', ' ')
601    self.popLanguage()
602
603  def configureIsatty(self):
604    '''Check if the Unix C function isatty() works correctly
605       Actually just assumes it does not work correctly on batch systems'''
606    if not self.framework.argDB['with-batch']:
607      self.addDefine('USE_ISATTY',1)
608
609  def configureDeprecated(self):
610    '''Check if __attribute((deprecated)) is supported'''
611    self.pushLanguage(self.languages.clanguage)
612    ## Recent versions of gcc and clang support __attribute((deprecated("string argument"))), which is very useful, but
613    ## Intel has conspired to make a supremely environment-sensitive compiler.  The Intel compiler looks at the gcc
614    ## executable in the environment to determine the language compatibility that it should attempt to emulate.  Some
615    ## important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g.,
616    ## 4.7).  Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc
617    ## found in the default user environment is older and does not support the argument.  If GCC and Intel were cool
618    ## like Clang and supported __has_attribute, we could avoid configure tests entirely, but they don't.  And that is
619    ## why we can't have nice things.
620    #
621    # if self.checkCompile("""__attribute((deprecated("Why you shouldn't use myfunc"))) static int myfunc(void) { return 1;}""", ''):
622    #   self.addDefine('DEPRECATED_FUNCTION(why)', '__attribute((deprecated(why)))')
623    #   self.addDefine('DEPRECATED_TYPEDEF(why)', '__attribute((deprecated(why)))')
624    if self.checkCompile("""__attribute((deprecated)) static int myfunc(void) { return 1;}""", ''):
625      self.addDefine('DEPRECATED_FUNCTION(why)', '__attribute((deprecated))')
626      self.addDefine('DEPRECATED_TYPEDEF(why)', '__attribute((deprecated))')
627    else:
628      self.addDefine('DEPRECATED_FUNCTION(why)', ' ')
629      self.addDefine('DEPRECATED_TYPEDEF(why)', ' ')
630    if self.checkCompile("""enum E {oldval __attribute((deprecated)), newval };""", ''):
631      self.addDefine('DEPRECATED_ENUM(why)', '__attribute((deprecated))')
632    else:
633      self.addDefine('DEPRECATED_ENUM(why)', ' ')
634    # 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
635    # hence the deprecation message is handled as it is
636    if self.checkCompile('#define TEST _Pragma("GCC warning \"Testing _Pragma\"") value'):
637      self.addDefine('DEPRECATED_MACRO(why)', '_Pragma(why)')
638    else:
639      self.addDefine('DEPRECATED_MACRO(why)', ' ')
640    self.popLanguage()
641
642  def configureAlign(self):
643    '''Check if __attribute(aligned) is supported'''
644    code = '''\
645struct mystruct {int myint;} __attribute((aligned(16)));
646char assert_aligned[(sizeof(struct mystruct)==16)*2-1];
647'''
648    self.pushLanguage(self.languages.clanguage)
649    if self.checkCompile(code):
650      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned(size)))')
651      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
652    else:
653      self.framework.logPrint('Incorrect attribute(aligned)')
654      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
655    self.popLanguage()
656    return
657
658  def configureExpect(self):
659    '''Sees if the __builtin_expect directive is supported'''
660    self.pushLanguage(self.languages.clanguage)
661    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
662      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
663    self.popLanguage()
664
665  def configureFunctionName(self):
666    '''Sees if the compiler supports __func__ or a variant.'''
667    def getFunctionName(lang):
668      name = '"unknown"'
669      self.pushLanguage(lang)
670      for fname in ['__func__','__FUNCTION__','__extension__ __func__']:
671        code = "if ("+fname+"[0] != 'm') return 1;"
672        if self.checkCompile('',code) and self.checkLink('',code):
673          name = fname
674          break
675      self.popLanguage()
676      return name
677    langs = []
678
679    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
680    if hasattr(self.compilers, 'CXX'):
681      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
682
683  def configureIntptrt(self):
684    '''Determine what to use for uintptr_t'''
685    def staticAssertSizeMatchesVoidStar(inc,typename):
686      # The declaration is an error if either array size is negative.
687      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
688      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
689                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
690    self.pushLanguage(self.languages.clanguage)
691    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
692      self.addDefine('UINTPTR_T', 'uintptr_t')
693    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
694      self.addDefine('UINTPTR_T', 'unsigned long long')
695    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
696      self.addDefine('UINTPTR_T', 'size_t')
697    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
698      self.addDefine('UINTPTR_T', 'unsigned long')
699    elif staticAssertSizeMatchesVoidStar('','unsigned'):
700      self.addDefine('UINTPTR_T', 'unsigned')
701    else:
702      raise RuntimeError('Could not find any unsigned integer type matching void*')
703    self.popLanguage()
704
705  def configureRTLDDefault(self):
706    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
707      self.addDefine('RTLD_DEFAULT','1')
708    return
709
710  def configureSolaris(self):
711    '''Solaris specific stuff'''
712    if os.path.isdir(os.path.join('/usr','ucblib')):
713      try:
714        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
715      except AttributeError:
716        flag = None
717      if flag is None:
718        self.compilers.LIBS += ' -L/usr/ucblib'
719      else:
720        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
721    return
722
723  def configureLinux(self):
724    '''Linux specific stuff'''
725    # TODO: Test for this by mallocing an odd number of floats and checking the address
726    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
727    return
728
729  def configureWin32(self):
730    '''Win32 non-cygwin specific stuff'''
731    kernel32=0
732    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'):
733      self.addDefine('HAVE_WINDOWS_H',1)
734      self.addDefine('HAVE_GETCOMPUTERNAME',1)
735      kernel32=1
736    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'):
737      self.addDefine('HAVE_WINDOWS_H',1)
738      self.addDefine('HAVE_GETCOMPUTERNAME',1)
739      kernel32=1
740    if kernel32:
741      if self.framework.argDB['with-windows-graphics']:
742        self.addDefine('USE_WINDOWS_GRAPHICS',1)
743      if self.checkLink('#include <windows.h>','LoadLibrary(0)'):
744        self.addDefine('HAVE_LOADLIBRARY',1)
745      if self.checkLink('#include <windows.h>','GetProcAddress(0,0)'):
746        self.addDefine('HAVE_GETPROCADDRESS',1)
747      if self.checkLink('#include <windows.h>','FreeLibrary(0)'):
748        self.addDefine('HAVE_FREELIBRARY',1)
749      if self.checkLink('#include <windows.h>','GetLastError()'):
750        self.addDefine('HAVE_GETLASTERROR',1)
751      if self.checkLink('#include <windows.h>','SetLastError(0)'):
752        self.addDefine('HAVE_SETLASTERROR',1)
753      if self.checkLink('#include <windows.h>\n','QueryPerformanceCounter(0);\n'):
754        self.addDefine('USE_MICROSOFT_TIME',1)
755    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'):
756      self.addDefine('HAVE_GET_USER_NAME',1)
757    elif self.libraries.add('advapi32','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'):
758      self.addDefine('HAVE_GET_USER_NAME',1)
759
760    if not self.libraries.add('User32.lib','GetDC',prototype='#include <windows.h>',call='GetDC(0);'):
761      self.libraries.add('user32','GetDC',prototype='#include <windows.h>',call='GetDC(0);')
762    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);'):
763      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);')
764
765    self.types.check('int32_t', 'int')
766    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
767      self.addTypedef('int', 'uid_t')
768      self.addTypedef('int', 'gid_t')
769    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
770      self.framework.addDefine('R_OK', '04')
771      self.framework.addDefine('W_OK', '02')
772      self.framework.addDefine('X_OK', '01')
773    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
774      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
775      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
776    if self.checkCompile('#include <windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
777      self.addDefine('HAVE_LARGE_INTEGER_U',1)
778
779    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
780    if self.checkCompile('#include <windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
781      self.addDefine('HAVE_O_BINARY',1)
782
783    if self.compilers.CC.find('win32fe') >= 0:
784      self.addDefine('HAVE_WINDOWS_COMPILERS',1)
785      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
786      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
787      self.addDefine('CANNOT_START_DEBUGGER',1)
788      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log)
789      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
790      (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log)
791      self.addMakeMacro('wPETSC_DIR',petscdir)
792      if self.dataFilesPath.datafilespath:
793        (datafilespath,error,status) = self.executeShellCommand('cygpath -m '+self.dataFilesPath.datafilespath, log = self.log)
794        self.addMakeMacro('DATAFILESPATH',datafilespath)
795
796    else:
797      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
798      self.addDefine('DIR_SEPARATOR','\'/\'')
799      self.addDefine('DIR','"'+self.installdir.petscDir+'"')
800      self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir)
801      if self.dataFilesPath.datafilespath:
802        self.addMakeMacro('DATAFILESPATH',self.dataFilesPath.datafilespath)
803    self.addDefine('ARCH','"'+self.installdir.petscArch+'"')
804    return
805
806#-----------------------------------------------------------------------------------------------------
807  def configureCygwinBrokenPipe(self):
808    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
809    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
810    if config.setCompilers.Configure.isCygwin(self.log):
811      import platform
812      import re
813      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
814      m=r.match(platform.release())
815      major=int(m.group(1))
816      minor=int(m.group(2))
817      subminor=int(m.group(3))
818      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
819        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
820    return
821
822#-----------------------------------------------------------------------------------------------------
823  def configureDefaultArch(self):
824    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
825    if self.framework.argDB['with-default-arch']:
826      fd = open(conffile, 'w')
827      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
828      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
829      fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n')
830      fd.close()
831      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
832    elif os.path.isfile(conffile):
833      try:
834        os.unlink(conffile)
835      except:
836        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
837    return
838
839#-----------------------------------------------------------------------------------------------------
840  def configureScript(self):
841    '''Output a script in the conf directory which will reproduce the configuration'''
842    import nargs
843    import sys
844    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
845    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
846    if 'with-clean' in args:
847      del args['with-clean']
848    if 'force' in args:
849      del args['force']
850    if 'configModules' in args:
851      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
852        del args['configModules']
853    if 'optionsModule' in args:
854      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
855        del args['optionsModule']
856    if not 'PETSC_ARCH' in args:
857      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
858    f = open(scriptName, 'w')
859    f.write('#!'+sys.executable+'\n')
860    f.write('if __name__ == \'__main__\':\n')
861    f.write('  import sys\n')
862    f.write('  import os\n')
863    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
864    f.write('  import configure\n')
865    # pretty print repr(args.values())
866    f.write('  configure_options = [\n')
867    for itm in sorted(args.values()):
868      f.write('    \''+str(itm)+'\',\n')
869    f.write('  ]\n')
870    f.write('  configure.petsc_configure(configure_options)\n')
871    f.close()
872    try:
873      os.chmod(scriptName, 0o775)
874    except OSError as e:
875      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
876    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
877    return
878
879  def configureInstall(self):
880    '''Setup the directories for installation'''
881    if self.framework.argDB['prefix']:
882      self.addMakeRule('print_mesg_after_build','',
883       ['-@echo "========================================="',
884        '-@echo "Now to install the libraries do:"',
885        '-@echo "%s${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"' % self.installdir.installSudo,
886        '-@echo "========================================="'])
887    else:
888      self.addMakeRule('print_mesg_after_build','',
889       ['-@echo "========================================="',
890        '-@echo "Now to check if the libraries are working do:"',
891        '-@echo "${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"',
892        '-@echo "========================================="'])
893      return
894
895  def configureGCOV(self):
896    if self.framework.argDB['with-gcov']:
897      self.addDefine('USE_GCOV','1')
898    return
899
900  def postProcessPackages(self):
901    postPackages=[]
902    for i in self.framework.packages:
903      if hasattr(i,'postProcess'): postPackages.append(i)
904    if postPackages:
905      # ctetgen needs petsc conf files. so attempt to create them early
906      self.framework.dumpConfFiles()
907      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
908      for i in postPackages:
909        if i.name.upper() in ['PFLOTRAN']:
910          i.postProcess()
911          postPackages.remove(i)
912      for i in postPackages: i.postProcess()
913      for i in postPackages:
914        if i.installedpetsc:
915          self.installed = 1
916          break
917    return
918
919  def configure(self):
920    if 'package-prefix-hash' in self.argDB:
921      # turn off prefix if it was only used to for installing external packages.
922      self.framework.argDB['prefix'] = ''
923      self.dir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch))
924      self.installdir.dir = self.dir
925      self.installdir.petscDir = self.petscdir.dir
926      self.petscDir = self.petscdir.dir
927      self.petscArch = self.arch.arch
928      self.addMakeMacro('PREFIXDIR',self.dir)
929      self.confDir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch))
930
931    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
932      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
933    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
934      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
935    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
936      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')
937    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)):
938      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
939    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
940    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
941    self.framework.poisonheader    = os.path.join(self.arch.arch,'include','petscconf_poison.h')
942    self.framework.pkgheader       = os.path.join(self.arch.arch,'include','petscpkg_version.h')
943    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
944    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
945    if self.libraries.math is None:
946      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
947    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
948      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
949    self.executeTest(self.configureRTLDDefault)
950    self.executeTest(self.configurePrefetch)
951    self.executeTest(self.configureUnused)
952    self.executeTest(self.configureDeprecated)
953    self.executeTest(self.configureIsatty)
954    self.executeTest(self.configureExpect)
955    self.executeTest(self.configureAlign)
956    self.executeTest(self.configureFunctionName)
957    self.executeTest(self.configureIntptrt)
958    self.executeTest(self.configureSolaris)
959    self.executeTest(self.configureLinux)
960    self.executeTest(self.configureWin32)
961    self.executeTest(self.configureCygwinBrokenPipe)
962    self.executeTest(self.configureDefaultArch)
963    self.executeTest(self.configureScript)
964    self.executeTest(self.configureInstall)
965    self.executeTest(self.configureGCOV)
966    self.executeTest(self.configureAtoll)
967
968    self.Dump()
969    self.dumpConfigInfo()
970    self.dumpMachineInfo()
971    self.delGenFiles()
972    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
973    self.framework.storeSubstitutions(self.framework.argDB)
974    self.framework.argDB['configureCache'] = pickle.dumps(self.framework)
975    self.framework.argDB.save(force = True)
976    self.DumpPkgconfig('PETSc.pc')
977    self.DumpPkgconfig('petsc.pc')
978    self.DumpModule()
979    self.postProcessPackages()
980    self.framework.log.write('================================================================================\n')
981    self.logClear()
982    return
983