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