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