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