xref: /petsc/config/PETSc/Configure.py (revision 9f4d3c52fa2fe0bb72fec4f4e85d8e495867af35)
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 os.listdir(os.path.join('config','PETSc','options')):
102      self.registerPythonFile(utility,'PETSc.options')
103
104    for utility in os.listdir(os.path.join('config','BuildSystem','config','utilities')):
105      self.registerPythonFile(utility,'config.utilities')
106
107    for package in 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#-----------------------------------------------------------------------------------------------------
250
251    # Sometimes we need C compiler, even if built with C++
252    self.setCompilers.pushLanguage('C')
253    self.addMakeMacro('CC_FLAGS',self.setCompilers.getCompilerFlags())
254    self.setCompilers.popLanguage()
255
256    # And sometimes we need a C++ compiler even when PETSc is built with C
257    if hasattr(self.compilers, 'CXX'):
258      self.setCompilers.pushLanguage('Cxx')
259      self.addDefine('HAVE_CXX','1')
260      self.addMakeMacro('CXX_FLAGS',self.setCompilers.getCompilerFlags())
261      self.setCompilers.popLanguage()
262
263    # C preprocessor values
264    self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS)
265
266    # compiler values
267    self.setCompilers.pushLanguage(self.languages.clanguage)
268    self.addMakeMacro('PCC',self.setCompilers.getCompiler())
269    self.addMakeMacro('PCC_FLAGS',self.setCompilers.getCompilerFlags())
270    self.setCompilers.popLanguage()
271    # .o or .obj
272    self.addMakeMacro('CC_SUFFIX','o')
273
274    # executable linker values
275    self.setCompilers.pushLanguage(self.languages.clanguage)
276    pcc_linker = self.setCompilers.getLinker()
277    self.addMakeMacro('PCC_LINKER',pcc_linker)
278    self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
279    self.setCompilers.popLanguage()
280    # '' for Unix, .exe for Windows
281    self.addMakeMacro('CC_LINKER_SUFFIX','')
282
283    if hasattr(self.compilers, 'FC'):
284      if self.framework.argDB['with-fortran-bindings']:
285        self.addDefine('HAVE_FORTRAN','1')
286      self.setCompilers.pushLanguage('FC')
287      # need FPPFLAGS in config/setCompilers
288      self.addMakeMacro('FPP_FLAGS',self.setCompilers.CPPFLAGS)
289
290      # compiler values
291      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
292      self.setCompilers.popLanguage()
293      # .o or .obj
294      self.addMakeMacro('FC_SUFFIX','o')
295
296      # executable linker values
297      self.setCompilers.pushLanguage('FC')
298      # Cannot have NAG f90 as the linker - so use pcc_linker as fc_linker
299      fc_linker = self.setCompilers.getLinker()
300      if config.setCompilers.Configure.isNAG(fc_linker, self.log):
301        self.addMakeMacro('FC_LINKER',pcc_linker)
302      else:
303        self.addMakeMacro('FC_LINKER',fc_linker)
304      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
305      # apple requires this shared library linker flag on SOME versions of the os
306      if self.setCompilers.getLinkerFlags().find('-Wl,-commons,use_dylibs') > -1:
307        self.addMakeMacro('DARWIN_COMMONS_USE_DYLIBS',' -Wl,-commons,use_dylibs ')
308      self.setCompilers.popLanguage()
309
310      # F90 Modules
311      if self.setCompilers.fortranModuleIncludeFlag:
312        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
313      else: # for non-f90 compilers like g77
314        self.addMakeMacro('FC_MODULE_FLAG', '-I')
315      if self.setCompilers.fortranModuleIncludeFlag:
316        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
317    else:
318      self.addMakeMacro('FC','')
319
320    if hasattr(self.compilers, 'CUDAC'):
321      self.setCompilers.pushLanguage('CUDA')
322      self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags())
323      self.setCompilers.popLanguage()
324
325    # shared library linker values
326    self.setCompilers.pushLanguage(self.languages.clanguage)
327    # need to fix BuildSystem to collect these separately
328    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
329    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
330    self.setCompilers.popLanguage()
331    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
332    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
333    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
334      self.addMakeMacro('SL_LINKER_SUFFIX', '')
335      self.addDefine('SLSUFFIX','""')
336    else:
337      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
338      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
339
340    self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}')
341
342#-----------------------------------------------------------------------------------------------------
343
344    # CONLY or CPP. We should change the PETSc makefiles to do this better
345    if self.languages.clanguage == 'C': lang = 'CONLY'
346    else: lang = 'CXXONLY'
347    self.addMakeMacro('PETSC_LANGUAGE',lang)
348
349    # real or complex
350    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
351    # double or float
352    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
353
354    if self.framework.argDB['with-batch']:
355      self.addMakeMacro('PETSC_WITH_BATCH','1')
356
357    # Test for compiler-specific macros that need to be defined.
358    if self.setCompilers.isCrayVector('CC', self.log):
359      self.addDefine('HAVE_CRAY_VECTOR','1')
360
361#-----------------------------------------------------------------------------------------------------
362    if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket') and self.headers.haveHeader('netinet/in.h'):
363      self.addDefine('USE_SOCKET_VIEWER','1')
364      if self.checkCompile('#include <sys/socket.h>','setsockopt(0,SOL_SOCKET,SO_REUSEADDR,0,0)'):
365        self.addDefine('HAVE_SO_REUSEADDR','1')
366
367#-----------------------------------------------------------------------------------------------------
368    # print include and lib for makefiles
369    self.framework.packages.reverse()
370    includes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')]
371    self.packagelibs = []
372    for i in self.framework.packages:
373      if i.useddirectly:
374        self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
375      if not isinstance(i.lib, list):
376        i.lib = [i.lib]
377      if i.linkedbypetsc: self.packagelibs.extend(i.lib)
378      self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib))
379      if hasattr(i,'include'):
380        if not isinstance(i.include,list):
381          i.include = [i.include]
382        includes.extend(i.include)
383        self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include))
384    if self.framework.argDB['with-single-library']:
385      self.petsclib = '-lpetsc'
386    else:
387      self.petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
388    self.complibs = self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split()
389    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)
390    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(self.packagelibs+self.complibs)
391    if self.framework.argDB['prefix'] and self.setCompilers.CSharedLinkerFlag not in ['-L']:
392      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'))
393
394    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.PETSC_EXTERNAL_LIB_BASIC)
395    self.allincludes = self.headers.toStringNoDupes(includes)
396    self.addMakeMacro('PETSC_CC_INCLUDES',self.allincludes)
397    self.PETSC_CC_INCLUDES = self.allincludes
398    if hasattr(self.compilers, 'FC'):
399      if self.compilers.fortranIsF90:
400        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes,includes))
401      else:
402        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes))
403
404    self.addMakeMacro('DESTDIR',self.installdir.dir)
405    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"')
406
407    if self.framework.argDB['with-single-library']:
408      # overrides the values set in conf/variables
409      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
410      self.addMakeMacro('SHLIBS','libpetsc')
411      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
412      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
413      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
414      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
415      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.PETSC_WITH_EXTERNAL_LIB)
416      self.addDefine('USE_SINGLE_LIBRARY', '1')
417      if self.sharedlibraries.useShared:
418        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
419        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
420        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
421        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
422        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
423        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
424        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
425        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
426        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
427        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
428        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
429      else:
430        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
431        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
432        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
433        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
434        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
435        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
436        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
437        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
438        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
439        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
440        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
441
442    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
443      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
444
445# add a makefile endtry for display
446    if self.framework.argDB['with-display']:
447      self.addMakeMacro('DISPLAY',self.framework.argDB['with-display'])
448
449    # add a makefile entry for configure options
450    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
451    return
452
453  def dumpConfigInfo(self):
454    import time
455    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
456    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
457    fd.close()
458    return
459
460  def dumpMachineInfo(self):
461    import platform
462    import time
463    import script
464    def escape(s):
465      return s.replace('"',r'\"').replace(r'\ ',r'\\ ')
466    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
467    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
468    fd.write('\"-----------------------------------------\\n\"\n')
469    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
470    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
471    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.petscdir.dir)))
472    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.arch.arch)))
473    fd.write('\"-----------------------------------------\\n\";\n')
474    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
475    self.setCompilers.pushLanguage(self.languages.clanguage)
476    fd.write('\"Using C compiler: %s %s ${COPTFLAGS} ${CFLAGS}\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
477    self.setCompilers.popLanguage()
478    if hasattr(self.compilers, 'FC'):
479      self.setCompilers.pushLanguage('FC')
480      fd.write('\"Using Fortran compiler: %s %s ${FOPTFLAGS} ${FFLAGS} %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
481      self.setCompilers.popLanguage()
482    fd.write('\"-----------------------------------------\\n\";\n')
483    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
484    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)))
485    fd.write('\"-----------------------------------------\\n\";\n')
486    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
487    self.setCompilers.pushLanguage(self.languages.clanguage)
488    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
489    self.setCompilers.popLanguage()
490    if hasattr(self.compilers, 'FC'):
491      self.setCompilers.pushLanguage('FC')
492      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
493      self.setCompilers.popLanguage()
494    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(self.petsclib), escape(self.PETSC_EXTERNAL_LIB_BASIC)))
495    fd.write('\"-----------------------------------------\\n\";\n')
496    fd.close()
497    return
498
499  def dumpCMakeConfig(self):
500    '''
501    Writes configuration-specific values to ${PETSC_ARCH}/lib/petsc/conf/PETScBuildInternal.cmake.
502    This file is private to PETSc and should not be included by third parties
503    (a suitable file can be produced later by CMake, but this is not it).
504    '''
505    def cmakeset(fd,key,val=True):
506      if val == True: val = 'YES'
507      if val == False: val = 'NO'
508      fd.write('set (' + key + ' ' + val + ')\n')
509    def ensurelist(a):
510      if isinstance(a,list):
511        return a
512      else:
513        return [a]
514    def libpath(lib):
515      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
516      if not isinstance(lib,str): return ''
517      if lib.startswith('-L'): return lib[2:]
518      if lib.startswith('-R'): return lib[2:]
519      if lib.startswith('-Wl,-rpath,'):
520        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
521        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
522        # corresponding library.
523        return lib[len('-Wl,-rpath,'):]
524      if lib.startswith('-'): return ''
525      return os.path.dirname(lib)
526    def cleanlib(lib):
527      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
528      if not isinstance(lib,str): return ''
529      if lib.startswith('-l'):  return lib[2:]
530      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
531      lib = os.path.splitext(os.path.basename(lib))[0]
532      if lib.startswith('lib'): return lib[3:]
533      return lib
534    def nub(lst):
535      'Return a list containing the first occurrence of each unique element'
536      unique = []
537      for elem in lst:
538        if elem not in unique and elem != '':
539          unique.append(elem)
540      return unique
541    try: reversed # reversed was added in Python-2.4
542    except NameError:
543      def reversed(lst): return lst[::-1]
544    def nublast(lst):
545      'Return a list containing the last occurrence of each unique entry in a list'
546      return reversed(nub(reversed(lst)))
547    def cmakeexpand(varname):
548      return r'"${' + varname + r'}"'
549    def uniqextend(lst,new):
550      for x in ensurelist(new):
551        if x not in lst:
552          lst.append(x)
553    def notstandardinclude(path):
554      return path not in '/usr/include'.split() # /usr/local/include is not automatically included on FreeBSD
555    def writeMacroDefinitions(fd):
556      if self.mpi.usingMPIUni:
557        cmakeset(fd,'PETSC_HAVE_MPIUNI')
558      for pkg in self.framework.packages:
559        if pkg.useddirectly:
560          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE.replace('-','_'))
561        for pair in pkg.defines.items():
562          if pair[0].startswith('HAVE_') and pair[1]:
563            cmakeset(fd, self.framework.getFullDefineName(pkg, pair[0]), pair[1])
564      for name,val in self.functions.defines.items():
565        cmakeset(fd,'PETSC_'+name,val)
566      for dct in [self.defines, self.libraryoptions.defines]:
567        for k,v in dct.items():
568          if k.startswith('USE_'):
569            cmakeset(fd,'PETSC_' + k, v)
570      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
571      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
572      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
573      if hasattr(self.compilers, 'FC'):
574        cmakeset(fd,'PETSC_HAVE_FORTRAN')
575        if self.compilers.fortranIsF90:
576          cmakeset(fd,'PETSC_USING_F90')
577        if self.compilers.fortranIsF2003:
578          cmakeset(fd,'PETSC_USING_F2003')
579      if hasattr(self.compilers, 'CXX'):
580        cmakeset(fd,'PETSC_HAVE_CXX')
581      if self.sharedlibraries.useShared:
582        cmakeset(fd,'BUILD_SHARED_LIBS')
583    def writeBuildFlags(fd):
584      def extendby(lib):
585        libs = ensurelist(lib)
586        lib_paths.extend(map(libpath,libs))
587        lib_libs.extend(map(cleanlib,libs))
588      lib_paths = []
589      lib_libs  = []
590      includes  = []
591      libvars   = []
592      for pkg in self.framework.packages:
593        if pkg.linkedbypetsc:
594          extendby(pkg.lib)
595          uniqextend(includes,pkg.include)
596      extendby(self.libraries.math)
597      extendby(self.libraries.rt)
598      extendby(self.compilers.flibs)
599      extendby(self.compilers.cxxlibs)
600      extendby(self.compilers.LIBS.split())
601      for libname in nublast(lib_libs):
602        libvar = 'PETSC_' + libname.upper() + '_LIB'
603        addpath = ''
604        for lpath in nublast(lib_paths):
605          addpath += '"' + str(lpath) + '" '
606        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
607        libvars.append(libvar)
608      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
609      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
610      includes = filter(notstandardinclude,includes)
611      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',includes)) + ')\n')
612    fd = open(os.path.join(self.arch.arch,'lib','petsc','conf','PETScBuildInternal.cmake'), 'w')
613    writeMacroDefinitions(fd)
614    writeBuildFlags(fd)
615    fd.close()
616    return
617
618  def dumpCMakeLists(self):
619    import sys
620    if sys.version_info >= (2,4):
621      import cmakegen
622      try:
623        cmakegen.main(self.petscdir.dir, log=self.framework.log)
624      except (OSError), e:
625        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
626    else:
627      self.framework.logPrint('Skipping cmakegen due to old python version: ' +str(sys.version_info) )
628
629  def cmakeBoot(self):
630    import sys
631    self.cmakeboot_success = False
632    if sys.version_info >= (2,4) and hasattr(self.cmake,'cmake'):
633      oldRead = self.argDB.readonly
634      self.argDB.readonly = True
635      try:
636        import cmakeboot
637        self.cmakeboot_success = cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
638      except (OSError), e:
639        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
640      except (ImportError, KeyError), e:
641        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
642      self.argDB.readonly = oldRead
643      if self.cmakeboot_success:
644        if hasattr(self.compilers, 'FC') and self.compilers.fortranIsF90 and not self.setCompilers.fortranModuleOutputFlag:
645          self.framework.logPrint('CMake configured successfully, but could not be used by default because of missing fortranModuleOutputFlag\n')
646        else:
647          self.framework.logPrint('CMake configured successfully, using as default build\n')
648          self.addMakeMacro('PETSC_BUILD_USING_CMAKE',1)
649      else:
650        self.framework.logPrint('CMake configuration was unsuccessful\n')
651    else:
652      self.framework.logPrint('Skipping cmakeboot due to old python version: ' +str(sys.version_info) )
653    return
654
655  def configurePrefetch(self):
656    '''Sees if there are any prefetch functions supported'''
657    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
658      self.addDefine('Prefetch(a,b,c)', ' ')
659      return
660    self.pushLanguage(self.languages.clanguage)
661    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
662      # The Intel Intrinsics manual [1] specifies the prototype
663      #
664      #   void _mm_prefetch(char const *a, int sel);
665      #
666      # but other vendors seem to insist on using subtly different
667      # prototypes, including void* for the pointer, and an enum for
668      # sel.  These are both reasonable changes, but negatively impact
669      # portability.
670      #
671      # [1] http://software.intel.com/file/6373
672      self.addDefine('HAVE_XMMINTRIN_H', 1)
673      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
674      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
675      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
676      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
677      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
678    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
679      self.addDefine('HAVE_XMMINTRIN_H', 1)
680      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
681      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
682      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
683      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
684      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
685    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
686      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
687      #
688      #   The value of rw is a compile-time constant one or zero; one
689      #   means that the prefetch is preparing for a write to the memory
690      #   address and zero, the default, means that the prefetch is
691      #   preparing for a read. The value locality must be a compile-time
692      #   constant integer between zero and three. A value of zero means
693      #   that the data has no temporal locality, so it need not be left
694      #   in the cache after the access. A value of three means that the
695      #   data has a high degree of temporal locality and should be left
696      #   in all levels of cache possible. Values of one and two mean,
697      #   respectively, a low or moderate degree of temporal locality.
698      #
699      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
700      # hints.  Using macros for these values in necessary since some
701      # compilers require an enum.
702      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
703      self.addDefine('PREFETCH_HINT_NTA', '0')
704      self.addDefine('PREFETCH_HINT_T0',  '3')
705      self.addDefine('PREFETCH_HINT_T1',  '2')
706      self.addDefine('PREFETCH_HINT_T2',  '1')
707    else:
708      self.addDefine('Prefetch(a,b,c)', ' ')
709    self.popLanguage()
710
711  def configureAtoll(self):
712    '''Checks if atoll exists'''
713    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")'):
714       self.addDefine('HAVE_ATOLL', '1')
715
716  def configureUnused(self):
717    '''Sees if __attribute((unused)) is supported'''
718    if self.framework.argDB['with-ios']:
719      self.addDefine('UNUSED', ' ')
720      return
721    self.pushLanguage(self.languages.clanguage)
722    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'):
723      self.addDefine('UNUSED', '__attribute((unused))')
724    else:
725      self.addDefine('UNUSED', ' ')
726    self.popLanguage()
727
728  def configureIsatty(self):
729    '''Check if the Unix C function isatty() works correctly
730       Actually just assumes it does not work correctly on batch systems'''
731    if not self.framework.argDB['with-batch']:
732      self.addDefine('USE_ISATTY',1)
733
734  def configureDeprecated(self):
735    '''Check if __attribute((deprecated)) is supported'''
736    self.pushLanguage(self.languages.clanguage)
737    ## Recent versions of gcc and clang support __attribute((deprecated("string argument"))), which is very useful, but
738    ## Intel has conspired to make a supremely environment-sensitive compiler.  The Intel compiler looks at the gcc
739    ## executable in the environment to determine the language compatibility that it should attempt to emulate.  Some
740    ## important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g.,
741    ## 4.7).  Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc
742    ## found in the default user environment is older and does not support the argument.  If GCC and Intel were cool
743    ## like Clang and supported __has_attribute, we could avoid configure tests entirely, but they don't.  And that is
744    ## why we can't have nice things.
745    #
746    # if self.checkCompile("""__attribute((deprecated("Why you shouldn't use myfunc"))) static int myfunc(void) { return 1;}""", ''):
747    #   self.addDefine('DEPRECATED(why)', '__attribute((deprecated(why)))')
748    if self.checkCompile("""__attribute((deprecated)) static int myfunc(void) { return 1;}""", ''):
749      self.addDefine('DEPRECATED(why)', '__attribute((deprecated))')
750    else:
751      self.addDefine('DEPRECATED(why)', ' ')
752    self.popLanguage()
753
754  def configureAlign(self):
755    '''Check if __attribute(align) is supported'''
756    filename = 'conftestalign'
757    includes = '''
758#include <sys/types.h>
759#if STDC_HEADERS
760#include <stdlib.h>
761#include <stdio.h>
762#include <stddef.h>
763#endif\n'''
764    body     = '''
765struct mystruct {int myint;} __attribute((aligned(16)));
766FILE *f = fopen("'''+filename+'''", "w");
767if (!f) exit(1);
768fprintf(f, "%lu\\n", (unsigned long)sizeof(struct mystruct));
769'''
770    if 'known-has-attribute-aligned' in self.argDB:
771      if self.argDB['known-has-attribute-aligned']:
772        size = 16
773      else:
774        size = -3
775    elif not self.argDB['with-batch']:
776      self.pushLanguage(self.languages.clanguage)
777      try:
778        if self.checkRun(includes, body) and os.path.exists(filename):
779          f    = file(filename)
780          size = int(f.read())
781          f.close()
782          os.remove(filename)
783        else:
784          size = -4
785      except:
786        size = -1
787        self.framework.logPrint('Error checking attribute(aligned)')
788      self.popLanguage()
789    else:
790      self.framework.addBatchInclude(['#include <stdlib.h>', '#include <stdio.h>', '#include <sys/types.h>','struct mystruct {int myint;} __attribute((aligned(16)));'])
791      self.framework.addBatchBody('fprintf(output, "  \'--known-has-attribute-aligned=%d\',\\n", sizeof(struct mystruct)==16);')
792      size = -2
793    if size == 16:
794      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned (size)))')
795      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
796    else:
797      self.framework.logPrint('incorrect alignment. Found alignment:'+ str(size))
798      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
799    return
800
801  def configureExpect(self):
802    '''Sees if the __builtin_expect directive is supported'''
803    self.pushLanguage(self.languages.clanguage)
804    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
805      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
806    self.popLanguage()
807
808  def configureFunctionName(self):
809    '''Sees if the compiler supports __func__ or a variant.'''
810    def getFunctionName(lang):
811      name = '"unknown"'
812      self.pushLanguage(lang)
813      for fname in ['__func__','__FUNCTION__']:
814        code = "if ("+fname+"[0] != 'm') return 1;"
815        if self.checkCompile('',code) and self.checkLink('',code):
816          name = fname
817          break
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