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