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