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