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