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