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