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