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