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