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