xref: /petsc/config/PETSc/Configure.py (revision 7b6bb2c608b6fc6714ef38fda02c2dbb91c82665)
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', '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'])
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'):
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    return
460
461  def configurePrefetch(self):
462    '''Sees if there are any prefetch functions supported'''
463    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
464      self.addDefine('Prefetch(a,b,c)', ' ')
465      return
466    self.pushLanguage(self.languages.clanguage)
467    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
468      # The Intel Intrinsics manual [1] specifies the prototype
469      #
470      #   void _mm_prefetch(char const *a, int sel);
471      #
472      # but other vendors seem to insist on using subtly different
473      # prototypes, including void* for the pointer, and an enum for
474      # sel.  These are both reasonable changes, but negatively impact
475      # portability.
476      #
477      # [1] http://software.intel.com/file/6373
478      self.addDefine('HAVE_XMMINTRIN_H', 1)
479      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
480      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
481      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
482      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
483      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
484    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
485      self.addDefine('HAVE_XMMINTRIN_H', 1)
486      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(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('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
492      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
493      #
494      #   The value of rw is a compile-time constant one or zero; one
495      #   means that the prefetch is preparing for a write to the memory
496      #   address and zero, the default, means that the prefetch is
497      #   preparing for a read. The value locality must be a compile-time
498      #   constant integer between zero and three. A value of zero means
499      #   that the data has no temporal locality, so it need not be left
500      #   in the cache after the access. A value of three means that the
501      #   data has a high degree of temporal locality and should be left
502      #   in all levels of cache possible. Values of one and two mean,
503      #   respectively, a low or moderate degree of temporal locality.
504      #
505      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
506      # hints.  Using macros for these values in necessary since some
507      # compilers require an enum.
508      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
509      self.addDefine('PREFETCH_HINT_NTA', '0')
510      self.addDefine('PREFETCH_HINT_T0',  '3')
511      self.addDefine('PREFETCH_HINT_T1',  '2')
512      self.addDefine('PREFETCH_HINT_T2',  '1')
513    else:
514      self.addDefine('Prefetch(a,b,c)', ' ')
515    self.popLanguage()
516
517  def configureUnused(self):
518    '''Sees if __attribute((unused)) is supported'''
519    if self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
520      self.addDefine('UNUSED', ' ')
521      return
522    self.pushLanguage(self.languages.clanguage)
523    if self.checkLink('__attribute((unused)) static int myfunc(void){ return 1;}', 'int i = myfunc();\n'):
524      self.addDefine('UNUSED', '__attribute((unused))')
525    else:
526      self.addDefine('UNUSED', ' ')
527    self.popLanguage()
528
529  def configureExpect(self):
530    '''Sees if the __builtin_expect directive is supported'''
531    self.pushLanguage(self.languages.clanguage)
532    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
533      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
534    self.popLanguage()
535
536  def configureFunctionName(self):
537    '''Sees if the compiler supports __func__ or a variant.  Falls back
538    on __FUNCT__ which PETSc source defines, but most users do not, thus
539    stack traces through user code are better when the compiler's
540    variant is used.'''
541    def getFunctionName(lang):
542      name = '__FUNCT__'
543      self.pushLanguage(lang)
544      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
545        name = '__func__'
546      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
547        name = '__FUNCTION__'
548      self.popLanguage()
549      return name
550    langs = []
551
552    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
553    if hasattr(self.compilers, 'CXX'):
554      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
555    else:
556      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
557
558  def configureIntptrt(self):
559    '''Determine what to use for uintptr_t'''
560    def staticAssertSizeMatchesVoidStar(inc,typename):
561      # The declaration is an error if either array size is negative.
562      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
563      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
564                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
565    self.pushLanguage(self.languages.clanguage)
566    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
567      self.addDefine('UINTPTR_T', 'uintptr_t')
568    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
569      self.addDefine('UINTPTR_T', 'unsigned long long')
570    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
571      self.addDefine('UINTPTR_T', 'size_t')
572    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
573      self.addDefine('UINTPTR_T', 'unsigned long')
574    elif staticAssertSizeMatchesVoidStar('','unsigned'):
575      self.addDefine('UINTPTR_T', 'unsigned')
576    else:
577      raise RuntimeError('Could not find any unsigned integer type matching void*')
578    self.popLanguage()
579
580  def configureInline(self):
581    '''Get a generic inline keyword, depending on the language'''
582    if self.languages.clanguage == 'C':
583      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
584      self.addDefine('RESTRICT', self.compilers.cRestrict)
585    elif self.languages.clanguage == 'Cxx':
586      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
587      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
588
589    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
590      self.addDefine('RTLD_DEFAULT','1')
591    return
592
593  def configureSolaris(self):
594    '''Solaris specific stuff'''
595    if os.path.isdir(os.path.join('/usr','ucblib')):
596      try:
597        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
598      except AttributeError:
599        flag = None
600      if flag is None:
601        self.compilers.LIBS += ' -L/usr/ucblib'
602      else:
603        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
604    return
605
606  def configureLinux(self):
607    '''Linux specific stuff'''
608    # TODO: Test for this by mallocing an odd number of floats and checking the address
609    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
610    return
611
612  def configureWin32(self):
613    '''Win32 non-cygwin specific stuff'''
614    kernel32=0
615    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
616      self.addDefine('HAVE_WINDOWS_H',1)
617      self.addDefine('HAVE_GETCOMPUTERNAME',1)
618      kernel32=1
619    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
620      self.addDefine('HAVE_WINDOWS_H',1)
621      self.addDefine('HAVE_GETCOMPUTERNAME',1)
622      kernel32=1
623    if kernel32:
624      if self.framework.argDB['with-windows-graphics']:
625        self.addDefine('USE_WINDOWS_GRAPHICS',1)
626      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
627        self.addDefine('HAVE_LOADLIBRARY',1)
628      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
629        self.addDefine('HAVE_GETPROCADDRESS',1)
630      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
631        self.addDefine('HAVE_FREELIBRARY',1)
632      if self.checkLink('#include <Windows.h>','GetLastError()'):
633        self.addDefine('HAVE_GETLASTERROR',1)
634      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
635        self.addDefine('HAVE_SETLASTERROR',1)
636      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
637        self.addDefine('USE_NT_TIME',1)
638    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
639      self.addDefine('HAVE_GET_USER_NAME',1)
640    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
641      self.addDefine('HAVE_GET_USER_NAME',1)
642
643    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
644      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
645    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
646      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
647
648    self.types.check('int32_t', 'int')
649    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
650      self.addTypedef('int', 'uid_t')
651      self.addTypedef('int', 'gid_t')
652    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
653      self.framework.addDefine('R_OK', '04')
654      self.framework.addDefine('W_OK', '02')
655      self.framework.addDefine('X_OK', '01')
656    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
657      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
658      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
659    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
660      self.addDefine('HAVE_LARGE_INTEGER_U',1)
661
662    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
663    if self.checkCompile('#include <Windows.h>\n', 'int flags = O_BINARY;'):
664      self.addDefine('HAVE_O_BINARY',1)
665
666    if self.compilers.CC.find('win32fe') >= 0:
667      self.addDefine('PATH_SEPARATOR','\';\'')
668      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
669      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
670      self.addDefine('CANNOT_START_DEBUGGER',1)
671    else:
672      self.addDefine('PATH_SEPARATOR','\':\'')
673      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
674      self.addDefine('DIR_SEPARATOR','\'/\'')
675
676    return
677
678#-----------------------------------------------------------------------------------------------------
679  def configureDefaultArch(self):
680    conffile = os.path.join('conf', 'petscvariables')
681    if self.framework.argDB['with-default-arch']:
682      fd = file(conffile, 'w')
683      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
684      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
685      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
686      fd.close()
687      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
688    elif os.path.isfile(conffile):
689      try:
690        os.unlink(conffile)
691      except:
692        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
693    return
694
695#-----------------------------------------------------------------------------------------------------
696  def configureScript(self):
697    '''Output a script in the conf directory which will reproduce the configuration'''
698    import nargs
699    import sys
700    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
701    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
702    if 'configModules' in args:
703      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
704        del args['configModules']
705    if 'optionsModule' in args:
706      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
707        del args['optionsModule']
708    if not 'PETSC_ARCH' in args:
709      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
710    f = file(scriptName, 'w')
711    f.write('#!'+sys.executable+'\n')
712    f.write('if __name__ == \'__main__\':\n')
713    f.write('  import sys\n')
714    f.write('  import os\n')
715    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
716    f.write('  import configure\n')
717    # pretty print repr(args.values())
718    f.write('  configure_options = [\n')
719    for itm in sorted(args.values()):
720      f.write('    \''+str(itm)+'\',\n')
721    f.write('  ]\n')
722    f.write('  configure.petsc_configure(configure_options)\n')
723    f.close()
724    try:
725      os.chmod(scriptName, 0775)
726    except OSError, e:
727      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
728    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
729    return
730
731  def configureInstall(self):
732    '''Setup the directories for installation'''
733    if self.framework.argDB['prefix']:
734      self.installdir = self.framework.argDB['prefix']
735      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
736                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
737                                              '-@echo "========================================="'])
738    else:
739      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
740      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
741                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
742                                              '-@echo "========================================="'])
743      return
744
745  def configureGCOV(self):
746    if self.framework.argDB['with-gcov']:
747      self.addDefine('USE_GCOV','1')
748    return
749
750  def configureFortranFlush(self):
751    if hasattr(self.compilers, 'FC'):
752      for baseName in ['flush','flush_']:
753        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
754          self.addDefine('HAVE_'+baseName.upper(), 1)
755          return
756
757
758  def configure(self):
759    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
760      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
761    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
762      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
763    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)):
764      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
765    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
766    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
767    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
768    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
769    if self.libraries.math is None:
770      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
771    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
772      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
773    self.executeTest(self.configureInline)
774    self.executeTest(self.configurePrefetch)
775    self.executeTest(self.configureUnused)
776    self.executeTest(self.configureExpect);
777    self.executeTest(self.configureFunctionName);
778    self.executeTest(self.configureIntptrt);
779    self.executeTest(self.configureSolaris)
780    self.executeTest(self.configureLinux)
781    self.executeTest(self.configureWin32)
782    self.executeTest(self.configureDefaultArch)
783    self.executeTest(self.configureScript)
784    self.executeTest(self.configureInstall)
785    self.executeTest(self.configureGCOV)
786    self.executeTest(self.configureFortranFlush)
787    # dummy rules, always needed except for remote builds
788    self.addMakeRule('remote','')
789    self.addMakeRule('remoteclean','')
790
791    self.Dump()
792    self.dumpConfigInfo()
793    self.dumpMachineInfo()
794    self.dumpCMakeConfig()
795    self.dumpCMakeLists()
796    self.cmakeBoot()
797    self.framework.log.write('================================================================================\n')
798    self.logClear()
799    return
800