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