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