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