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