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