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