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