xref: /petsc/config/PETSc/Configure.py (revision a36306386cafcfd646eca44e6635f8f93e2148e5)
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 configureFeatureTestMacros(self):
529    '''Checks if certain feature test macros are support'''
530    if self.checkCompile('#define _POSIX_C_SOURCE 200112L\n#include <stdlib.h>',''):
531       self.addDefine('_POSIX_C_SOURCE_200112L', '1')
532    if self.checkCompile('#define _BSD_SOURCE\n#include<stdlib.h>',''):
533       self.addDefine('_BSD_SOURCE', '1')
534
535  def configureAtoll(self):
536    '''Checks if atoll exists'''
537    if self.checkCompile('#define _POSIX_C_SOURCE 200112L\n#include <stdlib.h>','long v = atoll("25")') or self.checkCompile ('#include <stdlib.h>','long v = atoll("25")'):
538       self.addDefine('HAVE_ATOLL', '1')
539
540  def configureUnused(self):
541    '''Sees if __attribute((unused)) is supported'''
542    if self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
543      self.addDefine('UNUSED', ' ')
544      return
545    self.pushLanguage(self.languages.clanguage)
546    if self.checkLink('__attribute((unused)) static int myfunc(void){ return 1;}', 'int i = myfunc();\n'):
547      self.addDefine('UNUSED', '__attribute((unused))')
548    else:
549      self.addDefine('UNUSED', ' ')
550    self.popLanguage()
551
552  def configureExpect(self):
553    '''Sees if the __builtin_expect directive is supported'''
554    self.pushLanguage(self.languages.clanguage)
555    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
556      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
557    self.popLanguage()
558
559  def configureFunctionName(self):
560    '''Sees if the compiler supports __func__ or a variant.  Falls back
561    on __FUNCT__ which PETSc source defines, but most users do not, thus
562    stack traces through user code are better when the compiler's
563    variant is used.'''
564    def getFunctionName(lang):
565      name = '__FUNCT__'
566      self.pushLanguage(lang)
567      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
568        name = '__func__'
569      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
570        name = '__FUNCTION__'
571      self.popLanguage()
572      return name
573    langs = []
574
575    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
576    if hasattr(self.compilers, 'CXX'):
577      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
578    else:
579      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
580
581  def configureIntptrt(self):
582    '''Determine what to use for uintptr_t'''
583    def staticAssertSizeMatchesVoidStar(inc,typename):
584      # The declaration is an error if either array size is negative.
585      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
586      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
587                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
588    self.pushLanguage(self.languages.clanguage)
589    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
590      self.addDefine('UINTPTR_T', 'uintptr_t')
591    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
592      self.addDefine('UINTPTR_T', 'unsigned long long')
593    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
594      self.addDefine('UINTPTR_T', 'size_t')
595    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
596      self.addDefine('UINTPTR_T', 'unsigned long')
597    elif staticAssertSizeMatchesVoidStar('','unsigned'):
598      self.addDefine('UINTPTR_T', 'unsigned')
599    else:
600      raise RuntimeError('Could not find any unsigned integer type matching void*')
601    self.popLanguage()
602
603  def configureInline(self):
604    '''Get a generic inline keyword, depending on the language'''
605    if self.languages.clanguage == 'C':
606      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
607      self.addDefine('RESTRICT', self.compilers.cRestrict)
608    elif self.languages.clanguage == 'Cxx':
609      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
610      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
611
612    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
613      self.addDefine('RTLD_DEFAULT','1')
614    return
615
616  def configureSolaris(self):
617    '''Solaris specific stuff'''
618    if os.path.isdir(os.path.join('/usr','ucblib')):
619      try:
620        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
621      except AttributeError:
622        flag = None
623      if flag is None:
624        self.compilers.LIBS += ' -L/usr/ucblib'
625      else:
626        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
627    return
628
629  def configureLinux(self):
630    '''Linux specific stuff'''
631    # TODO: Test for this by mallocing an odd number of floats and checking the address
632    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
633    return
634
635  def configureWin32(self):
636    '''Win32 non-cygwin specific stuff'''
637    kernel32=0
638    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
639      self.addDefine('HAVE_WINDOWS_H',1)
640      self.addDefine('HAVE_GETCOMPUTERNAME',1)
641      kernel32=1
642    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
643      self.addDefine('HAVE_WINDOWS_H',1)
644      self.addDefine('HAVE_GETCOMPUTERNAME',1)
645      kernel32=1
646    if kernel32:
647      if self.framework.argDB['with-windows-graphics']:
648        self.addDefine('USE_WINDOWS_GRAPHICS',1)
649      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
650        self.addDefine('HAVE_LOADLIBRARY',1)
651      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
652        self.addDefine('HAVE_GETPROCADDRESS',1)
653      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
654        self.addDefine('HAVE_FREELIBRARY',1)
655      if self.checkLink('#include <Windows.h>','GetLastError()'):
656        self.addDefine('HAVE_GETLASTERROR',1)
657      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
658        self.addDefine('HAVE_SETLASTERROR',1)
659      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
660        self.addDefine('USE_NT_TIME',1)
661    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
662      self.addDefine('HAVE_GET_USER_NAME',1)
663    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
664      self.addDefine('HAVE_GET_USER_NAME',1)
665
666    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
667      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
668    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
669      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
670
671    self.types.check('int32_t', 'int')
672    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
673      self.addTypedef('int', 'uid_t')
674      self.addTypedef('int', 'gid_t')
675    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
676      self.framework.addDefine('R_OK', '04')
677      self.framework.addDefine('W_OK', '02')
678      self.framework.addDefine('X_OK', '01')
679    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
680      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
681      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
682    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
683      self.addDefine('HAVE_LARGE_INTEGER_U',1)
684
685    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
686    if self.checkCompile('#include <Windows.h>\n', 'int flags = O_BINARY;'):
687      self.addDefine('HAVE_O_BINARY',1)
688
689    if self.compilers.CC.find('win32fe') >= 0:
690      self.addDefine('PATH_SEPARATOR','\';\'')
691      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
692      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
693      self.addDefine('CANNOT_START_DEBUGGER',1)
694    else:
695      self.addDefine('PATH_SEPARATOR','\':\'')
696      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
697      self.addDefine('DIR_SEPARATOR','\'/\'')
698
699    return
700
701#-----------------------------------------------------------------------------------------------------
702  def configureDefaultArch(self):
703    conffile = os.path.join('conf', 'petscvariables')
704    if self.framework.argDB['with-default-arch']:
705      fd = file(conffile, 'w')
706      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
707      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
708      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
709      fd.close()
710      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
711    elif os.path.isfile(conffile):
712      try:
713        os.unlink(conffile)
714      except:
715        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
716    return
717
718#-----------------------------------------------------------------------------------------------------
719  def configureScript(self):
720    '''Output a script in the conf directory which will reproduce the configuration'''
721    import nargs
722    import sys
723    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
724    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
725    if 'configModules' in args:
726      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
727        del args['configModules']
728    if 'optionsModule' in args:
729      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
730        del args['optionsModule']
731    if not 'PETSC_ARCH' in args:
732      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
733    f = file(scriptName, 'w')
734    f.write('#!'+sys.executable+'\n')
735    f.write('if __name__ == \'__main__\':\n')
736    f.write('  import sys\n')
737    f.write('  import os\n')
738    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
739    f.write('  import configure\n')
740    # pretty print repr(args.values())
741    f.write('  configure_options = [\n')
742    for itm in sorted(args.values()):
743      f.write('    \''+str(itm)+'\',\n')
744    f.write('  ]\n')
745    f.write('  configure.petsc_configure(configure_options)\n')
746    f.close()
747    try:
748      os.chmod(scriptName, 0775)
749    except OSError, e:
750      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
751    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
752    return
753
754  def configureInstall(self):
755    '''Setup the directories for installation'''
756    if self.framework.argDB['prefix']:
757      self.installdir = self.framework.argDB['prefix']
758      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
759                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
760                                              '-@echo "========================================="'])
761    else:
762      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
763      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
764                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
765                                              '-@echo "========================================="'])
766      return
767
768  def configureGCOV(self):
769    if self.framework.argDB['with-gcov']:
770      self.addDefine('USE_GCOV','1')
771    return
772
773  def configureFortranFlush(self):
774    if hasattr(self.compilers, 'FC'):
775      for baseName in ['flush','flush_']:
776        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
777          self.addDefine('HAVE_'+baseName.upper(), 1)
778          return
779
780
781  def configure(self):
782    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
783      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
784    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
785      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
786    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)):
787      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
788    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
789    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
790    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
791    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
792    if self.libraries.math is None:
793      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
794    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
795      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
796    self.executeTest(self.configureInline)
797    self.executeTest(self.configurePrefetch)
798    self.executeTest(self.configureUnused)
799    self.executeTest(self.configureExpect);
800    self.executeTest(self.configureFunctionName);
801    self.executeTest(self.configureIntptrt);
802    self.executeTest(self.configureSolaris)
803    self.executeTest(self.configureLinux)
804    self.executeTest(self.configureWin32)
805    self.executeTest(self.configureDefaultArch)
806    self.executeTest(self.configureScript)
807    self.executeTest(self.configureInstall)
808    self.executeTest(self.configureGCOV)
809    self.executeTest(self.configureFortranFlush)
810    self.executeTest(self.configureFeatureTestMacros)
811    self.executeTest(self.configureAtoll)
812    # dummy rules, always needed except for remote builds
813    self.addMakeRule('remote','')
814    self.addMakeRule('remoteclean','')
815
816    self.Dump()
817    self.dumpConfigInfo()
818    self.dumpMachineInfo()
819    self.dumpCMakeConfig()
820    self.dumpCMakeLists()
821    self.cmakeBoot()
822    self.framework.log.write('================================================================================\n')
823    self.logClear()
824    return
825