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