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