xref: /petsc/config/PETSc/Configure.py (revision bbd3f3368baff017a6ea7962313571cf23b2b4ec)
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    for package in config.packages.all:
77      if not package == 'PETSc':
78        packageObj                    = framework.require('config.packages.'+package, self)
79        packageObj.archProvider       = self.arch
80        packageObj.languageProvider   = self.languages
81        packageObj.precisionProvider  = self.scalartypes
82        packageObj.installDirProvider = self.installdir
83        packageObj.externalPackagesDirProvider = self.externalpackagesdir
84        setattr(self, package.lower(), packageObj)
85    # Force blaslapack to depend on scalarType so precision is set before BlasLapack is built
86    framework.require('PETSc.utilities.scalarTypes', self.f2cblaslapack)
87    framework.require('PETSc.utilities.scalarTypes', self.fblaslapack)
88    framework.require('PETSc.utilities.scalarTypes', self.blaslapack)
89
90    self.programs.headerPrefix   = self.headerPrefix
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                 '_set_output_format']
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)
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+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+self.CHUD.LIBS
344    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(libs+self.libraries.math+self.compilers.flibs+self.compilers.cxxlibs)+' '+self.compilers.LIBS+self.CHUD.LIBS
345    if self.framework.argDB['prefix'] and self.setCompilers.CSharedLinkerFlag not in ['-L']:
346      installdir = self.framework.argDB['prefix']
347      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'))
348    else:
349      lib_basic = self.PETSC_EXTERNAL_LIB_BASIC
350    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',lib_basic)
351    self.allincludes = self.headers.toStringNoDupes(includes)
352    self.addMakeMacro('PETSC_CC_INCLUDES',self.allincludes)
353    self.PETSC_CC_INCLUDES = self.allincludes
354    if hasattr(self.compilers, 'FC'):
355      if self.compilers.fortranIsF90:
356        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes,includes))
357      else:
358        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes))
359
360    self.addMakeMacro('DESTDIR',self.installdir)
361    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir,'lib')+'"')
362
363    if self.framework.argDB['with-single-library']:
364      # overrides the values set in conf/variables
365      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
366      self.addMakeMacro('SHLIBS','libpetsc')
367      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
368      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
369      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
370      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
371      self.addDefine('USE_SINGLE_LIBRARY', '1')
372      if self.sharedlibraries.useShared:
373        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
374        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
375        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
376        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
377        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
378        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
379        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
380        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
381        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
382        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
383        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
384      else:
385        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
386        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
387        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
388        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
389        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
390        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
391        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
392        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
393        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
394        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
395        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
396
397    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
398      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
399
400    # add a makefile entry for configure options
401    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
402    return
403
404  def dumpConfigInfo(self):
405    import time
406    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
407    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
408    fd.close()
409    return
410
411  def dumpMachineInfo(self):
412    import platform
413    import time
414    import script
415    def escape(s):
416      return s.replace('"',r'\"').replace(r'\ ',r'\\ ')
417    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
418    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
419    fd.write('\"-----------------------------------------\\n\"\n')
420    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
421    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
422    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.petscdir.dir)))
423    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.arch.arch)))
424    fd.write('\"-----------------------------------------\\n\";\n')
425    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
426    self.setCompilers.pushLanguage(self.languages.clanguage)
427    fd.write('\"Using C compiler: %s %s ${COPTFLAGS} ${CFLAGS}\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
428    self.setCompilers.popLanguage()
429    if hasattr(self.compilers, 'FC'):
430      self.setCompilers.pushLanguage('FC')
431      fd.write('\"Using Fortran compiler: %s %s ${FOPTFLAGS} ${FFLAGS} %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
432      self.setCompilers.popLanguage()
433    fd.write('\"-----------------------------------------\\n\";\n')
434    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
435    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)))
436    fd.write('\"-----------------------------------------\\n\";\n')
437    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
438    self.setCompilers.pushLanguage(self.languages.clanguage)
439    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
440    self.setCompilers.popLanguage()
441    if hasattr(self.compilers, 'FC'):
442      self.setCompilers.pushLanguage('FC')
443      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
444      self.setCompilers.popLanguage()
445    if self.framework.argDB['with-single-library']:
446      petsclib = '-lpetsc'
447    else:
448      petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
449    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)))
450    fd.write('\"-----------------------------------------\\n\";\n')
451    fd.close()
452    return
453
454  def dumpCMakeConfig(self):
455    '''
456    Writes configuration-specific values to ${PETSC_ARCH}/conf/PETScConfig.cmake.
457    This file is private to PETSc and should not be included by third parties
458    (a suitable file can be produced later by CMake, but this is not it).
459    '''
460    def cmakeset(fd,key,val=True):
461      if val == True: val = 'YES'
462      if val == False: val = 'NO'
463      fd.write('set (' + key + ' ' + val + ')\n')
464    def ensurelist(a):
465      if isinstance(a,list):
466        return a
467      else:
468        return [a]
469    def libpath(lib):
470      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
471      if not isinstance(lib,str): return ''
472      if lib.startswith('-L'): return lib[2:]
473      if lib.startswith('-R'): return lib[2:]
474      if lib.startswith('-Wl,-rpath,'):
475        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
476        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
477        # corresponding library.
478        return lib[len('-Wl,-rpath,'):]
479      if lib.startswith('-'): return ''
480      return os.path.dirname(lib)
481    def cleanlib(lib):
482      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
483      if not isinstance(lib,str): return ''
484      if lib.startswith('-l'):  return lib[2:]
485      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
486      lib = os.path.splitext(os.path.basename(lib))[0]
487      if lib.startswith('lib'): return lib[3:]
488      return lib
489    def nub(lst):
490      'Return a list containing the first occurrence of each unique element'
491      unique = []
492      for elem in lst:
493        if elem not in unique and elem != '':
494          unique.append(elem)
495      return unique
496    try: reversed # reversed was added in Python-2.4
497    except NameError:
498      def reversed(lst): return lst[::-1]
499    def nublast(lst):
500      'Return a list containing the last occurrence of each unique entry in a list'
501      return reversed(nub(reversed(lst)))
502    def cmakeexpand(varname):
503      return r'"${' + varname + r'}"'
504    def uniqextend(lst,new):
505      for x in ensurelist(new):
506        if x not in lst:
507          lst.append(x)
508    def notstandardinclude(path):
509      return path not in '/usr/include'.split() # /usr/local/include is not automatically included on FreeBSD
510    def writeMacroDefinitions(fd):
511      if self.mpi.usingMPIUni:
512        cmakeset(fd,'PETSC_HAVE_MPIUNI')
513      for pkg in self.framework.packages:
514        if pkg.useddirectly:
515          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE.replace('-','_'))
516        for pair in pkg.defines.items():
517          if pair[0].startswith('HAVE_') and pair[1]:
518            cmakeset(fd, self.framework.getFullDefineName(pkg, pair[0]), pair[1])
519      for name,val in self.functions.defines.items():
520        cmakeset(fd,'PETSC_'+name,val)
521      for dct in [self.defines, self.libraryoptions.defines]:
522        for k,v in dct.items():
523          if k.startswith('USE_'):
524            cmakeset(fd,'PETSC_' + k, v)
525      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
526      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
527      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
528      if hasattr(self.compilers, 'FC'):
529        cmakeset(fd,'PETSC_HAVE_FORTRAN')
530        if self.compilers.fortranIsF90:
531          cmakeset(fd,'PETSC_USING_F90')
532        if self.compilers.fortranIsF2003:
533          cmakeset(fd,'PETSC_USING_F2003')
534      if hasattr(self.compilers, 'CXX'):
535        cmakeset(fd,'PETSC_HAVE_CXX')
536      if self.sharedlibraries.useShared:
537        cmakeset(fd,'BUILD_SHARED_LIBS')
538    def writeBuildFlags(fd):
539      def extendby(lib):
540        libs = ensurelist(lib)
541        lib_paths.extend(map(libpath,libs))
542        lib_libs.extend(map(cleanlib,libs))
543      lib_paths = []
544      lib_libs  = []
545      includes  = []
546      libvars   = []
547      for pkg in self.framework.packages:
548        extendby(pkg.lib)
549        uniqextend(includes,pkg.include)
550      extendby(self.libraries.math)
551      extendby(self.libraries.rt)
552      extendby(self.compilers.flibs)
553      extendby(self.compilers.cxxlibs)
554      extendby(self.compilers.LIBS.split())
555      for libname in nublast(lib_libs):
556        libvar = 'PETSC_' + libname.upper() + '_LIB'
557        addpath = ''
558        for lpath in nublast(lib_paths):
559          addpath += '"' + str(lpath) + '" '
560        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
561        libvars.append(libvar)
562      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
563      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
564      includes = filter(notstandardinclude,includes)
565      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',includes)) + ')\n')
566    fd = open(os.path.join(self.arch.arch,'conf','PETScConfig.cmake'), 'w')
567    writeMacroDefinitions(fd)
568    writeBuildFlags(fd)
569    fd.close()
570    return
571
572  def dumpCMakeLists(self):
573    import sys
574    if sys.version_info >= (2,4):
575      import cmakegen
576      try:
577        cmakegen.main(self.petscdir.dir, log=self.framework.log)
578      except (OSError), e:
579        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
580    else:
581      self.framework.logPrint('Skipping cmakegen due to old python version: ' +str(sys.version_info) )
582
583  def cmakeBoot(self):
584    import sys
585    self.cmakeboot_success = False
586    if sys.version_info >= (2,4) and hasattr(self.cmake,'cmake'):
587      try:
588        import cmakeboot
589        self.cmakeboot_success = cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
590      except (OSError), e:
591        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
592      except (ImportError, KeyError), e:
593        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
594      if self.cmakeboot_success:
595        if hasattr(self.compilers, 'FC') and self.compilers.fortranIsF90 and not self.setCompilers.fortranModuleOutputFlag:
596          self.framework.logPrint('CMake configured successfully, but could not be used by default because of missing fortranModuleOutputFlag\n')
597        else:
598          self.framework.logPrint('CMake configured successfully, using as default build\n')
599          self.addMakeMacro('PETSC_BUILD_USING_CMAKE',1)
600      else:
601        self.framework.logPrint('CMake configuration was unsuccessful\n')
602    else:
603      self.framework.logPrint('Skipping cmakeboot due to old python version: ' +str(sys.version_info) )
604    return
605
606  def configurePrefetch(self):
607    '''Sees if there are any prefetch functions supported'''
608    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-ios']:
609      self.addDefine('Prefetch(a,b,c)', ' ')
610      return
611    self.pushLanguage(self.languages.clanguage)
612    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
613      # The Intel Intrinsics manual [1] specifies the prototype
614      #
615      #   void _mm_prefetch(char const *a, int sel);
616      #
617      # but other vendors seem to insist on using subtly different
618      # prototypes, including void* for the pointer, and an enum for
619      # sel.  These are both reasonable changes, but negatively impact
620      # portability.
621      #
622      # [1] http://software.intel.com/file/6373
623      self.addDefine('HAVE_XMMINTRIN_H', 1)
624      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
625      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
626      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
627      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
628      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
629    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
630      self.addDefine('HAVE_XMMINTRIN_H', 1)
631      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
632      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
633      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
634      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
635      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
636    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
637      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
638      #
639      #   The value of rw is a compile-time constant one or zero; one
640      #   means that the prefetch is preparing for a write to the memory
641      #   address and zero, the default, means that the prefetch is
642      #   preparing for a read. The value locality must be a compile-time
643      #   constant integer between zero and three. A value of zero means
644      #   that the data has no temporal locality, so it need not be left
645      #   in the cache after the access. A value of three means that the
646      #   data has a high degree of temporal locality and should be left
647      #   in all levels of cache possible. Values of one and two mean,
648      #   respectively, a low or moderate degree of temporal locality.
649      #
650      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
651      # hints.  Using macros for these values in necessary since some
652      # compilers require an enum.
653      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
654      self.addDefine('PREFETCH_HINT_NTA', '0')
655      self.addDefine('PREFETCH_HINT_T0',  '3')
656      self.addDefine('PREFETCH_HINT_T1',  '2')
657      self.addDefine('PREFETCH_HINT_T2',  '1')
658    else:
659      self.addDefine('Prefetch(a,b,c)', ' ')
660    self.popLanguage()
661
662  def configureAtoll(self):
663    '''Checks if atoll exists'''
664    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")'):
665       self.addDefine('HAVE_ATOLL', '1')
666
667  def configureUnused(self):
668    '''Sees if __attribute((unused)) is supported'''
669    if self.framework.argDB['with-ios']:
670      self.addDefine('UNUSED', ' ')
671      return
672    self.pushLanguage(self.languages.clanguage)
673    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'):
674      self.addDefine('UNUSED', '__attribute((unused))')
675    else:
676      self.addDefine('UNUSED', ' ')
677    self.popLanguage()
678
679  def configureIsatty(self):
680    '''Check if the Unix C function isatty() works correctly
681       Actually just assumes it does not work correctly on batch systems'''
682    if not self.framework.argDB['with-batch']:
683      self.addDefine('USE_ISATTY',1)
684
685  def configureDeprecated(self):
686    '''Check if __attribute((deprecated)) is supported'''
687    self.pushLanguage(self.languages.clanguage)
688    ## Recent versions of gcc and clang support __attribute((deprecated("string argument"))), which is very useful, but
689    ## Intel has conspired to make a supremely environment-sensitive compiler.  The Intel compiler looks at the gcc
690    ## executable in the environment to determine the language compatibility that it should attempt to emulate.  Some
691    ## important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g.,
692    ## 4.7).  Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc
693    ## found in the default user environment is older and does not support the argument.  If GCC and Intel were cool
694    ## like Clang and supported __has_attribute, we could avoid configure tests entirely, but they don't.  And that is
695    ## why we can't have nice things.
696    #
697    # if self.checkCompile("""__attribute((deprecated("Why you shouldn't use myfunc"))) static int myfunc(void) { return 1;}""", ''):
698    #   self.addDefine('DEPRECATED(why)', '__attribute((deprecated(why)))')
699    if self.checkCompile("""__attribute((deprecated)) static int myfunc(void) { return 1;}""", ''):
700      self.addDefine('DEPRECATED(why)', '__attribute((deprecated))')
701    else:
702      self.addDefine('DEPRECATED(why)', ' ')
703    self.popLanguage()
704
705  def configureExpect(self):
706    '''Sees if the __builtin_expect directive is supported'''
707    self.pushLanguage(self.languages.clanguage)
708    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
709      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
710    self.popLanguage()
711
712  def configureFunctionName(self):
713    '''Sees if the compiler supports __func__ or a variant.  Falls back
714    on __FUNCT__ which PETSc source defines, but most users do not, thus
715    stack traces through user code are better when the compiler's
716    variant is used.'''
717    def getFunctionName(lang):
718      name = '__FUNCT__'
719      self.pushLanguage(lang)
720      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
721        name = '__func__'
722      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
723        name = '__FUNCTION__'
724      self.popLanguage()
725      return name
726    langs = []
727
728    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
729    if hasattr(self.compilers, 'CXX'):
730      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
731    else:
732      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
733
734  def configureIntptrt(self):
735    '''Determine what to use for uintptr_t'''
736    def staticAssertSizeMatchesVoidStar(inc,typename):
737      # The declaration is an error if either array size is negative.
738      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
739      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
740                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
741    self.pushLanguage(self.languages.clanguage)
742    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
743      self.addDefine('UINTPTR_T', 'uintptr_t')
744    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
745      self.addDefine('UINTPTR_T', 'unsigned long long')
746    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
747      self.addDefine('UINTPTR_T', 'size_t')
748    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
749      self.addDefine('UINTPTR_T', 'unsigned long')
750    elif staticAssertSizeMatchesVoidStar('','unsigned'):
751      self.addDefine('UINTPTR_T', 'unsigned')
752    else:
753      raise RuntimeError('Could not find any unsigned integer type matching void*')
754    self.popLanguage()
755
756  def configureRTLDDefault(self):
757    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
758      self.addDefine('RTLD_DEFAULT','1')
759    return
760
761  def configureSolaris(self):
762    '''Solaris specific stuff'''
763    if os.path.isdir(os.path.join('/usr','ucblib')):
764      try:
765        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
766      except AttributeError:
767        flag = None
768      if flag is None:
769        self.compilers.LIBS += ' -L/usr/ucblib'
770      else:
771        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
772    return
773
774  def configureLinux(self):
775    '''Linux specific stuff'''
776    # TODO: Test for this by mallocing an odd number of floats and checking the address
777    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
778    return
779
780  def configureWin32(self):
781    '''Win32 non-cygwin specific stuff'''
782    kernel32=0
783    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
784      self.addDefine('HAVE_WINDOWS_H',1)
785      self.addDefine('HAVE_GETCOMPUTERNAME',1)
786      kernel32=1
787    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
788      self.addDefine('HAVE_WINDOWS_H',1)
789      self.addDefine('HAVE_GETCOMPUTERNAME',1)
790      kernel32=1
791    if kernel32:
792      if self.framework.argDB['with-windows-graphics']:
793        self.addDefine('USE_WINDOWS_GRAPHICS',1)
794      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
795        self.addDefine('HAVE_LOADLIBRARY',1)
796      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
797        self.addDefine('HAVE_GETPROCADDRESS',1)
798      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
799        self.addDefine('HAVE_FREELIBRARY',1)
800      if self.checkLink('#include <Windows.h>','GetLastError()'):
801        self.addDefine('HAVE_GETLASTERROR',1)
802      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
803        self.addDefine('HAVE_SETLASTERROR',1)
804      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
805        self.addDefine('USE_MICROSOFT_TIME',1)
806    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
807      self.addDefine('HAVE_GET_USER_NAME',1)
808    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
809      self.addDefine('HAVE_GET_USER_NAME',1)
810
811    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
812      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
813    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
814      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
815
816    self.types.check('int32_t', 'int')
817    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
818      self.addTypedef('int', 'uid_t')
819      self.addTypedef('int', 'gid_t')
820    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
821      self.framework.addDefine('R_OK', '04')
822      self.framework.addDefine('W_OK', '02')
823      self.framework.addDefine('X_OK', '01')
824    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
825      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
826      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
827    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
828      self.addDefine('HAVE_LARGE_INTEGER_U',1)
829
830    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
831    if self.checkCompile('#include <Windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
832      self.addDefine('HAVE_O_BINARY',1)
833
834    if self.compilers.CC.find('win32fe') >= 0:
835      self.addDefine('PATH_SEPARATOR','\';\'')
836      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
837      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
838      self.addDefine('CANNOT_START_DEBUGGER',1)
839      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.petscdir.dir)
840      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
841    else:
842      self.addDefine('PATH_SEPARATOR','\':\'')
843      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
844      self.addDefine('DIR_SEPARATOR','\'/\'')
845      self.addDefine('DIR', '"'+self.petscdir.dir+'"')
846
847    return
848
849#-----------------------------------------------------------------------------------------------------
850  def configureCygwinBrokenPipe(self):
851    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
852    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
853    if config.setCompilers.Configure.isCygwin():
854      import platform
855      import re
856      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
857      m=r.match(platform.release())
858      major=int(m.group(1))
859      minor=int(m.group(2))
860      subminor=int(m.group(3))
861      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
862        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
863    return
864
865#-----------------------------------------------------------------------------------------------------
866  def configureDefaultArch(self):
867    conffile = os.path.join('conf', 'petscvariables')
868    if self.framework.argDB['with-default-arch']:
869      fd = file(conffile, 'w')
870      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
871      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
872      fd.write('include '+os.path.join(self.petscdir.dir,self.arch.arch,'conf','petscvariables')+'\n')
873      fd.close()
874      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
875    elif os.path.isfile(conffile):
876      try:
877        os.unlink(conffile)
878      except:
879        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
880    return
881
882#-----------------------------------------------------------------------------------------------------
883  def configureScript(self):
884    '''Output a script in the conf directory which will reproduce the configuration'''
885    import nargs
886    import sys
887    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
888    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
889    if 'with-clean' in args:
890      del args['with-clean']
891    if 'configModules' in args:
892      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
893        del args['configModules']
894    if 'optionsModule' in args:
895      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
896        del args['optionsModule']
897    if not 'PETSC_ARCH' in args:
898      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
899    f = file(scriptName, 'w')
900    f.write('#!'+sys.executable+'\n')
901    f.write('if __name__ == \'__main__\':\n')
902    f.write('  import sys\n')
903    f.write('  import os\n')
904    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
905    f.write('  import configure\n')
906    # pretty print repr(args.values())
907    f.write('  configure_options = [\n')
908    for itm in sorted(args.values()):
909      f.write('    \''+str(itm)+'\',\n')
910    f.write('  ]\n')
911    f.write('  configure.petsc_configure(configure_options)\n')
912    f.close()
913    try:
914      os.chmod(scriptName, 0775)
915    except OSError, e:
916      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
917    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
918    return
919
920  def configureInstall(self):
921    '''Setup the directories for installation'''
922    if self.framework.argDB['prefix']:
923      self.installdir = self.framework.argDB['prefix']
924      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
925                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
926                                              '-@echo "========================================="'])
927    else:
928      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
929      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
930                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
931                                              '-@echo "========================================="'])
932      return
933
934  def configureGCOV(self):
935    if self.framework.argDB['with-gcov']:
936      self.addDefine('USE_GCOV','1')
937    return
938
939  def configureFortranFlush(self):
940    if hasattr(self.compilers, 'FC'):
941      for baseName in ['flush','flush_']:
942        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
943          self.addDefine('HAVE_'+baseName.upper(), 1)
944          return
945
946  def postProcessPackages(self):
947    postPackages=[]
948    for i in self.framework.packages:
949      if hasattr(i,'postProcess'): postPackages.append(i)
950    if postPackages:
951      # ctetgen needs petsc conf files. so attempt to create them early
952      self.framework.dumpConfFiles()
953      for i in postPackages: i.postProcess()
954    return
955
956  def configure(self):
957    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
958      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
959    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
960      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
961    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)):
962      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
963    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
964    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
965    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
966    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
967    if self.libraries.math is None:
968      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
969    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
970      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
971    self.executeTest(self.configureRTLDDefault)
972    self.executeTest(self.configurePrefetch)
973    self.executeTest(self.configureUnused)
974    self.executeTest(self.configureDeprecated)
975    self.executeTest(self.configureIsatty)
976    self.executeTest(self.configureExpect);
977    self.executeTest(self.configureFunctionName);
978    self.executeTest(self.configureIntptrt);
979    self.executeTest(self.configureSolaris)
980    self.executeTest(self.configureLinux)
981    self.executeTest(self.configureWin32)
982    self.executeTest(self.configureCygwinBrokenPipe)
983    self.executeTest(self.configureDefaultArch)
984    self.executeTest(self.configureScript)
985    self.executeTest(self.configureInstall)
986    self.executeTest(self.configureGCOV)
987    self.executeTest(self.configureFortranFlush)
988    self.executeTest(self.configureAtoll)
989    # dummy rules, always needed except for remote builds
990    self.addMakeRule('remote','')
991    self.addMakeRule('remoteclean','')
992
993    self.Dump()
994    self.dumpConfigInfo()
995    self.dumpMachineInfo()
996    self.postProcessPackages()
997    self.dumpCMakeConfig()
998    self.dumpCMakeLists()
999    self.cmakeBoot()
1000    self.DumpPkgconfig()
1001    self.DumpModule()
1002    self.framework.log.write('================================================================================\n')
1003    self.logClear()
1004    return
1005