xref: /petsc/config/PETSc/Configure.py (revision 85afcc9ae9ea289cfdbcd5f2fb7e605e311ecd9d)
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.cmakeboot_success:
24      build_type = 'cmake build'
25    else:
26      build_type = 'legacy build'
27    desc.append(' Configure stage complete. Now build PETSc libraries with (%s):' % build_type)
28    desc.append('   make PETSC_DIR='+self.petscdir.dir+' PETSC_ARCH='+self.arch.arch+' all')
29    desc.append(' or (experimental with python):')
30    desc.append('   PETSC_DIR='+self.petscdir.dir+' PETSC_ARCH='+self.arch.arch+' ./config/builder.py')
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('Windows','-with-windows-graphics=<bool>',   nargs.ArgBool(None, 1,'Enable check for Windows Graphics'))
38    help.addArgument('PETSc', '-with-default-arch=<bool>',        nargs.ArgBool(None, 1, 'Allow using the last configured arch without setting PETSC_ARCH'))
39    help.addArgument('PETSc','-with-single-library=<bool>',       nargs.ArgBool(None, 1,'Put all PETSc code into the single -lpetsc library'))
40    help.addArgument('PETSc', '-with-iphone=<bool>',              nargs.ArgBool(None, 0, 'Build an iPhone version of PETSc'))
41    return
42
43  def setupDependencies(self, framework):
44    config.base.Configure.setupDependencies(self, framework)
45    self.setCompilers  = framework.require('config.setCompilers',      self)
46    self.arch          = framework.require('PETSc.utilities.arch',     self.setCompilers)
47    self.petscdir      = framework.require('PETSc.utilities.petscdir', self.setCompilers)
48    self.languages     = framework.require('PETSc.utilities.languages',self.setCompilers)
49    self.debugging     = framework.require('PETSc.utilities.debugging',self.setCompilers)
50    self.CHUD          = framework.require('PETSc.utilities.CHUD',     self)
51    self.compilers     = framework.require('config.compilers',         self)
52    self.types         = framework.require('config.types',             self)
53    self.headers       = framework.require('config.headers',           self)
54    self.functions     = framework.require('config.functions',         self)
55    self.libraries     = framework.require('config.libraries',         self)
56    if os.path.isdir(os.path.join('config', 'PETSc')):
57      for d in ['utilities', 'packages']:
58        for utility in os.listdir(os.path.join('config', 'PETSc', d)):
59          (utilityName, ext) = os.path.splitext(utility)
60          if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__':
61            utilityObj                    = self.framework.require('PETSc.'+d+'.'+utilityName, self)
62            utilityObj.headerPrefix       = self.headerPrefix
63            utilityObj.archProvider       = self.arch
64            utilityObj.languageProvider   = self.languages
65            utilityObj.installDirProvider = self.petscdir
66            setattr(self, utilityName.lower(), utilityObj)
67
68    for package in config.packages.all:
69      if not package == 'PETSc':
70        packageObj                    = framework.require('config.packages.'+package, self)
71        packageObj.archProvider       = self.arch
72        packageObj.languageProvider   = self.languages
73        packageObj.installDirProvider = self.petscdir
74        setattr(self, package.lower(), packageObj)
75    # Force blaslapack to depend on scalarType so precision is set before BlasLapack is built
76    framework.require('PETSc.utilities.scalarTypes', self.blaslapack)
77    self.blaslapack.precisionProvider = self.scalartypes
78
79    self.compilers.headerPrefix  = self.headerPrefix
80    self.types.headerPrefix      = self.headerPrefix
81    self.headers.headerPrefix    = self.headerPrefix
82    self.functions.headerPrefix  = self.headerPrefix
83    self.libraries.headerPrefix  = self.headerPrefix
84    self.blaslapack.headerPrefix = self.headerPrefix
85    self.mpi.headerPrefix        = self.headerPrefix
86    headersC = map(lambda name: name+'.h', ['dos', 'endian', 'fcntl', 'float', 'io', 'limits', 'malloc', 'pwd', 'search', 'strings',
87                                            'unistd', 'sys/sysinfo', 'machine/endian', 'sys/param', 'sys/procfs', 'sys/resource',
88                                            'sys/systeminfo', 'sys/times', 'sys/utsname','string', 'stdlib','memory',
89                                            'sys/socket','sys/wait','netinet/in','netdb','Direct','time','Ws2tcpip','sys/types',
90                                            'WindowsX', 'cxxabi','float','ieeefp','stdint','fenv','sched'])
91    functions = ['access', '_access', 'clock', 'drand48', 'getcwd', '_getcwd', 'getdomainname', 'gethostname', 'getpwuid',
92                 'gettimeofday', 'getwd', 'memalign', 'memmove', 'mkstemp', 'popen', 'PXFGETARG', 'rand', 'getpagesize',
93                 'readlink', 'realpath',  'sigaction', 'signal', 'sigset', 'nanosleep', 'usleep', 'sleep', '_sleep', 'socket',
94                 'times', 'gethostbyname', 'uname','snprintf','_snprintf','_fullpath','lseek','_lseek','time','fork','stricmp',
95                 'strcasecmp', 'bzero', 'dlopen', 'dlsym', 'dlclose', 'dlerror',
96                 '_intel_fast_memcpy','_intel_fast_memset']
97    libraries1 = [(['socket', 'nsl'], 'socket'), (['fpe'], 'handle_sigfpes')]
98    self.headers.headers.extend(headersC)
99    self.functions.functions.extend(functions)
100    self.libraries.libraries.extend(libraries1)
101
102    return
103
104  def Dump(self):
105    ''' Actually put the values into the configuration files '''
106    # eventually everything between -- should be gone
107#-----------------------------------------------------------------------------------------------------
108
109    # Sometimes we need C compiler, even if built with C++
110    self.setCompilers.pushLanguage('C')
111    self.addMakeMacro('CC_FLAGS',self.setCompilers.getCompilerFlags())
112    self.setCompilers.popLanguage()
113
114    # C preprocessor values
115    self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS+self.CHUD.CPPFLAGS)
116
117    # compiler values
118    self.setCompilers.pushLanguage(self.languages.clanguage)
119    self.addMakeMacro('PCC',self.setCompilers.getCompiler())
120    self.addMakeMacro('PCC_FLAGS',self.setCompilers.getCompilerFlags())
121    self.setCompilers.popLanguage()
122    # .o or .obj
123    self.addMakeMacro('CC_SUFFIX','o')
124
125    # executable linker values
126    self.setCompilers.pushLanguage(self.languages.clanguage)
127    pcc_linker = self.setCompilers.getLinker()
128    self.addMakeMacro('PCC_LINKER',pcc_linker)
129    self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
130    self.setCompilers.popLanguage()
131    # '' for Unix, .exe for Windows
132    self.addMakeMacro('CC_LINKER_SUFFIX','')
133
134    if hasattr(self.compilers, 'FC'):
135      self.setCompilers.pushLanguage('FC')
136      # need FPPFLAGS in config/setCompilers
137      self.addDefine('HAVE_FORTRAN','1')
138      self.addMakeMacro('FPP_FLAGS',self.setCompilers.CPPFLAGS)
139
140      # compiler values
141      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
142      self.setCompilers.popLanguage()
143      # .o or .obj
144      self.addMakeMacro('FC_SUFFIX','o')
145
146      # executable linker values
147      self.setCompilers.pushLanguage('FC')
148      # Cannot have NAG f90 as the linker - so use pcc_linker as fc_linker
149      fc_linker = self.setCompilers.getLinker()
150      if config.setCompilers.Configure.isNAG(fc_linker):
151        self.addMakeMacro('FC_LINKER',pcc_linker)
152      else:
153        self.addMakeMacro('FC_LINKER',fc_linker)
154      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
155      # apple requires this shared library linker flag on SOME versions of the os
156      if self.setCompilers.getLinkerFlags().find('-Wl,-commons,use_dylibs') > -1:
157        self.addMakeMacro('DARWIN_COMMONS_USE_DYLIBS',' -Wl,-commons,use_dylibs ')
158      self.setCompilers.popLanguage()
159
160      # F90 Modules
161      if self.setCompilers.fortranModuleIncludeFlag:
162        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
163      else: # for non-f90 compilers like g77
164        self.addMakeMacro('FC_MODULE_FLAG', '-I')
165      if self.setCompilers.fortranModuleIncludeFlag:
166        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
167    else:
168      self.addMakeMacro('FC','')
169
170    if hasattr(self.compilers, 'CUDAC'):
171      self.setCompilers.pushLanguage('CUDA')
172      self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags())
173      self.setCompilers.popLanguage()
174
175    # shared library linker values
176    self.setCompilers.pushLanguage(self.languages.clanguage)
177    # need to fix BuildSystem to collect these separately
178    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
179    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
180    self.setCompilers.popLanguage()
181    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
182    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
183    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
184      self.addMakeMacro('SL_LINKER_SUFFIX', '')
185      self.addDefine('SLSUFFIX','""')
186    else:
187      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
188      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
189
190    self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}')
191
192#-----------------------------------------------------------------------------------------------------
193
194    # CONLY or CPP. We should change the PETSc makefiles to do this better
195    if self.languages.clanguage == 'C': lang = 'CONLY'
196    else: lang = 'CXXONLY'
197    self.addMakeMacro('PETSC_LANGUAGE',lang)
198
199    # real or complex
200    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
201    # double or float
202    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
203
204    if self.framework.argDB['with-batch']:
205      self.addMakeMacro('PETSC_WITH_BATCH','1')
206
207    # Test for compiler-specific macros that need to be defined.
208    if self.setCompilers.isCrayVector('CC'):
209      self.addDefine('HAVE_CRAY_VECTOR','1')
210
211#-----------------------------------------------------------------------------------------------------
212    if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket') and self.headers.haveHeader('netinet/in.h'):
213      self.addDefine('USE_SOCKET_VIEWER','1')
214
215#-----------------------------------------------------------------------------------------------------
216    # print include and lib for makefiles
217    self.framework.packages.reverse()
218    includes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')]
219    libs = []
220    for i in self.framework.packages:
221      if i.useddirectly:
222        self.addDefine('HAVE_'+i.PACKAGE, 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
223      if not isinstance(i.lib, list):
224        i.lib = [i.lib]
225      libs.extend(i.lib)
226      self.addMakeMacro(i.PACKAGE+'_LIB', self.libraries.toStringNoDupes(i.lib))
227      if hasattr(i,'include'):
228        if not isinstance(i.include,list):
229          i.include = [i.include]
230        includes.extend(i.include)
231        self.addMakeMacro(i.PACKAGE+'_INCLUDE',self.headers.toStringNoDupes(i.include))
232    if self.framework.argDB['with-single-library']:
233      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',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.split(' '))+self.CHUD.LIBS)
234    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.libraries.toStringNoDupes(libs+self.libraries.math+self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' '))+self.CHUD.LIBS)
235    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(libs+self.libraries.math+self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' '))+self.CHUD.LIBS
236    self.addMakeMacro('PETSC_CC_INCLUDES',self.headers.toStringNoDupes(includes))
237    self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(includes)
238    if hasattr(self.compilers, 'FC'):
239      if self.compilers.fortranIsF90:
240        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes,includes))
241      else:
242        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes))
243
244    self.addMakeMacro('DESTDIR',self.installdir)
245    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir,'lib')+'"')
246
247    if self.framework.argDB['with-single-library']:
248      # overrides the values set in conf/variables
249      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
250      self.addMakeMacro('SHLIBS','libpetsc')
251      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
252      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
253      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
254      self.addDefine('USE_SINGLE_LIBRARY', '1')
255      if self.sharedlibraries.useShared:
256        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
257        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
258        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
259        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
260        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
261        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
262        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
263        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
264        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
265        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
266      else:
267        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
268        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
269        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
270        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
271        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
272        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
273        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
274        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
275        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
276        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
277
278    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
279      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
280
281    # add a makefile entry for configure options
282    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
283    return
284
285  def dumpConfigInfo(self):
286    import time
287    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
288    fd.write('static const char *petscconfigureruntime = "'+time.ctime(time.time())+'";\n')
289    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
290    fd.close()
291    return
292
293  def dumpMachineInfo(self):
294    import platform
295    import time
296    import script
297    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
298    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
299    fd.write('\"-----------------------------------------\\n\"\n')
300    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
301    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
302    fd.write('\"Using PETSc directory: %s\\n\"\n' % (self.petscdir.dir))
303    fd.write('\"Using PETSc arch: %s\\n\"\n' % (self.arch.arch))
304    fd.write('\"-----------------------------------------\\n\";\n')
305    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
306    self.setCompilers.pushLanguage(self.languages.clanguage)
307    fd.write('\"Using C compiler: %s %s ${COPTFLAGS} ${CFLAGS}\\n\"\n' % (self.setCompilers.getCompiler(), self.setCompilers.getCompilerFlags()))
308    self.setCompilers.popLanguage()
309    if hasattr(self.compilers, 'FC'):
310      self.setCompilers.pushLanguage('FC')
311      fd.write('\"Using Fortran compiler: %s %s ${FOPTFLAGS} ${FFLAGS} %s\\n\"\n' % (self.setCompilers.getCompiler(), self.setCompilers.getCompilerFlags(), self.setCompilers.CPPFLAGS))
312      self.setCompilers.popLanguage()
313    fd.write('\"-----------------------------------------\\n\";\n')
314    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
315    fd.write('\"Using include paths: %s %s %s\\n\"\n' % ('-I'+os.path.join(self.petscdir.dir, self.arch.arch, 'include'), '-I'+os.path.join(self.petscdir.dir, 'include'), self.PETSC_CC_INCLUDES))
316    fd.write('\"-----------------------------------------\\n\";\n')
317    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
318    self.setCompilers.pushLanguage(self.languages.clanguage)
319    fd.write('\"Using C linker: %s\\n\"\n' % (self.setCompilers.getLinker()))
320    self.setCompilers.popLanguage()
321    if hasattr(self.compilers, 'FC'):
322      self.setCompilers.pushLanguage('FC')
323      fd.write('\"Using Fortran linker: %s\\n\"\n' % (self.setCompilers.getLinker()))
324      self.setCompilers.popLanguage()
325    fd.write('\"Using libraries: %s%s -L%s %s %s\\n\"\n' % (self.setCompilers.CSharedLinkerFlag, os.path.join(self.petscdir.dir, self.arch.arch, 'lib'), os.path.join(self.petscdir.dir, self.arch.arch, 'lib'), '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys', self.PETSC_EXTERNAL_LIB_BASIC))
326    fd.write('\"-----------------------------------------\\n\";\n')
327    fd.close()
328    return
329
330  def dumpCMakeConfig(self):
331    '''
332    Writes configuration-specific values to ${PETSC_ARCH}/conf/PETScConfig.cmake.
333    This file is private to PETSc and should not be included by third parties
334    (a suitable file can be produced later by CMake, but this is not it).
335    '''
336    def cmakeset(fd,key,val=True):
337      if val == True: val = 'YES'
338      if val == False: val = 'NO'
339      fd.write('set (' + key + ' ' + val + ')\n')
340    def ensurelist(a):
341      if isinstance(a,list):
342        return a
343      else:
344        return [a]
345    def libpath(lib):
346      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
347      if not isinstance(lib,str): return ''
348      if lib.startswith('-L'): return lib[2:]
349      if lib.startswith('-R'): return lib[2:]
350      if lib.startswith('-Wl,-rpath,'):
351        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
352        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
353        # corresponding library.
354        return lib[len('-Wl,-rpath,'):]
355      if lib.startswith('-'): return ''
356      return os.path.dirname(lib)
357    def cleanlib(lib):
358      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
359      if not isinstance(lib,str): return ''
360      if lib.startswith('-l'):  return lib[2:]
361      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
362      lib = os.path.splitext(os.path.basename(lib))[0]
363      if lib.startswith('lib'): return lib[3:]
364      return lib
365    def nub(lst):
366      'Return a list containing the first occurrence of each unique element'
367      unique = []
368      for elem in lst:
369        if elem not in unique and elem != '':
370          unique.append(elem)
371      return unique
372    try: reversed # reversed was added in Python-2.4
373    except NameError:
374      def reversed(lst): return lst[::-1]
375    def nublast(lst):
376      'Return a list containing the last occurrence of each unique entry in a list'
377      return reversed(nub(reversed(lst)))
378    def cmakeexpand(varname):
379      return r'"${' + varname + r'}"'
380    def uniqextend(lst,new):
381      for x in ensurelist(new):
382        if x not in lst:
383          lst.append(x)
384    def notstandardinclude(path):
385      return path not in '/usr/include /usr/local/include'.split()
386    def writeMacroDefinitions(fd):
387      if self.mpi.usingMPIUni:
388        cmakeset(fd,'PETSC_HAVE_MPIUNI')
389      for pkg in self.framework.packages:
390        if pkg.useddirectly:
391          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE)
392      for name,val in self.functions.defines.items():
393        cmakeset(fd,'PETSC_'+name,val)
394      for dct in [self.defines, self.libraryoptions.defines]:
395        for k,v in dct.items():
396          if k.startswith('USE_'):
397            cmakeset(fd,'PETSC_' + k, v)
398      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
399      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
400      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
401      if hasattr(self.compilers, 'FC'):
402        cmakeset(fd,'PETSC_HAVE_FORTRAN')
403        if self.compilers.fortranIsF90:
404          cmakeset(fd,'PETSC_USING_F90')
405      if self.sharedlibraries.useShared:
406        cmakeset(fd,'BUILD_SHARED_LIBS')
407    def writeBuildFlags(fd):
408      def extendby(lib):
409        libs = ensurelist(lib)
410        lib_paths.extend(map(libpath,libs))
411        lib_libs.extend(map(cleanlib,libs))
412        uniqextend(includes,pkg.include)
413      lib_paths = []
414      lib_libs  = []
415      includes  = []
416      libvars   = []
417      for pkg in self.framework.packages:
418        extendby(pkg.lib)
419      extendby(self.libraries.math)
420      extendby(self.libraries.rt)
421      extendby(self.compilers.flibs)
422      extendby(self.compilers.cxxlibs)
423      extendby(self.compilers.LIBS.split())
424      for libname in nublast(lib_libs):
425        libvar = 'PETSC_' + libname.upper() + '_LIB'
426        addpath = ''
427        for lpath in nublast(lib_paths):
428          addpath += '"' + str(lpath) + '" '
429        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
430        libvars.append(libvar)
431      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
432      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
433      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',filter(notstandardinclude,includes))) + ')\n')
434    fd = open(os.path.join(self.arch.arch,'conf','PETScConfig.cmake'), 'w')
435    writeMacroDefinitions(fd)
436    writeBuildFlags(fd)
437    fd.close()
438    return
439
440  def dumpCMakeLists(self):
441    import sys
442    if sys.version_info >= (2,5):
443      import cmakegen
444      try:
445        cmakegen.main(self.petscdir.dir)
446      except (OSError), e:
447        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
448    else:
449      self.framework.logPrint('Skipping cmakegen due to old python version: ' +str(sys.version_info) )
450
451  def cmakeBoot(self):
452    import sys
453    self.cmakeboot_success = False
454    if sys.version_info >= (2,5) and hasattr(self.cmake,'cmake'):
455      try:
456        import cmakeboot
457        self.cmakeboot_success = cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
458      except (OSError), e:
459        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
460      except (ImportError, KeyError), e:
461        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
462      if self.cmakeboot_success and not hasattr(self.compilers, 'CUDAC'): # Our CMake build does not support CUDA at this time
463        self.addMakeMacro('PETSC_BUILD_USING_CMAKE',1)
464    else:
465      self.framework.logPrint('Skipping cmakeboot due to old python version: ' +str(sys.version_info) )
466    return
467
468  def configurePrefetch(self):
469    '''Sees if there are any prefetch functions supported'''
470    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
471      self.addDefine('Prefetch(a,b,c)', ' ')
472      return
473    self.pushLanguage(self.languages.clanguage)
474    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
475      # The Intel Intrinsics manual [1] specifies the prototype
476      #
477      #   void _mm_prefetch(char const *a, int sel);
478      #
479      # but other vendors seem to insist on using subtly different
480      # prototypes, including void* for the pointer, and an enum for
481      # sel.  These are both reasonable changes, but negatively impact
482      # portability.
483      #
484      # [1] http://software.intel.com/file/6373
485      self.addDefine('HAVE_XMMINTRIN_H', 1)
486      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
487      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
488      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
489      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
490      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
491    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
492      self.addDefine('HAVE_XMMINTRIN_H', 1)
493      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
494      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
495      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
496      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
497      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
498    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
499      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
500      #
501      #   The value of rw is a compile-time constant one or zero; one
502      #   means that the prefetch is preparing for a write to the memory
503      #   address and zero, the default, means that the prefetch is
504      #   preparing for a read. The value locality must be a compile-time
505      #   constant integer between zero and three. A value of zero means
506      #   that the data has no temporal locality, so it need not be left
507      #   in the cache after the access. A value of three means that the
508      #   data has a high degree of temporal locality and should be left
509      #   in all levels of cache possible. Values of one and two mean,
510      #   respectively, a low or moderate degree of temporal locality.
511      #
512      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
513      # hints.  Using macros for these values in necessary since some
514      # compilers require an enum.
515      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
516      self.addDefine('PREFETCH_HINT_NTA', '0')
517      self.addDefine('PREFETCH_HINT_T0',  '3')
518      self.addDefine('PREFETCH_HINT_T1',  '2')
519      self.addDefine('PREFETCH_HINT_T2',  '1')
520    else:
521      self.addDefine('Prefetch(a,b,c)', ' ')
522    self.popLanguage()
523
524  def configureUnused(self):
525    '''Sees if __attribute((unused)) is supported'''
526    if self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
527      self.addDefine('UNUSED', ' ')
528      return
529    self.pushLanguage(self.languages.clanguage)
530    if self.checkLink('__attribute((unused)) static int myfunc(void){ return 1;}', 'int i = myfunc();\n'):
531      self.addDefine('UNUSED', '__attribute((unused))')
532    else:
533      self.addDefine('UNUSED', ' ')
534    self.popLanguage()
535
536  def configureExpect(self):
537    '''Sees if the __builtin_expect directive is supported'''
538    self.pushLanguage(self.languages.clanguage)
539    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
540      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
541    self.popLanguage()
542
543  def configureFunctionName(self):
544    '''Sees if the compiler supports __func__ or a variant.  Falls back
545    on __FUNCT__ which PETSc source defines, but most users do not, thus
546    stack traces through user code are better when the compiler's
547    variant is used.'''
548    def getFunctionName(lang):
549      name = '__FUNCT__'
550      self.pushLanguage(lang)
551      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
552        name = '__func__'
553      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
554        name = '__FUNCTION__'
555      self.popLanguage()
556      return name
557    langs = []
558
559    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
560    if hasattr(self.compilers, 'CXX'):
561      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
562    else:
563      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
564
565  def configureIntptrt(self):
566    '''Determine what to use for uintptr_t'''
567    def staticAssertSizeMatchesVoidStar(inc,typename):
568      # The declaration is an error if either array size is negative.
569      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
570      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
571                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
572    self.pushLanguage(self.languages.clanguage)
573    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
574      self.addDefine('UINTPTR_T', 'uintptr_t')
575    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
576      self.addDefine('UINTPTR_T', 'unsigned long long')
577    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
578      self.addDefine('UINTPTR_T', 'size_t')
579    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
580      self.addDefine('UINTPTR_T', 'unsigned long')
581    elif staticAssertSizeMatchesVoidStar('','unsigned'):
582      self.addDefine('UINTPTR_T', 'unsigned')
583    else:
584      raise RuntimeError('Could not find any unsigned integer type matching void*')
585    self.popLanguage()
586
587  def configureInline(self):
588    '''Get a generic inline keyword, depending on the language'''
589    if self.languages.clanguage == 'C':
590      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
591      self.addDefine('RESTRICT', self.compilers.cRestrict)
592    elif self.languages.clanguage == 'Cxx':
593      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
594      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
595
596    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
597      self.addDefine('RTLD_DEFAULT','1')
598    return
599
600  def configureSolaris(self):
601    '''Solaris specific stuff'''
602    if os.path.isdir(os.path.join('/usr','ucblib')):
603      try:
604        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
605      except AttributeError:
606        flag = None
607      if flag is None:
608        self.compilers.LIBS += ' -L/usr/ucblib'
609      else:
610        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
611    return
612
613  def configureLinux(self):
614    '''Linux specific stuff'''
615    # TODO: Test for this by mallocing an odd number of floats and checking the address
616    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
617    return
618
619  def configureWin32(self):
620    '''Win32 non-cygwin specific stuff'''
621    kernel32=0
622    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
623      self.addDefine('HAVE_WINDOWS_H',1)
624      self.addDefine('HAVE_GETCOMPUTERNAME',1)
625      kernel32=1
626    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
627      self.addDefine('HAVE_WINDOWS_H',1)
628      self.addDefine('HAVE_GETCOMPUTERNAME',1)
629      kernel32=1
630    if kernel32:
631      if self.framework.argDB['with-windows-graphics']:
632        self.addDefine('USE_WINDOWS_GRAPHICS',1)
633      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
634        self.addDefine('HAVE_LOADLIBRARY',1)
635      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
636        self.addDefine('HAVE_GETPROCADDRESS',1)
637      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
638        self.addDefine('HAVE_FREELIBRARY',1)
639      if self.checkLink('#include <Windows.h>','GetLastError()'):
640        self.addDefine('HAVE_GETLASTERROR',1)
641      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
642        self.addDefine('HAVE_SETLASTERROR',1)
643      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
644        self.addDefine('USE_NT_TIME',1)
645    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
646      self.addDefine('HAVE_GET_USER_NAME',1)
647    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
648      self.addDefine('HAVE_GET_USER_NAME',1)
649
650    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
651      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
652    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
653      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
654
655    self.types.check('int32_t', 'int')
656    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
657      self.addTypedef('int', 'uid_t')
658      self.addTypedef('int', 'gid_t')
659    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
660      self.framework.addDefine('R_OK', '04')
661      self.framework.addDefine('W_OK', '02')
662      self.framework.addDefine('X_OK', '01')
663    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
664      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
665      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
666    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
667      self.addDefine('HAVE_LARGE_INTEGER_U',1)
668
669    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
670    if self.checkCompile('#include <Windows.h>\n', 'int flags = O_BINARY;'):
671      self.addDefine('HAVE_O_BINARY',1)
672
673    if self.compilers.CC.find('win32fe') >= 0:
674      self.addDefine('PATH_SEPARATOR','\';\'')
675      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
676      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
677      self.addDefine('CANNOT_START_DEBUGGER',1)
678    else:
679      self.addDefine('PATH_SEPARATOR','\':\'')
680      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
681      self.addDefine('DIR_SEPARATOR','\'/\'')
682
683    return
684
685#-----------------------------------------------------------------------------------------------------
686  def configureDefaultArch(self):
687    conffile = os.path.join('conf', 'petscvariables')
688    if self.framework.argDB['with-default-arch']:
689      fd = file(conffile, 'w')
690      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
691      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
692      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
693      fd.close()
694      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
695    elif os.path.isfile(conffile):
696      try:
697        os.unlink(conffile)
698      except:
699        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
700    return
701
702#-----------------------------------------------------------------------------------------------------
703  def configureScript(self):
704    '''Output a script in the conf directory which will reproduce the configuration'''
705    import nargs
706    import sys
707    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
708    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
709    if 'configModules' in args:
710      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
711        del args['configModules']
712    if 'optionsModule' in args:
713      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
714        del args['optionsModule']
715    if not 'PETSC_ARCH' in args:
716      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
717    f = file(scriptName, 'w')
718    f.write('#!'+sys.executable+'\n')
719    f.write('if __name__ == \'__main__\':\n')
720    f.write('  import sys\n')
721    f.write('  import os\n')
722    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
723    f.write('  import configure\n')
724    # pretty print repr(args.values())
725    f.write('  configure_options = [\n')
726    for itm in sorted(args.values()):
727      f.write('    \''+str(itm)+'\',\n')
728    f.write('  ]\n')
729    f.write('  configure.petsc_configure(configure_options)\n')
730    f.close()
731    try:
732      os.chmod(scriptName, 0775)
733    except OSError, e:
734      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
735    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
736    return
737
738  def configureInstall(self):
739    '''Setup the directories for installation'''
740    if self.framework.argDB['prefix']:
741      self.installdir = self.framework.argDB['prefix']
742      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
743                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
744                                              '-@echo "========================================="'])
745    else:
746      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
747      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
748                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
749                                              '-@echo "========================================="'])
750      return
751
752  def configureGCOV(self):
753    if self.framework.argDB['with-gcov']:
754      self.addDefine('USE_GCOV','1')
755    return
756
757  def configureFortranFlush(self):
758    if hasattr(self.compilers, 'FC'):
759      for baseName in ['flush','flush_']:
760        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
761          self.addDefine('HAVE_'+baseName.upper(), 1)
762          return
763
764
765  def configure(self):
766    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
767      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
768    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
769      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
770    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)):
771      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
772    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
773    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
774    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
775    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
776    if self.libraries.math is None:
777      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
778    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
779      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
780    self.executeTest(self.configureInline)
781    self.executeTest(self.configurePrefetch)
782    self.executeTest(self.configureUnused)
783    self.executeTest(self.configureExpect);
784    self.executeTest(self.configureFunctionName);
785    self.executeTest(self.configureIntptrt);
786    self.executeTest(self.configureSolaris)
787    self.executeTest(self.configureLinux)
788    self.executeTest(self.configureWin32)
789    self.executeTest(self.configureDefaultArch)
790    self.executeTest(self.configureScript)
791    self.executeTest(self.configureInstall)
792    self.executeTest(self.configureGCOV)
793    self.executeTest(self.configureFortranFlush)
794    # dummy rules, always needed except for remote builds
795    self.addMakeRule('remote','')
796    self.addMakeRule('remoteclean','')
797
798    self.Dump()
799    self.dumpConfigInfo()
800    self.dumpMachineInfo()
801    self.dumpCMakeConfig()
802    self.dumpCMakeLists()
803    self.cmakeBoot()
804    self.framework.log.write('================================================================================\n')
805    self.logClear()
806    return
807