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