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