xref: /petsc/config/PETSc/Configure.py (revision e5a36eccef3d6b83a2c625c30d0dfd5adb4001f2)
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    if self.checkCompile("""enum E {oldval __attribute((deprecated)), newval };""", ''):
761      self.addDefine('DEPRECATED_ENUM(why)', '__attribute((deprecated))')
762    else:
763      self.addDefine('DEPRECATED_ENUM(why)', ' ')
764    self.popLanguage()
765
766  def configureAlign(self):
767    '''Check if __attribute(align) is supported'''
768    filename = 'conftestalign'
769    includes = '''
770#include <sys/types.h>
771#if STDC_HEADERS
772#include <stdlib.h>
773#include <stdio.h>
774#include <stddef.h>
775#endif\n'''
776    body     = '''
777struct mystruct {int myint;} __attribute((aligned(16)));
778FILE *f = fopen("'''+filename+'''", "w");
779if (!f) exit(1);
780fprintf(f, "%lu\\n", (unsigned long)sizeof(struct mystruct));
781'''
782    if 'known-has-attribute-aligned' in self.argDB:
783      if self.argDB['known-has-attribute-aligned']:
784        size = 16
785      else:
786        size = -3
787    elif not self.argDB['with-batch']:
788      self.pushLanguage(self.languages.clanguage)
789      try:
790        if self.checkRun(includes, body) and os.path.exists(filename):
791          f    = open(filename)
792          size = int(f.read())
793          f.close()
794          os.remove(filename)
795        else:
796          size = -4
797      except:
798        size = -1
799        self.framework.logPrint('Error checking attribute(aligned)')
800      self.popLanguage()
801    else:
802      self.framework.addBatchInclude(['#include <stdlib.h>', '#include <stdio.h>', '#include <sys/types.h>','struct mystruct {int myint;} __attribute((aligned(16)));'])
803      self.framework.addBatchBody('fprintf(output, "  \'--known-has-attribute-aligned=%d\',\\n", sizeof(struct mystruct)==16);')
804      size = -2
805    if size == 16:
806      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned (size)))')
807      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
808    else:
809      self.framework.logPrint('incorrect alignment. Found alignment:'+ str(size))
810      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
811    return
812
813  def configureExpect(self):
814    '''Sees if the __builtin_expect directive is supported'''
815    self.pushLanguage(self.languages.clanguage)
816    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
817      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
818    self.popLanguage()
819
820  def configureFunctionName(self):
821    '''Sees if the compiler supports __func__ or a variant.'''
822    def getFunctionName(lang):
823      name = '"unknown"'
824      self.pushLanguage(lang)
825      for fname in ['__func__','__FUNCTION__','__extension__ __func__']:
826        code = "if ("+fname+"[0] != 'm') return 1;"
827        if self.checkCompile('',code) and self.checkLink('',code):
828          name = fname
829          break
830      self.popLanguage()
831      return name
832    langs = []
833
834    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
835    if hasattr(self.compilers, 'CXX'):
836      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
837
838  def configureIntptrt(self):
839    '''Determine what to use for uintptr_t'''
840    def staticAssertSizeMatchesVoidStar(inc,typename):
841      # The declaration is an error if either array size is negative.
842      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
843      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
844                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
845    self.pushLanguage(self.languages.clanguage)
846    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
847      self.addDefine('UINTPTR_T', 'uintptr_t')
848    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
849      self.addDefine('UINTPTR_T', 'unsigned long long')
850    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
851      self.addDefine('UINTPTR_T', 'size_t')
852    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
853      self.addDefine('UINTPTR_T', 'unsigned long')
854    elif staticAssertSizeMatchesVoidStar('','unsigned'):
855      self.addDefine('UINTPTR_T', 'unsigned')
856    else:
857      raise RuntimeError('Could not find any unsigned integer type matching void*')
858    self.popLanguage()
859
860  def configureRTLDDefault(self):
861    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
862      self.addDefine('RTLD_DEFAULT','1')
863    return
864
865  def configureSolaris(self):
866    '''Solaris specific stuff'''
867    if os.path.isdir(os.path.join('/usr','ucblib')):
868      try:
869        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
870      except AttributeError:
871        flag = None
872      if flag is None:
873        self.compilers.LIBS += ' -L/usr/ucblib'
874      else:
875        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
876    return
877
878  def configureLinux(self):
879    '''Linux specific stuff'''
880    # TODO: Test for this by mallocing an odd number of floats and checking the address
881    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
882    return
883
884  def configureWin32(self):
885    '''Win32 non-cygwin specific stuff'''
886    kernel32=0
887    if self.libraries.add('Kernel32.lib','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    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
892      self.addDefine('HAVE_WINDOWS_H',1)
893      self.addDefine('HAVE_GETCOMPUTERNAME',1)
894      kernel32=1
895    if kernel32:
896      if self.framework.argDB['with-windows-graphics']:
897        self.addDefine('USE_WINDOWS_GRAPHICS',1)
898      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
899        self.addDefine('HAVE_LOADLIBRARY',1)
900      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
901        self.addDefine('HAVE_GETPROCADDRESS',1)
902      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
903        self.addDefine('HAVE_FREELIBRARY',1)
904      if self.checkLink('#include <Windows.h>','GetLastError()'):
905        self.addDefine('HAVE_GETLASTERROR',1)
906      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
907        self.addDefine('HAVE_SETLASTERROR',1)
908      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
909        self.addDefine('USE_MICROSOFT_TIME',1)
910    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
911      self.addDefine('HAVE_GET_USER_NAME',1)
912    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
913      self.addDefine('HAVE_GET_USER_NAME',1)
914
915    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
916      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
917    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
918      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
919
920    self.types.check('int32_t', 'int')
921    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
922      self.addTypedef('int', 'uid_t')
923      self.addTypedef('int', 'gid_t')
924    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
925      self.framework.addDefine('R_OK', '04')
926      self.framework.addDefine('W_OK', '02')
927      self.framework.addDefine('X_OK', '01')
928    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
929      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
930      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
931    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
932      self.addDefine('HAVE_LARGE_INTEGER_U',1)
933
934    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
935    if self.checkCompile('#include <Windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
936      self.addDefine('HAVE_O_BINARY',1)
937
938    if self.compilers.CC.find('win32fe') >= 0:
939      self.addDefine('HAVE_WINDOWS_COMPILERS',1)
940      self.addDefine('PATH_SEPARATOR','\';\'')
941      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
942      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
943      self.addDefine('CANNOT_START_DEBUGGER',1)
944      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log)
945      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
946      (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log)
947      self.addMakeMacro('wPETSC_DIR',petscdir)
948    else:
949      self.addDefine('PATH_SEPARATOR','\':\'')
950      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
951      self.addDefine('DIR_SEPARATOR','\'/\'')
952      self.addDefine('DIR','"'+self.installdir.petscDir+'"')
953      self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir)
954    self.addDefine('ARCH','"'+self.installdir.petscArch+'"')
955    return
956
957#-----------------------------------------------------------------------------------------------------
958  def configureCygwinBrokenPipe(self):
959    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
960    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
961    if config.setCompilers.Configure.isCygwin(self.log):
962      import platform
963      import re
964      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
965      m=r.match(platform.release())
966      major=int(m.group(1))
967      minor=int(m.group(2))
968      subminor=int(m.group(3))
969      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
970        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
971    return
972
973#-----------------------------------------------------------------------------------------------------
974  def configureDefaultArch(self):
975    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
976    if self.framework.argDB['with-default-arch']:
977      fd = open(conffile, 'w')
978      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
979      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
980      fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n')
981      fd.close()
982      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
983    elif os.path.isfile(conffile):
984      try:
985        os.unlink(conffile)
986      except:
987        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
988    return
989
990#-----------------------------------------------------------------------------------------------------
991  def configureScript(self):
992    '''Output a script in the conf directory which will reproduce the configuration'''
993    import nargs
994    import sys
995    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
996    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
997    if 'with-clean' in args:
998      del args['with-clean']
999    if 'configModules' in args:
1000      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
1001        del args['configModules']
1002    if 'optionsModule' in args:
1003      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
1004        del args['optionsModule']
1005    if not 'PETSC_ARCH' in args:
1006      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
1007    f = open(scriptName, 'w')
1008    f.write('#!'+sys.executable+'\n')
1009    f.write('if __name__ == \'__main__\':\n')
1010    f.write('  import sys\n')
1011    f.write('  import os\n')
1012    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
1013    f.write('  import configure\n')
1014    # pretty print repr(args.values())
1015    f.write('  configure_options = [\n')
1016    for itm in sorted(args.values()):
1017      f.write('    \''+str(itm)+'\',\n')
1018    f.write('  ]\n')
1019    f.write('  configure.petsc_configure(configure_options)\n')
1020    f.close()
1021    try:
1022      os.chmod(scriptName, 0o775)
1023    except OSError as e:
1024      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
1025    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
1026    return
1027
1028  def configureInstall(self):
1029    '''Setup the directories for installation'''
1030    if self.framework.argDB['prefix']:
1031      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
1032                                              '-@echo "'+self.installdir.installSudo+'make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
1033                                              '-@echo "========================================="'])
1034    else:
1035      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
1036                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"',\
1037                                              '-@echo "========================================="'])
1038      return
1039
1040  def configureGCOV(self):
1041    if self.framework.argDB['with-gcov']:
1042      self.addDefine('USE_GCOV','1')
1043    return
1044
1045  def postProcessPackages(self):
1046    postPackages=[]
1047    for i in self.framework.packages:
1048      if hasattr(i,'postProcess'): postPackages.append(i)
1049    if postPackages:
1050      # ctetgen needs petsc conf files. so attempt to create them early
1051      self.framework.dumpConfFiles()
1052      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
1053      for i in postPackages:
1054        if i.name.upper() in ['PFLOTRAN']:
1055          i.postProcess()
1056          postPackages.remove(i)
1057      for i in postPackages: i.postProcess()
1058      for i in postPackages:
1059        if i.installedpetsc:
1060          self.installed = 1
1061          break
1062    return
1063
1064  def configure(self):
1065    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
1066      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
1067    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
1068      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
1069    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
1070      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')
1071    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)):
1072      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
1073    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
1074    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
1075    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
1076    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
1077    if self.libraries.math is None:
1078      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
1079    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
1080      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
1081    self.executeTest(self.configureRTLDDefault)
1082    self.executeTest(self.configurePrefetch)
1083    self.executeTest(self.configureUnused)
1084    self.executeTest(self.configureDeprecated)
1085    self.executeTest(self.configureIsatty)
1086    self.executeTest(self.configureExpect);
1087    self.executeTest(self.configureAlign);
1088    self.executeTest(self.configureFunctionName);
1089    self.executeTest(self.configureIntptrt);
1090    self.executeTest(self.configureSolaris)
1091    self.executeTest(self.configureLinux)
1092    self.executeTest(self.configureWin32)
1093    self.executeTest(self.configureCygwinBrokenPipe)
1094    self.executeTest(self.configureDefaultArch)
1095    self.executeTest(self.configureScript)
1096    self.executeTest(self.configureInstall)
1097    self.executeTest(self.configureGCOV)
1098    self.executeTest(self.configureAtoll)
1099
1100    self.Dump()
1101    self.dumpConfigInfo()
1102    self.dumpMachineInfo()
1103    self.dumpCMakeConfig()
1104    self.dumpCMakeLists()
1105    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
1106    self.framework.storeSubstitutions(self.framework.argDB)
1107    self.framework.argDB['configureCache'] = pickle.dumps(self.framework)
1108    self.framework.argDB.save(force = True)
1109    self.cmakeBoot()
1110    self.DumpPkgconfig()
1111    self.DumpModule()
1112    self.postProcessPackages()
1113    self.framework.log.write('================================================================================\n')
1114    self.logClear()
1115    return
1116