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