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