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