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