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