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