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