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