xref: /petsc/config/PETSc/Configure.py (revision 42e8629d68ca496fa85ee9d9ed12fa495a249bd3)
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 not isinstance(lib,str): return ''
341      if lib.startswith('-L'): return lib[2:]
342      if lib.startswith('-R'): return lib[2:]
343      if lib.startswith('-Wl,-rpath,'):
344        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
345        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
346        # corresponding library.
347        return lib[len('-Wl,-rpath,'):]
348      if lib.startswith('-'): return ''
349      return os.path.dirname(lib)
350    def cleanlib(lib):
351      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
352      if not isinstance(lib,str): return ''
353      if lib.startswith('-l'):  return lib[2:]
354      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
355      lib = os.path.splitext(os.path.basename(lib))[0]
356      if lib.startswith('lib'): return lib[3:]
357      return lib
358    def nub(lst):
359      'Return a list containing the first occurrence of each unique element'
360      unique = []
361      for elem in lst:
362        if elem not in unique and elem != '':
363          unique.append(elem)
364      return unique
365    def nublast(lst):
366      'Return a list containing the last occurrence of each unique entry in a list'
367      return reversed(nub(reversed(lst)))
368    def cmakeexpand(varname):
369      return r'"${' + varname + r'}"'
370    def uniqextend(lst,new):
371      for x in ensurelist(new):
372        if x not in lst:
373          lst.append(x)
374    def notstandardinclude(path):
375      return path not in '/usr/include /usr/local/include'.split()
376    def writeMacroDefinitions(fd):
377      if self.mpi.usingMPIUni:
378        cmakeset(fd,'PETSC_HAVE_MPIUNI')
379      for pkg in self.framework.packages:
380        if pkg.useddirectly:
381          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE)
382      for name,val in self.functions.defines.items():
383        cmakeset(fd,'PETSC_'+name,val)
384      for dct in [self.defines, self.libraryoptions.defines]:
385        for k,v in dct.items():
386          if k.startswith('USE_'):
387            cmakeset(fd,'PETSC_' + k, v)
388      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
389      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
390      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
391      if hasattr(self.compilers, 'FC'):
392        cmakeset(fd,'PETSC_HAVE_FORTRAN')
393        if self.compilers.fortranIsF90:
394          cmakeset(fd,'PETSC_USING_F90')
395      if self.sharedlibraries.useShared:
396        cmakeset(fd,'BUILD_SHARED_LIBS')
397    def writeBuildFlags(fd):
398      def extendby(lib):
399        libs = ensurelist(lib)
400        lib_paths.extend(map(libpath,libs))
401        lib_libs.extend(map(cleanlib,libs))
402        uniqextend(includes,pkg.include)
403      lib_paths = []
404      lib_libs  = []
405      includes  = []
406      libvars   = []
407      for pkg in self.framework.packages:
408        extendby(pkg.lib)
409      extendby(self.libraries.math)
410      extendby(self.libraries.rt)
411      extendby(self.compilers.flibs)
412      extendby(self.compilers.cxxlibs)
413      extendby(self.compilers.LIBS.split())
414      for libname in nublast(lib_libs):
415        libvar = 'PETSC_' + libname.upper() + '_LIB'
416        addpath = ''
417        for lpath in nublast(lib_paths):
418          addpath += '"' + str(lpath) + '" '
419        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
420        libvars.append(libvar)
421      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
422      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
423      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',filter(notstandardinclude,includes))) + ')\n')
424    fd = open(os.path.join(self.arch.arch,'conf','PETScConfig.cmake'), 'w')
425    writeMacroDefinitions(fd)
426    writeBuildFlags(fd)
427    fd.close()
428    return
429
430  def dumpCMakeLists(self):
431    import sys
432    if sys.version_info >= (2,5):
433      import cmakegen
434      try:
435        cmakegen.main(self.petscdir.dir)
436      except (OSError), e:
437        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
438
439  def cmakeBoot(self):
440    import sys
441    if sys.version_info >= (2,5) and hasattr(self.cmake,'cmake'):
442      try:
443        import cmakeboot
444        cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
445      except (OSError), e:
446        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
447      except (ImportError, KeyError), e:
448        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
449    return
450
451  def configurePrefetch(self):
452    '''Sees if there are any prefetch functions supported'''
453    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
454      self.addDefine('Prefetch(a,b,c)', ' ')
455      return
456    self.pushLanguage(self.languages.clanguage)
457    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
458      # The Intel Intrinsics manual [1] specifies the prototype
459      #
460      #   void _mm_prefetch(char const *a, int sel);
461      #
462      # but other vendors seem to insist on using subtly different
463      # prototypes, including void* for the pointer, and an enum for
464      # sel.  These are both reasonable changes, but negatively impact
465      # portability.
466      #
467      # [1] http://software.intel.com/file/6373
468      self.addDefine('HAVE_XMMINTRIN_H', 1)
469      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(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('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
475      self.addDefine('HAVE_XMMINTRIN_H', 1)
476      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
477      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
478      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
479      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
480      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
481    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
482      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
483      #
484      #   The value of rw is a compile-time constant one or zero; one
485      #   means that the prefetch is preparing for a write to the memory
486      #   address and zero, the default, means that the prefetch is
487      #   preparing for a read. The value locality must be a compile-time
488      #   constant integer between zero and three. A value of zero means
489      #   that the data has no temporal locality, so it need not be left
490      #   in the cache after the access. A value of three means that the
491      #   data has a high degree of temporal locality and should be left
492      #   in all levels of cache possible. Values of one and two mean,
493      #   respectively, a low or moderate degree of temporal locality.
494      #
495      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
496      # hints.  Using macros for these values in necessary since some
497      # compilers require an enum.
498      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
499      self.addDefine('PREFETCH_HINT_NTA', '0')
500      self.addDefine('PREFETCH_HINT_T0',  '3')
501      self.addDefine('PREFETCH_HINT_T1',  '2')
502      self.addDefine('PREFETCH_HINT_T2',  '1')
503    else:
504      self.addDefine('Prefetch(a,b,c)', ' ')
505    self.popLanguage()
506
507  def configureUnused(self):
508    '''Sees if __attribute((unused)) is supported'''
509    if self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
510      self.addDefine('UNUSED', ' ')
511      return
512    self.pushLanguage(self.languages.clanguage)
513    if self.checkLink('__attribute((unused)) static int myfunc(void){ return 1;}', 'int i = myfunc();\n'):
514      self.addDefine('UNUSED', '__attribute((unused))')
515    else:
516      self.addDefine('UNUSED', ' ')
517    self.popLanguage()
518
519  def configureExpect(self):
520    '''Sees if the __builtin_expect directive is supported'''
521    self.pushLanguage(self.languages.clanguage)
522    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
523      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
524    self.popLanguage()
525
526  def configureFunctionName(self):
527    '''Sees if the compiler supports __func__ or a variant.  Falls back
528    on __FUNCT__ which PETSc source defines, but most users do not, thus
529    stack traces through user code are better when the compiler's
530    variant is used.'''
531    def getFunctionName(lang):
532      name = '__FUNCT__'
533      self.pushLanguage(lang)
534      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
535        name = '__func__'
536      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
537        name = '__FUNCTION__'
538      self.popLanguage()
539      return name
540    langs = []
541
542    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
543    if hasattr(self.compilers, 'CXX'):
544      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
545    else:
546      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
547
548  def configureIntptrt(self):
549    '''Determine what to use for uintptr_t'''
550    def staticAssertSizeMatchesVoidStar(inc,typename):
551      # The declaration is an error if either array size is negative.
552      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
553      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
554                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
555    self.pushLanguage(self.languages.clanguage)
556    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
557      self.addDefine('UINTPTR_T', 'uintptr_t')
558    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
559      self.addDefine('UINTPTR_T', 'unsigned long long')
560    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
561      self.addDefine('UINTPTR_T', 'size_t')
562    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
563      self.addDefine('UINTPTR_T', 'unsigned long')
564    elif staticAssertSizeMatchesVoidStar('','unsigned'):
565      self.addDefine('UINTPTR_T', 'unsigned')
566    else:
567      raise RuntimeError('Could not find any unsigned integer type matching void*')
568    self.popLanguage()
569
570  def configureInline(self):
571    '''Get a generic inline keyword, depending on the language'''
572    if self.languages.clanguage == 'C':
573      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
574      self.addDefine('RESTRICT', self.compilers.cRestrict)
575    elif self.languages.clanguage == 'Cxx':
576      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
577      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
578    return
579
580  def configureSolaris(self):
581    '''Solaris specific stuff'''
582    if os.path.isdir(os.path.join('/usr','ucblib')):
583      try:
584        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
585      except AttributeError:
586        flag = None
587      if flag is None:
588        self.compilers.LIBS += ' -L/usr/ucblib'
589      else:
590        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
591    return
592
593  def configureLinux(self):
594    '''Linux specific stuff'''
595    # TODO: Test for this by mallocing an odd number of floats and checking the address
596    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
597    return
598
599  def configureWin32(self):
600    '''Win32 non-cygwin specific stuff'''
601    kernel32=0
602    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
603      self.addDefine('HAVE_WINDOWS_H',1)
604      self.addDefine('HAVE_GETCOMPUTERNAME',1)
605      kernel32=1
606    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
607      self.addDefine('HAVE_WINDOWS_H',1)
608      self.addDefine('HAVE_GETCOMPUTERNAME',1)
609      kernel32=1
610    if kernel32:
611      if self.framework.argDB['with-windows-graphics']:
612        self.addDefine('USE_WINDOWS_GRAPHICS',1)
613      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
614        self.addDefine('HAVE_LOADLIBRARY',1)
615      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
616        self.addDefine('HAVE_GETPROCADDRESS',1)
617      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
618        self.addDefine('HAVE_FREELIBRARY',1)
619      if self.checkLink('#include <Windows.h>','GetLastError()'):
620        self.addDefine('HAVE_GETLASTERROR',1)
621      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
622        self.addDefine('HAVE_SETLASTERROR',1)
623      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
624        self.addDefine('USE_NT_TIME',1)
625    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
626      self.addDefine('HAVE_GET_USER_NAME',1)
627    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
628      self.addDefine('HAVE_GET_USER_NAME',1)
629
630    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
631      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
632    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
633      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
634
635    self.types.check('int32_t', 'int')
636    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
637      self.addTypedef('int', 'uid_t')
638      self.addTypedef('int', 'gid_t')
639    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
640      self.framework.addDefine('R_OK', '04')
641      self.framework.addDefine('W_OK', '02')
642      self.framework.addDefine('X_OK', '01')
643    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
644      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
645      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
646    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
647      self.addDefine('HAVE_LARGE_INTEGER_U',1)
648
649    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
650    if self.checkCompile('#include <Windows.h>\n', 'int flags = O_BINARY;'):
651      self.addDefine('HAVE_O_BINARY',1)
652
653    if self.compilers.CC.find('win32fe') >= 0:
654      self.addDefine('PATH_SEPARATOR','\';\'')
655      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
656      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
657      self.addDefine('CANNOT_START_DEBUGGER',1)
658    else:
659      self.addDefine('PATH_SEPARATOR','\':\'')
660      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
661      self.addDefine('DIR_SEPARATOR','\'/\'')
662    return
663
664#-----------------------------------------------------------------------------------------------------
665  def configureDefaultArch(self):
666    conffile = os.path.join('conf', 'petscvariables')
667    if self.framework.argDB['with-default-arch']:
668      fd = file(conffile, 'w')
669      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
670      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
671      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
672      fd.close()
673      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
674    elif os.path.isfile(conffile):
675      try:
676        os.unlink(conffile)
677      except:
678        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
679    return
680
681#-----------------------------------------------------------------------------------------------------
682  def configureScript(self):
683    '''Output a script in the conf directory which will reproduce the configuration'''
684    import nargs
685    import sys
686    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
687    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
688    if 'configModules' in args:
689      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
690        del args['configModules']
691    if 'optionsModule' in args:
692      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
693        del args['optionsModule']
694    if not 'PETSC_ARCH' in args:
695      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
696    f = file(scriptName, 'w')
697    f.write('#!'+sys.executable+'\n')
698    f.write('if __name__ == \'__main__\':\n')
699    f.write('  import sys\n')
700    f.write('  import os\n')
701    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
702    f.write('  import configure\n')
703    # pretty print repr(args.values())
704    f.write('  configure_options = [\n')
705    for itm in sorted(args.values()):
706      f.write('    \''+str(itm)+'\',\n')
707    f.write('  ]\n')
708    f.write('  configure.petsc_configure(configure_options)\n')
709    f.close()
710    try:
711      os.chmod(scriptName, 0775)
712    except OSError, e:
713      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
714    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
715    return
716
717  def configureInstall(self):
718    '''Setup the directories for installation'''
719    if self.framework.argDB['prefix']:
720      self.installdir = self.framework.argDB['prefix']
721      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
722                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
723                                              '-@echo "========================================="'])
724    else:
725      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
726      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
727                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
728                                              '-@echo "========================================="'])
729      return
730
731  def configureGCOV(self):
732    if self.framework.argDB['with-gcov']:
733      self.addDefine('USE_GCOV','1')
734    return
735
736  def configureFortranFlush(self):
737    if hasattr(self.compilers, 'FC'):
738      for baseName in ['flush','flush_']:
739        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
740          self.addDefine('HAVE_'+baseName.upper(), 1)
741          return
742
743
744  def configure(self):
745    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
746      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
747    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
748      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
749    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)):
750      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
751    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
752    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
753    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
754    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
755    if self.libraries.math is None:
756      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
757    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
758      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
759    self.executeTest(self.configureInline)
760    self.executeTest(self.configurePrefetch)
761    self.executeTest(self.configureUnused)
762    self.executeTest(self.configureExpect);
763    self.executeTest(self.configureFunctionName);
764    self.executeTest(self.configureIntptrt);
765    self.executeTest(self.configureSolaris)
766    self.executeTest(self.configureLinux)
767    self.executeTest(self.configureWin32)
768    self.executeTest(self.configureDefaultArch)
769    self.executeTest(self.configureScript)
770    self.executeTest(self.configureInstall)
771    self.executeTest(self.configureGCOV)
772    self.executeTest(self.configureFortranFlush)
773    # dummy rules, always needed except for remote builds
774    self.addMakeRule('remote','')
775    self.addMakeRule('remoteclean','')
776
777    self.Dump()
778    self.dumpConfigInfo()
779    self.dumpMachineInfo()
780    self.dumpCMakeConfig()
781    self.dumpCMakeLists()
782    self.cmakeBoot()
783    self.framework.log.write('================================================================================\n')
784    self.logClear()
785    return
786