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