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