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