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