xref: /petsc/config/PETSc/Configure.py (revision 00a402e09c6d62f19dbf72eef0e53394ab690d5c)
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','mathimf','inttypes','immintrin','zmmintrin'])
148    functions = ['access', '_access', 'clock', 'drand48', 'getcwd', '_getcwd', 'getdomainname', 'gethostname',
149                 'gettimeofday', 'getwd', 'memalign', 'memmove', '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    if self.framework.argDB['prefix']:
167      fd.write('prefix='+self.installdir.dir+'\n')
168      fd.write('exec_prefix=${prefix}\n')
169      fd.write('includedir=${prefix}/include\n')
170    else:
171      fd.write('prefix='+self.petscdir.dir+'\n')
172      fd.write('exec_prefix=${prefix}\n')
173      fd.write('includedir=${prefix}/include\n')
174    fd.write('libdir='+os.path.join(self.installdir.dir,'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: ' + self.setCompilers.CPPFLAGS + ' ' + self.PETSC_CC_INCLUDES + '\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    includes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')]
386    self.packagelibs = []
387    for i in self.framework.packages:
388      if i.useddirectly:
389        self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
390      if not isinstance(i.lib, list):
391        i.lib = [i.lib]
392      if i.linkedbypetsc: self.packagelibs.extend(i.lib)
393      self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib))
394      if hasattr(i,'include'):
395        if not isinstance(i.include,list):
396          i.include = [i.include]
397        includes.extend(i.include)
398        self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include))
399    if self.framework.argDB['with-single-library']:
400      self.petsclib = '-lpetsc'
401    else:
402      self.petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
403    self.complibs = self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split()
404    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)
405    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(self.packagelibs+self.complibs)
406    if self.framework.argDB['prefix'] and self.setCompilers.CSharedLinkerFlag not in ['-L']:
407      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'))
408
409    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.PETSC_EXTERNAL_LIB_BASIC)
410    self.allincludes = self.headers.toStringNoDupes(includes)
411    self.addMakeMacro('PETSC_CC_INCLUDES',self.allincludes)
412    self.PETSC_CC_INCLUDES = self.allincludes
413    if hasattr(self.compilers, 'FC'):
414      if self.compilers.fortranIsF90:
415        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes,includes))
416      else:
417        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes))
418
419    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"')
420
421    if self.framework.argDB['with-single-library']:
422      # overrides the values set in conf/variables
423      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
424      self.addMakeMacro('SHLIBS','libpetsc')
425      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
426      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
427      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
428      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
429      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.PETSC_WITH_EXTERNAL_LIB)
430      self.addDefine('USE_SINGLE_LIBRARY', '1')
431      if self.sharedlibraries.useShared:
432        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
433        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
434        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
435        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
436        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
437        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
438        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
439        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
440        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
441        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
442        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
443      else:
444        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
445        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
446        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
447        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
448        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
449        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
450        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
451        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
452        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
453        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
454        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
455
456    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
457      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
458
459# add a makefile endtry for display
460    if self.framework.argDB['with-display']:
461      self.addMakeMacro('DISPLAY',self.framework.argDB['with-display'])
462
463    # add a makefile entry for configure options
464    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
465    return
466
467  def dumpConfigInfo(self):
468    import time
469    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
470    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
471    fd.close()
472    return
473
474  def dumpMachineInfo(self):
475    import platform
476    import datetime
477    import time
478    import script
479    def escape(s):
480      return s.replace('"',r'\"').replace(r'\ ',r'\\ ')
481    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
482    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
483    fd.write('\"-----------------------------------------\\n\"\n')
484    buildhost = platform.node()
485    if os.environ.get('SOURCE_DATE_EPOCH'):
486      buildhost = "reproducible"
487    buildtime = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
488    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (buildtime, buildhost))
489    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
490    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir)))
491    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch)))
492    fd.write('\"-----------------------------------------\\n\";\n')
493    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
494    self.setCompilers.pushLanguage(self.languages.clanguage)
495    fd.write('\"Using C compiler: %s %s \\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
496    self.setCompilers.popLanguage()
497    if hasattr(self.compilers, 'FC'):
498      self.setCompilers.pushLanguage('FC')
499      fd.write('\"Using Fortran compiler: %s %s  %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
500      self.setCompilers.popLanguage()
501    fd.write('\"-----------------------------------------\\n\";\n')
502    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
503    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)))
504    fd.write('\"-----------------------------------------\\n\";\n')
505    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
506    self.setCompilers.pushLanguage(self.languages.clanguage)
507    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
508    self.setCompilers.popLanguage()
509    if hasattr(self.compilers, 'FC'):
510      self.setCompilers.pushLanguage('FC')
511      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
512      self.setCompilers.popLanguage()
513    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)))
514    fd.write('\"-----------------------------------------\\n\";\n')
515    fd.close()
516    return
517
518  def dumpCMakeConfig(self):
519    '''
520    Writes configuration-specific values to ${PETSC_ARCH}/lib/petsc/conf/PETScBuildInternal.cmake.
521    This file is private to PETSc and should not be included by third parties
522    (a suitable file can be produced later by CMake, but this is not it).
523    '''
524    def cmakeset(fd,key,val=True):
525      if val == True: val = 'YES'
526      if val == False: val = 'NO'
527      fd.write('set (' + key + ' ' + val + ')\n')
528    def ensurelist(a):
529      if isinstance(a,list):
530        return a
531      else:
532        return [a]
533    def libpath(lib):
534      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
535      if not isinstance(lib,str): return ''
536      if lib.startswith('-L'): return lib[2:]
537      if lib.startswith('-R'): return lib[2:]
538      if lib.startswith('-Wl,-rpath,'):
539        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
540        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
541        # corresponding library.
542        return lib[len('-Wl,-rpath,'):]
543      if lib.startswith('-'): return ''
544      return os.path.dirname(lib)
545    def cleanlib(lib):
546      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
547      if not isinstance(lib,str): return ''
548      if lib.startswith('-l'):  return lib[2:]
549      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
550      lib = os.path.splitext(os.path.basename(lib))[0]
551      if lib.startswith('lib'): return lib[3:]
552      return lib
553    def nub(lst):
554      'Return a list containing the first occurrence of each unique element'
555      unique = []
556      for elem in lst:
557        if elem not in unique and elem != '':
558          unique.append(elem)
559      return unique
560    try: reversed # reversed was added in Python-2.4
561    except NameError:
562      def reversed(lst): return lst[::-1]
563    def nublast(lst):
564      'Return a list containing the last occurrence of each unique entry in a list'
565      return reversed(nub(reversed(lst)))
566    def cmakeexpand(varname):
567      return r'"${' + varname + r'}"'
568    def uniqextend(lst,new):
569      for x in ensurelist(new):
570        if x not in lst:
571          lst.append(x)
572    def notstandardinclude(path):
573      return path not in '/usr/include'.split() # /usr/local/include is not automatically included on FreeBSD
574    def writeMacroDefinitions(fd):
575      if self.mpi.usingMPIUni:
576        cmakeset(fd,'PETSC_HAVE_MPIUNI')
577      for pkg in self.framework.packages:
578        if pkg.useddirectly:
579          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE.replace('-','_'))
580        for pair in pkg.defines.items():
581          if pair[0].startswith('HAVE_') and pair[1]:
582            cmakeset(fd, self.framework.getFullDefineName(pkg, pair[0]), pair[1])
583      for name,val in self.functions.defines.items():
584        cmakeset(fd,'PETSC_'+name,val)
585      for dct in [self.defines, self.libraryoptions.defines]:
586        for k,v in dct.items():
587          if k.startswith('USE_'):
588            cmakeset(fd,'PETSC_' + k, v)
589      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
590      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
591      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
592      if hasattr(self.compilers, 'FC'):
593        cmakeset(fd,'PETSC_HAVE_FORTRAN')
594        if self.compilers.fortranIsF90:
595          cmakeset(fd,'PETSC_USING_F90')
596        if self.compilers.fortranIsF2003:
597          cmakeset(fd,'PETSC_USING_F2003')
598      if hasattr(self.compilers, 'CXX'):
599        cmakeset(fd,'PETSC_HAVE_CXX')
600      if self.sharedlibraries.useShared:
601        cmakeset(fd,'BUILD_SHARED_LIBS')
602    def writeBuildFlags(fd):
603      def extendby(lib):
604        libs = ensurelist(lib)
605        lib_paths.extend(map(libpath,libs))
606        lib_libs.extend(map(cleanlib,libs))
607      lib_paths = []
608      lib_libs  = []
609      includes  = []
610      libvars   = []
611      for pkg in self.framework.packages:
612        if pkg.linkedbypetsc:
613          extendby(pkg.lib)
614          uniqextend(includes,pkg.include)
615      extendby(self.libraries.math)
616      extendby(self.libraries.rt)
617      extendby(self.compilers.flibs)
618      extendby(self.compilers.cxxlibs)
619      extendby(self.compilers.LIBS.split())
620      for libname in nublast(lib_libs):
621        libvar = 'PETSC_' + libname.upper() + '_LIB'
622        addpath = ''
623        for lpath in nublast(lib_paths):
624          addpath += '"' + str(lpath) + '" '
625        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
626        libvars.append(libvar)
627      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
628      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
629      includes = filter(notstandardinclude,includes)
630      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',includes)) + ')\n')
631    fd = open(os.path.join(self.arch.arch,'lib','petsc','conf','PETScBuildInternal.cmake'), 'w')
632    writeMacroDefinitions(fd)
633    writeBuildFlags(fd)
634    fd.close()
635    return
636
637  def dumpCMakeLists(self):
638    import sys
639    if sys.version_info >= (2,4):
640      import cmakegen
641      try:
642        cmakegen.main(self.petscdir.dir, log=self.framework.log)
643      except (OSError) as e:
644        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
645    else:
646      self.framework.logPrint('Skipping cmakegen due to old python version: ' +str(sys.version_info) )
647
648  def cmakeBoot(self):
649    import sys
650    self.cmakeboot_success = False
651    if sys.version_info >= (2,4) and hasattr(self.cmake,'cmake'):
652      oldRead = self.argDB.readonly
653      self.argDB.readonly = True
654      try:
655        import cmakeboot
656        self.cmakeboot_success = cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
657      except (OSError) as e:
658        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
659      except (ImportError, KeyError) as e:
660        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
661      self.argDB.readonly = oldRead
662      if self.cmakeboot_success:
663        if hasattr(self.compilers, 'FC') and self.compilers.fortranIsF90 and not self.setCompilers.fortranModuleOutputFlag:
664          self.framework.logPrint('CMake configured successfully, but could not be used by default because of missing fortranModuleOutputFlag\n')
665        else:
666          self.framework.logPrint('CMake configured successfully, using as default build\n')
667          self.addMakeMacro('PETSC_BUILD_USING_CMAKE',1)
668      else:
669        self.framework.logPrint('CMake configuration was unsuccessful\n')
670    else:
671      self.framework.logPrint('Skipping cmakeboot due to old python version: ' +str(sys.version_info) )
672    return
673
674  def configurePrefetch(self):
675    '''Sees if there are any prefetch functions supported'''
676    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
677      self.addDefine('Prefetch(a,b,c)', ' ')
678      return
679    self.pushLanguage(self.languages.clanguage)
680    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
681      # The Intel Intrinsics manual [1] specifies the prototype
682      #
683      #   void _mm_prefetch(char const *a, int sel);
684      #
685      # but other vendors seem to insist on using subtly different
686      # prototypes, including void* for the pointer, and an enum for
687      # sel.  These are both reasonable changes, but negatively impact
688      # portability.
689      #
690      # [1] http://software.intel.com/file/6373
691      self.addDefine('HAVE_XMMINTRIN_H', 1)
692      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
693      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
694      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
695      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
696      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
697    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
698      self.addDefine('HAVE_XMMINTRIN_H', 1)
699      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
700      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
701      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
702      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
703      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
704    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
705      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
706      #
707      #   The value of rw is a compile-time constant one or zero; one
708      #   means that the prefetch is preparing for a write to the memory
709      #   address and zero, the default, means that the prefetch is
710      #   preparing for a read. The value locality must be a compile-time
711      #   constant integer between zero and three. A value of zero means
712      #   that the data has no temporal locality, so it need not be left
713      #   in the cache after the access. A value of three means that the
714      #   data has a high degree of temporal locality and should be left
715      #   in all levels of cache possible. Values of one and two mean,
716      #   respectively, a low or moderate degree of temporal locality.
717      #
718      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
719      # hints.  Using macros for these values in necessary since some
720      # compilers require an enum.
721      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
722      self.addDefine('PREFETCH_HINT_NTA', '0')
723      self.addDefine('PREFETCH_HINT_T0',  '3')
724      self.addDefine('PREFETCH_HINT_T1',  '2')
725      self.addDefine('PREFETCH_HINT_T2',  '1')
726    else:
727      self.addDefine('Prefetch(a,b,c)', ' ')
728    self.popLanguage()
729
730  def configureAtoll(self):
731    '''Checks if atoll exists'''
732    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")'):
733       self.addDefine('HAVE_ATOLL', '1')
734
735  def configureUnused(self):
736    '''Sees if __attribute((unused)) is supported'''
737    if self.framework.argDB['with-ios']:
738      self.addDefine('UNUSED', ' ')
739      return
740    self.pushLanguage(self.languages.clanguage)
741    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'):
742      self.addDefine('UNUSED', '__attribute((unused))')
743    else:
744      self.addDefine('UNUSED', ' ')
745    self.popLanguage()
746
747  def configureIsatty(self):
748    '''Check if the Unix C function isatty() works correctly
749       Actually just assumes it does not work correctly on batch systems'''
750    if not self.framework.argDB['with-batch']:
751      self.addDefine('USE_ISATTY',1)
752
753  def configureDeprecated(self):
754    '''Check if __attribute((deprecated)) is supported'''
755    self.pushLanguage(self.languages.clanguage)
756    ## Recent versions of gcc and clang support __attribute((deprecated("string argument"))), which is very useful, but
757    ## Intel has conspired to make a supremely environment-sensitive compiler.  The Intel compiler looks at the gcc
758    ## executable in the environment to determine the language compatibility that it should attempt to emulate.  Some
759    ## important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g.,
760    ## 4.7).  Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc
761    ## found in the default user environment is older and does not support the argument.  If GCC and Intel were cool
762    ## like Clang and supported __has_attribute, we could avoid configure tests entirely, but they don't.  And that is
763    ## why we can't have nice things.
764    #
765    # if self.checkCompile("""__attribute((deprecated("Why you shouldn't use myfunc"))) static int myfunc(void) { return 1;}""", ''):
766    #   self.addDefine('DEPRECATED(why)', '__attribute((deprecated(why)))')
767    if self.checkCompile("""__attribute((deprecated)) static int myfunc(void) { return 1;}""", ''):
768      self.addDefine('DEPRECATED(why)', '__attribute((deprecated))')
769    else:
770      self.addDefine('DEPRECATED(why)', ' ')
771    self.popLanguage()
772
773  def configureAlign(self):
774    '''Check if __attribute(align) is supported'''
775    filename = 'conftestalign'
776    includes = '''
777#include <sys/types.h>
778#if STDC_HEADERS
779#include <stdlib.h>
780#include <stdio.h>
781#include <stddef.h>
782#endif\n'''
783    body     = '''
784struct mystruct {int myint;} __attribute((aligned(16)));
785FILE *f = fopen("'''+filename+'''", "w");
786if (!f) exit(1);
787fprintf(f, "%lu\\n", (unsigned long)sizeof(struct mystruct));
788'''
789    if 'known-has-attribute-aligned' in self.argDB:
790      if self.argDB['known-has-attribute-aligned']:
791        size = 16
792      else:
793        size = -3
794    elif not self.argDB['with-batch']:
795      self.pushLanguage(self.languages.clanguage)
796      try:
797        if self.checkRun(includes, body) and os.path.exists(filename):
798          f    = file(filename)
799          size = int(f.read())
800          f.close()
801          os.remove(filename)
802        else:
803          size = -4
804      except:
805        size = -1
806        self.framework.logPrint('Error checking attribute(aligned)')
807      self.popLanguage()
808    else:
809      self.framework.addBatchInclude(['#include <stdlib.h>', '#include <stdio.h>', '#include <sys/types.h>','struct mystruct {int myint;} __attribute((aligned(16)));'])
810      self.framework.addBatchBody('fprintf(output, "  \'--known-has-attribute-aligned=%d\',\\n", sizeof(struct mystruct)==16);')
811      size = -2
812    if size == 16:
813      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned (size)))')
814      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
815    else:
816      self.framework.logPrint('incorrect alignment. Found alignment:'+ str(size))
817      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
818    return
819
820  def configureExpect(self):
821    '''Sees if the __builtin_expect directive is supported'''
822    self.pushLanguage(self.languages.clanguage)
823    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
824      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
825    self.popLanguage()
826
827  def configureFunctionName(self):
828    '''Sees if the compiler supports __func__ or a variant.'''
829    def getFunctionName(lang):
830      name = '"unknown"'
831      self.pushLanguage(lang)
832      for fname in ['__func__','__FUNCTION__']:
833        code = "if ("+fname+"[0] != 'm') return 1;"
834        if self.checkCompile('',code) and self.checkLink('',code):
835          name = fname
836          break
837      self.popLanguage()
838      return name
839    langs = []
840
841    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
842    if hasattr(self.compilers, 'CXX'):
843      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
844
845  def configureIntptrt(self):
846    '''Determine what to use for uintptr_t'''
847    def staticAssertSizeMatchesVoidStar(inc,typename):
848      # The declaration is an error if either array size is negative.
849      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
850      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
851                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
852    self.pushLanguage(self.languages.clanguage)
853    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
854      self.addDefine('UINTPTR_T', 'uintptr_t')
855    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
856      self.addDefine('UINTPTR_T', 'unsigned long long')
857    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
858      self.addDefine('UINTPTR_T', 'size_t')
859    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
860      self.addDefine('UINTPTR_T', 'unsigned long')
861    elif staticAssertSizeMatchesVoidStar('','unsigned'):
862      self.addDefine('UINTPTR_T', 'unsigned')
863    else:
864      raise RuntimeError('Could not find any unsigned integer type matching void*')
865    self.popLanguage()
866
867  def configureRTLDDefault(self):
868    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
869      self.addDefine('RTLD_DEFAULT','1')
870    return
871
872  def configureSolaris(self):
873    '''Solaris specific stuff'''
874    if os.path.isdir(os.path.join('/usr','ucblib')):
875      try:
876        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
877      except AttributeError:
878        flag = None
879      if flag is None:
880        self.compilers.LIBS += ' -L/usr/ucblib'
881      else:
882        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
883    return
884
885  def configureLinux(self):
886    '''Linux specific stuff'''
887    # TODO: Test for this by mallocing an odd number of floats and checking the address
888    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
889    return
890
891  def configureWin32(self):
892    '''Win32 non-cygwin specific stuff'''
893    kernel32=0
894    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
895      self.addDefine('HAVE_WINDOWS_H',1)
896      self.addDefine('HAVE_GETCOMPUTERNAME',1)
897      kernel32=1
898    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
899      self.addDefine('HAVE_WINDOWS_H',1)
900      self.addDefine('HAVE_GETCOMPUTERNAME',1)
901      kernel32=1
902    if kernel32:
903      if self.framework.argDB['with-windows-graphics']:
904        self.addDefine('USE_WINDOWS_GRAPHICS',1)
905      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
906        self.addDefine('HAVE_LOADLIBRARY',1)
907      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
908        self.addDefine('HAVE_GETPROCADDRESS',1)
909      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
910        self.addDefine('HAVE_FREELIBRARY',1)
911      if self.checkLink('#include <Windows.h>','GetLastError()'):
912        self.addDefine('HAVE_GETLASTERROR',1)
913      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
914        self.addDefine('HAVE_SETLASTERROR',1)
915      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
916        self.addDefine('USE_MICROSOFT_TIME',1)
917    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
918      self.addDefine('HAVE_GET_USER_NAME',1)
919    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
920      self.addDefine('HAVE_GET_USER_NAME',1)
921
922    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
923      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
924    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
925      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
926
927    self.types.check('int32_t', 'int')
928    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
929      self.addTypedef('int', 'uid_t')
930      self.addTypedef('int', 'gid_t')
931    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
932      self.framework.addDefine('R_OK', '04')
933      self.framework.addDefine('W_OK', '02')
934      self.framework.addDefine('X_OK', '01')
935    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
936      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
937      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
938    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
939      self.addDefine('HAVE_LARGE_INTEGER_U',1)
940
941    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
942    if self.checkCompile('#include <Windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
943      self.addDefine('HAVE_O_BINARY',1)
944
945    if self.compilers.CC.find('win32fe') >= 0:
946      self.addDefine('HAVE_WINDOWS_COMPILERS',1)
947      self.addDefine('PATH_SEPARATOR','\';\'')
948      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
949      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
950      self.addDefine('CANNOT_START_DEBUGGER',1)
951      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log)
952      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
953      (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log)
954      self.addMakeMacro('wPETSC_DIR',petscdir)
955    else:
956      self.addDefine('PATH_SEPARATOR','\':\'')
957      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
958      self.addDefine('DIR_SEPARATOR','\'/\'')
959      self.addDefine('DIR','"'+self.installdir.petscDir+'"')
960      self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir)
961    self.addDefine('ARCH','"'+self.installdir.petscArch+'"')
962    return
963
964#-----------------------------------------------------------------------------------------------------
965  def configureCygwinBrokenPipe(self):
966    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
967    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
968    if config.setCompilers.Configure.isCygwin(self.log):
969      import platform
970      import re
971      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
972      m=r.match(platform.release())
973      major=int(m.group(1))
974      minor=int(m.group(2))
975      subminor=int(m.group(3))
976      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
977        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
978    return
979
980#-----------------------------------------------------------------------------------------------------
981  def configureDefaultArch(self):
982    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
983    if self.framework.argDB['with-default-arch']:
984      fd = file(conffile, 'w')
985      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
986      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
987      fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n')
988      fd.close()
989      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
990    elif os.path.isfile(conffile):
991      try:
992        os.unlink(conffile)
993      except:
994        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
995    return
996
997#-----------------------------------------------------------------------------------------------------
998  def configureScript(self):
999    '''Output a script in the conf directory which will reproduce the configuration'''
1000    import nargs
1001    import sys
1002    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
1003    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
1004    if 'with-clean' in args:
1005      del args['with-clean']
1006    if 'configModules' in args:
1007      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
1008        del args['configModules']
1009    if 'optionsModule' in args:
1010      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
1011        del args['optionsModule']
1012    if not 'PETSC_ARCH' in args:
1013      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
1014    f = file(scriptName, 'w')
1015    f.write('#!'+sys.executable+'\n')
1016    f.write('if __name__ == \'__main__\':\n')
1017    f.write('  import sys\n')
1018    f.write('  import os\n')
1019    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
1020    f.write('  import configure\n')
1021    # pretty print repr(args.values())
1022    f.write('  configure_options = [\n')
1023    for itm in sorted(args.values()):
1024      f.write('    \''+str(itm)+'\',\n')
1025    f.write('  ]\n')
1026    f.write('  configure.petsc_configure(configure_options)\n')
1027    f.close()
1028    try:
1029      os.chmod(scriptName, 0o775)
1030    except OSError as e:
1031      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
1032    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
1033    return
1034
1035  def configureInstall(self):
1036    '''Setup the directories for installation'''
1037    if self.framework.argDB['prefix']:
1038      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
1039                                              '-@echo "'+self.installdir.installSudo+'make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
1040                                              '-@echo "========================================="'])
1041    else:
1042      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
1043                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"',\
1044                                              '-@echo "========================================="'])
1045      return
1046
1047  def configureGCOV(self):
1048    if self.framework.argDB['with-gcov']:
1049      self.addDefine('USE_GCOV','1')
1050    return
1051
1052  def configureFortranFlush(self):
1053    if hasattr(self.compilers, 'FC'):
1054      for baseName in ['flush','flush_']:
1055        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
1056          self.addDefine('HAVE_'+baseName.upper(), 1)
1057          return
1058
1059  def configureViewFromOptions(self):
1060    if not self.framework.argDB['with-viewfromoptions']:
1061      self.addDefine('SKIP_VIEWFROMOPTIONS',1)
1062
1063  def postProcessPackages(self):
1064    postPackages=[]
1065    for i in self.framework.packages:
1066      if hasattr(i,'postProcess'): postPackages.append(i)
1067    if postPackages:
1068      # ctetgen needs petsc conf files. so attempt to create them early
1069      self.framework.dumpConfFiles()
1070      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
1071      for i in postPackages:
1072        if i.name.upper() in ['PFLOTRAN']:
1073          i.postProcess()
1074          postPackages.remove(i)
1075      for i in postPackages: i.postProcess()
1076      for i in postPackages:
1077        if i.installedpetsc:
1078          self.installed = 1
1079          break
1080    return
1081
1082  def configure(self):
1083    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
1084      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
1085    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
1086      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
1087    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
1088      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')
1089    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)):
1090      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
1091    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
1092    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
1093    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
1094    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
1095    if self.libraries.math is None:
1096      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
1097    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
1098      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
1099    self.executeTest(self.configureRTLDDefault)
1100    self.executeTest(self.configurePrefetch)
1101    self.executeTest(self.configureUnused)
1102    self.executeTest(self.configureDeprecated)
1103    self.executeTest(self.configureIsatty)
1104    self.executeTest(self.configureExpect);
1105    self.executeTest(self.configureAlign);
1106    self.executeTest(self.configureFunctionName);
1107    self.executeTest(self.configureIntptrt);
1108    self.executeTest(self.configureSolaris)
1109    self.executeTest(self.configureLinux)
1110    self.executeTest(self.configureWin32)
1111    self.executeTest(self.configureCygwinBrokenPipe)
1112    self.executeTest(self.configureDefaultArch)
1113    self.executeTest(self.configureScript)
1114    self.executeTest(self.configureInstall)
1115    self.executeTest(self.configureGCOV)
1116    self.executeTest(self.configureFortranFlush)
1117    self.executeTest(self.configureAtoll)
1118    self.executeTest(self.configureViewFromOptions)
1119
1120    self.Dump()
1121    self.dumpConfigInfo()
1122    self.dumpMachineInfo()
1123    self.dumpCMakeConfig()
1124    self.dumpCMakeLists()
1125    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
1126    self.framework.storeSubstitutions(self.framework.argDB)
1127    self.framework.argDB['configureCache'] = cPickle.dumps(self.framework)
1128    self.framework.argDB.save(force = True)
1129    self.cmakeBoot()
1130    self.DumpPkgconfig()
1131    self.DumpModule()
1132    self.postProcessPackages()
1133    self.framework.log.write('================================================================================\n')
1134    self.logClear()
1135    return
1136