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