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