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