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