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