xref: /petsc/config/PETSc/Configure.py (revision 23e93537c7d0035e7d10ad65699f8345bcb44266)
1import config.base
2
3import os
4import re
5
6class Configure(config.base.Configure):
7  def __init__(self, framework):
8    config.base.Configure.__init__(self, framework)
9    self.headerPrefix = 'PETSC'
10    self.substPrefix  = 'PETSC'
11    self.defineAutoconfMacros()
12    return
13
14  def __str2__(self):
15    desc = []
16    desc.append('xxx=========================================================================xxx')
17    desc.append('   Configure stage complete. Now build PETSc libraries with:')
18    desc.append('   make PETSC_DIR='+self.petscdir.dir+' PETSC_ARCH='+self.arch.arch+' all')
19    desc.append('xxx=========================================================================xxx')
20    return '\n'.join(desc)+'\n'
21
22  def setupHelp(self, help):
23    import nargs
24    help.addArgument('PETSc',  '-prefix=<dir>',                  nargs.Arg(None, '', 'Specifiy location to install PETSc (eg. /usr/local)'))
25    help.addArgument('Windows','-with-windows-graphics=<bool>',   nargs.ArgBool(None, 1,'Enable check for Windows Graphics'))
26    help.addArgument('PETSc', '-with-default-arch=<bool>',        nargs.ArgBool(None, 1, 'Allow using the last configured arch without setting PETSC_ARCH'))
27    help.addArgument('PETSc','-with-single-library=<bool>',       nargs.ArgBool(None, 1,'Put all PETSc code into the single -lpetsc library'))
28    help.addArgument('PETSc', '-with-iphone=<bool>',              nargs.ArgBool(None, 0, 'Build an iPhone version of PETSc'))
29    return
30
31  def setupDependencies(self, framework):
32    config.base.Configure.setupDependencies(self, framework)
33    self.setCompilers  = framework.require('config.setCompilers',      self)
34    self.arch          = framework.require('PETSc.utilities.arch',     self.setCompilers)
35    self.petscdir      = framework.require('PETSc.utilities.petscdir', self.setCompilers)
36    self.languages     = framework.require('PETSc.utilities.languages',self.setCompilers)
37    self.debugging     = framework.require('PETSc.utilities.debugging',self.setCompilers)
38    self.make          = framework.require('PETSc.utilities.Make',     self)
39    self.CHUD          = framework.require('PETSc.utilities.CHUD',     self)
40    self.compilers     = framework.require('config.compilers',         self)
41    self.types         = framework.require('config.types',             self)
42    self.headers       = framework.require('config.headers',           self)
43    self.functions     = framework.require('config.functions',         self)
44    self.libraries     = framework.require('config.libraries',         self)
45    if os.path.isdir(os.path.join('config', 'PETSc')):
46      for d in ['utilities', 'packages']:
47        for utility in os.listdir(os.path.join('config', 'PETSc', d)):
48          (utilityName, ext) = os.path.splitext(utility)
49          if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__':
50            utilityObj                    = self.framework.require('PETSc.'+d+'.'+utilityName, self)
51            utilityObj.headerPrefix       = self.headerPrefix
52            utilityObj.archProvider       = self.arch
53            utilityObj.languageProvider   = self.languages
54            utilityObj.installDirProvider = self.petscdir
55            setattr(self, utilityName.lower(), utilityObj)
56    self.qd    = framework.require('PETSc.packages.qd', self)
57    self.qd.archProvider      = self.arch
58    self.qd.precisionProvider = self.scalartypes
59    self.qd.installDirProvider= self.petscdir
60
61    for package in config.packages.all:
62      if not package == 'PETSc':
63        packageObj                    = framework.require('config.packages.'+package, self)
64        packageObj.archProvider       = self.arch
65        packageObj.languageProvider   = self.languages
66        packageObj.installDirProvider = self.petscdir
67        setattr(self, package.lower(), packageObj)
68    # Force blaslapack to depend on scalarType so precision is set before BlasLapack is built
69    framework.require('PETSc.utilities.scalarTypes', self.blaslapack)
70    self.blaslapack.precisionProvider = self.scalartypes
71
72    self.compilers.headerPrefix  = self.headerPrefix
73    self.types.headerPrefix      = self.headerPrefix
74    self.headers.headerPrefix    = self.headerPrefix
75    self.functions.headerPrefix  = self.headerPrefix
76    self.libraries.headerPrefix  = self.headerPrefix
77    self.blaslapack.headerPrefix = self.headerPrefix
78    self.mpi.headerPrefix        = self.headerPrefix
79    headersC = map(lambda name: name+'.h', ['dos', 'endian', 'fcntl', 'float', 'io', 'limits', 'malloc', 'pwd', 'search', 'strings',
80                                            'unistd', 'machine/endian', 'sys/param', 'sys/procfs', 'sys/resource',
81                                            'sys/systeminfo', 'sys/times', 'sys/utsname','string', 'stdlib','memory',
82                                            'sys/socket','sys/wait','netinet/in','netdb','Direct','time','Ws2tcpip','sys/types',
83                                            'WindowsX', 'cxxabi','float','ieeefp','stdint','fenv'])
84    functions = ['access', '_access', 'clock', 'drand48', 'getcwd', '_getcwd', 'getdomainname', 'gethostname', 'getpwuid',
85                 'gettimeofday', 'getwd', 'memalign', 'memmove', 'mkstemp', 'popen', 'PXFGETARG', 'rand', 'getpagesize',
86                 'readlink', 'realpath',  'sigaction', 'signal', 'sigset', 'nanosleep', 'usleep', 'sleep', '_sleep', 'socket',
87                 'times', 'gethostbyname', 'uname','snprintf','_snprintf','_fullpath','lseek','_lseek','time','fork','stricmp',
88                 'strcasecmp', 'bzero', 'dlopen', 'dlsym', 'dlclose', 'dlerror',
89                 '_intel_fast_memcpy','_intel_fast_memset']
90    libraries1 = [(['socket', 'nsl'], 'socket'), (['fpe'], 'handle_sigfpes')]
91    self.headers.headers.extend(headersC)
92    self.functions.functions.extend(functions)
93    self.libraries.libraries.extend(libraries1)
94    return
95
96  def defineAutoconfMacros(self):
97    self.hostMacro = 'dnl Version: 2.13\ndnl Variable: host_cpu\ndnl Variable: host_vendor\ndnl Variable: host_os\nAC_CANONICAL_HOST'
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.isCray('CC'):
205      self.addDefine('HAVE_CRAYC','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    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)
229    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
230    self.addMakeMacro('PETSC_CC_INCLUDES',self.headers.toStringNoDupes(includes))
231    self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(includes)
232    if hasattr(self.compilers, 'FC'):
233      if self.compilers.fortranIsF90:
234        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringModulesNoDupes(includes))
235
236    self.addMakeMacro('DESTDIR',self.installdir)
237    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir,'lib')+'"')
238
239    if self.framework.argDB['with-single-library']:
240      # overrides the values set in conf/variables
241      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
242      self.addMakeMacro('PETSC_SYS_LIB_BASIC','-lpetsc')
243      self.addMakeMacro('PETSC_VEC_LIB_BASIC','-lpetsc')
244      self.addMakeMacro('PETSC_MAT_LIB_BASIC','-lpetsc')
245      self.addMakeMacro('PETSC_DM_LIB_BASIC','-lpetsc')
246      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
247      self.addMakeMacro('PETSC_SNES_LIB_BASIC','-lpetsc')
248      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
249      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
250      self.addMakeMacro('PETSC_CONTRIB_BASIC','-lpetsc')
251      self.addMakeMacro('SHLIBS','libpetsc')
252      self.addDefine('USE_SINGLE_LIBRARY', '1')
253
254    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
255      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
256
257    # add a makefile entry for configure options
258    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
259    return
260
261  def dumpConfigInfo(self):
262    import time
263    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
264    fd.write('static const char *petscconfigureruntime = "'+time.ctime(time.time())+'";\n')
265    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
266    fd.close()
267    return
268
269  def dumpMachineInfo(self):
270    import platform
271    import time
272    import script
273    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
274    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
275    fd.write('\"-----------------------------------------\\n\"\n')
276    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
277    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
278    fd.write('\"Using PETSc directory: %s\\n\"\n' % (self.petscdir.dir))
279    fd.write('\"Using PETSc arch: %s\\n\"\n' % (self.arch.arch))
280    fd.write('\"-----------------------------------------\\n\";\n')
281    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
282    self.setCompilers.pushLanguage(self.languages.clanguage)
283    fd.write('\"Using C compiler: %s %s ${COPTFLAGS} ${CFLAGS}\\n\"\n' % (self.setCompilers.getCompiler(), self.setCompilers.getCompilerFlags()))
284    self.setCompilers.popLanguage()
285    if hasattr(self.compilers, 'FC'):
286      self.setCompilers.pushLanguage('FC')
287      fd.write('\"Using Fortran compiler: %s %s ${FOPTFLAGS} ${FFLAGS} %s\\n\"\n' % (self.setCompilers.getCompiler(), self.setCompilers.getCompilerFlags(), self.setCompilers.CPPFLAGS))
288      self.setCompilers.popLanguage()
289    fd.write('\"-----------------------------------------\\n\";\n')
290    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
291    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))
292    fd.write('\"-----------------------------------------\\n\";\n')
293    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
294    self.setCompilers.pushLanguage(self.languages.clanguage)
295    fd.write('\"Using C linker: %s\\n\"\n' % (self.setCompilers.getLinker()))
296    self.setCompilers.popLanguage()
297    if hasattr(self.compilers, 'FC'):
298      self.setCompilers.pushLanguage('FC')
299      fd.write('\"Using Fortran linker: %s\\n\"\n' % (self.setCompilers.getLinker()))
300      self.setCompilers.popLanguage()
301    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))
302    fd.write('\"-----------------------------------------\\n\";\n')
303    fd.close()
304    return
305
306  def dumpCMakeConfig(self):
307    '''
308    Writes configuration-specific values to ${PETSC_ARCH}/conf/PETScConfig.cmake.
309    This file is private to PETSc and should not be included by third parties
310    (a suitable file can be produced later by CMake, but this is not it).
311    '''
312    def cmakeset(fd,key,val=True):
313      if val == True: val = 'YES'
314      if val == False: val = 'NO'
315      fd.write('set (' + key + ' ' + val + ')\n')
316    def ensurelist(a):
317      if isinstance(a,list):
318        return a
319      else:
320        return [a]
321    def libpath(lib):
322      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
323      if lib.startswith('-L'): return lib[2:]
324      if lib.startswith('-R'): return lib[2:]
325      if lib.startswith('-Wl,-rpath,'):
326        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
327        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
328        # corresponding library.
329        return lib[len('-Wl,-rpath,'):]
330      if lib.startswith('-'): return ''
331      return os.path.dirname(lib)
332    def cleanlib(lib):
333      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
334      if lib.startswith('-l'):  return lib[2:]
335      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
336      lib = os.path.splitext(os.path.basename(lib))[0]
337      if lib.startswith('lib'): return lib[3:]
338      return lib
339    def nub(lst):
340      unique = []
341      for elem in lst:
342        if elem not in unique and elem != '':
343          unique.append(elem)
344      return unique
345    def cmakeexpand(varname):
346      return r'"${' + varname + r'}"'
347    def uniqextend(list,new):
348      for x in ensurelist(new):
349        if x not in list:
350          list.append(x)
351    def notstandardinclude(path):
352      return path not in '/usr/include /usr/local/include'.split()
353    def writeMacroDefinitions(fd):
354      if self.mpi.usingMPIUni:
355        cmakeset(fd,'PETSC_HAVE_MPIUNI')
356      for pkg in self.framework.packages:
357        if pkg.useddirectly:
358          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE)
359      for name,val in self.functions.defines.items():
360        cmakeset(fd,'PETSC_'+name,val)
361      for dct in [self.defines, self.libraryoptions.defines]:
362        for k,v in dct.items():
363          if k.startswith('USE_'):
364            cmakeset(fd,'PETSC_' + k, v)
365      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
366      cmakeset(fd,'PETSC_USE_SCALAR_' + self.scalartypes.precision.upper())
367      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
368      if hasattr(self.compilers, 'FC'):
369        cmakeset(fd,'PETSC_HAVE_FORTRAN')
370        if self.compilers.fortranIsF90:
371          cmakeset(fd,'PETSC_USING_F90')
372      if self.sharedlibraries.useShared:
373        cmakeset(fd,'BUILD_SHARED_LIBS')
374    def writeBuildFlags(fd):
375      lib_paths = []
376      lib_libs  = []
377      includes  = []
378      libvars   = []
379      for pkg in self.framework.packages:
380        libs = ensurelist(pkg.lib)
381        lib_paths.extend(map(libpath,libs))
382        lib_libs.extend(map(cleanlib,libs))
383        uniqextend(includes,pkg.include)
384      if self.libraries.math: lib_libs.extend(map(cleanlib,self.libraries.math))
385      if self.libraries.rt: lib_libs.extend(map(cleanlib,self.libraries.rt))
386      for libname in nub(lib_libs):
387        libvar = 'PETSC_' + libname.upper() + '_LIB'
388        addpath = ''
389        for lpath in nub(lib_paths):
390          addpath += '"' + str(lpath) + '" '
391        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
392        libvars.append(libvar)
393      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
394      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
395      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',filter(notstandardinclude,includes))) + ')\n')
396    fd = open(os.path.join(self.arch.arch,'conf','PETScConfig.cmake'), 'w')
397    writeMacroDefinitions(fd)
398    writeBuildFlags(fd)
399    fd.close()
400    return
401
402  def dumpCMakeLists(self):
403    import sys
404    if sys.version_info >= (2,5):
405      import cmakegen
406      try:
407        cmakegen.main(self.petscdir.dir)
408      except (OSError), e:
409        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
410
411  def cmakeBoot(self):
412    import sys
413    if sys.version_info >= (2,5) and hasattr(self.cmake,'cmake'):
414      try:
415        import cmakeboot
416        cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,logPrint=self.framework.logPrint)
417      except (OSError), e:
418        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
419      except (ImportError, KeyError), e:
420        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
421    return
422
423  def configurePrefetch(self):
424    '''Sees if there are any prefetch functions supported'''
425    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
426      self.addDefine('Prefetch(a,b,c)', ' ')
427      return
428    self.pushLanguage(self.languages.clanguage)
429    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
430      # The Intel Intrinsics manual [1] specifies the prototype
431      #
432      #   void _mm_prefetch(char const *a, int sel);
433      #
434      # but other vendors seem to insist on using subtly different
435      # prototypes, including void* for the pointer, and an enum for
436      # sel.  These are both reasonable changes, but negatively impact
437      # portability.
438      #
439      # [1] http://software.intel.com/file/6373
440      self.addDefine('HAVE_XMMINTRIN_H', 1)
441      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
442      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
443      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
444      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
445      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
446    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
447      self.addDefine('HAVE_XMMINTRIN_H', 1)
448      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
449      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
450      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
451      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
452      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
453    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
454      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
455      #
456      #   The value of rw is a compile-time constant one or zero; one
457      #   means that the prefetch is preparing for a write to the memory
458      #   address and zero, the default, means that the prefetch is
459      #   preparing for a read. The value locality must be a compile-time
460      #   constant integer between zero and three. A value of zero means
461      #   that the data has no temporal locality, so it need not be left
462      #   in the cache after the access. A value of three means that the
463      #   data has a high degree of temporal locality and should be left
464      #   in all levels of cache possible. Values of one and two mean,
465      #   respectively, a low or moderate degree of temporal locality.
466      #
467      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
468      # hints.  Using macros for these values in necessary since some
469      # compilers require an enum.
470      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
471      self.addDefine('PREFETCH_HINT_NTA', '0')
472      self.addDefine('PREFETCH_HINT_T0',  '3')
473      self.addDefine('PREFETCH_HINT_T1',  '2')
474      self.addDefine('PREFETCH_HINT_T2',  '1')
475    else:
476      self.addDefine('Prefetch(a,b,c)', ' ')
477    self.popLanguage()
478
479  def configureUnused(self):
480    '''Sees if __attribute((unused)) is supported'''
481    if self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
482      self.addDefine('UNUSED', ' ')
483      return
484    self.pushLanguage(self.languages.clanguage)
485    if self.checkLink('__attribute((unused)) static int myfunc(void){ return 1;}', 'int i = myfunc();\n'):
486      self.addDefine('UNUSED', '__attribute((unused))')
487    else:
488      self.addDefine('UNUSED', ' ')
489    self.popLanguage()
490
491  def configureExpect(self):
492    '''Sees if the __builtin_expect directive is supported'''
493    self.pushLanguage(self.languages.clanguage)
494    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
495      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
496    self.popLanguage()
497
498  def configureFunctionName(self):
499    '''Sees if the compiler supports __FUNCTION__ or a variant'''
500    self.pushLanguage(self.languages.clanguage)
501    if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
502      self.addDefine('FUNCTION_NAME', '__func__')
503    elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
504      self.addDefine('FUNCTION_NAME', '__FUNCTION__')
505    else:
506      self.addDefine('FUNCTION_NAME', '__FUNCT__')
507
508  def configureIntptrt(self):
509    '''Determine what to use for uintptr_t'''
510    def staticAssertSizeMatchesVoidStar(inc,typename):
511      # The declaration is an error if either array size is negative.
512      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
513      return self.checkCompile(inc, '#define SZ (sizeof(void*)-sizeof(%s))\nint type_is_too_large[SZ],type_is_too_small[-SZ];'%typename)
514    self.pushLanguage(self.languages.clanguage)
515    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
516      self.addDefine('UINTPTR_T', 'uintptr_t')
517    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
518      self.addDefine('UINTPTR_T', 'unsigned long long')
519    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
520      self.addDefine('UINTPTR_T', 'size_t')
521    elif staticAssertSizeMatchesVoidStar('','unsigned'):
522      self.addDefine('UINTPTR_T', 'unsigned')
523    self.popLanguage()
524
525  def configureInline(self):
526    '''Get a generic inline keyword, depending on the language'''
527    if self.languages.clanguage == 'C':
528      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
529      self.addDefine('RESTRICT', self.compilers.cRestrict)
530    elif self.languages.clanguage == 'Cxx':
531      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
532      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
533    return
534
535  def configureSolaris(self):
536    '''Solaris specific stuff'''
537    if self.arch.hostOsBase.startswith('solaris'):
538      if os.path.isdir(os.path.join('/usr','ucblib')):
539        try:
540          flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
541        except AttributeError:
542          flag = None
543        if flag is None:
544          self.compilers.LIBS += ' -L/usr/ucblib'
545        else:
546          self.compilers.LIBS += ' '+flag+'/usr/ucblib'
547    return
548
549  def configureLinux(self):
550    '''Linux specific stuff'''
551    if self.arch.hostOsBase == 'linux':
552      self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
553    return
554
555  def configureWin32(self):
556    '''Win32 non-cygwin specific stuff'''
557    kernel32=0
558    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
559      self.addDefine('HAVE_WINDOWS_H',1)
560      self.addDefine('HAVE_GETCOMPUTERNAME',1)
561      kernel32=1
562    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
563      self.addDefine('HAVE_WINDOWS_H',1)
564      self.addDefine('HAVE_GETCOMPUTERNAME',1)
565      kernel32=1
566    if kernel32:
567      if self.framework.argDB['with-windows-graphics']:
568        self.addDefine('USE_WINDOWS_GRAPHICS',1)
569      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
570        self.addDefine('HAVE_LOADLIBRARY',1)
571      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
572        self.addDefine('HAVE_GETPROCADDRESS',1)
573      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
574        self.addDefine('HAVE_FREELIBRARY',1)
575      if self.checkLink('#include <Windows.h>','GetLastError()'):
576        self.addDefine('HAVE_GETLASTERROR',1)
577      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
578        self.addDefine('HAVE_SETLASTERROR',1)
579      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
580        self.addDefine('USE_NT_TIME',1)
581    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
582      self.addDefine('HAVE_GET_USER_NAME',1)
583    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
584      self.addDefine('HAVE_GET_USER_NAME',1)
585
586    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
587      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
588    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
589      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
590
591    self.types.check('int32_t', 'int')
592    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
593      self.addTypedef('int', 'uid_t')
594      self.addTypedef('int', 'gid_t')
595    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
596      self.framework.addDefine('R_OK', '04')
597      self.framework.addDefine('W_OK', '02')
598      self.framework.addDefine('X_OK', '01')
599    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
600      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
601      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
602    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
603      self.addDefine('HAVE_LARGE_INTEGER_U',1)
604
605    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
606    if self.checkCompile('#include <Windows.h>\n',''):
607      self.addDefine('HAVE_O_BINARY',1)
608
609    if self.compilers.CC.find('win32fe') >= 0:
610      self.addDefine('PATH_SEPARATOR','\';\'')
611      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
612      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
613      self.addDefine('CANNOT_START_DEBUGGER',1)
614    else:
615      self.addDefine('PATH_SEPARATOR','\':\'')
616      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
617      self.addDefine('DIR_SEPARATOR','\'/\'')
618    return
619
620#-----------------------------------------------------------------------------------------------------
621  def configureDefaultArch(self):
622    conffile = os.path.join('conf', 'petscvariables')
623    if self.framework.argDB['with-default-arch']:
624      fd = file(conffile, 'w')
625      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
626      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
627      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
628      fd.close()
629      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
630    elif os.path.isfile(conffile):
631      try:
632        os.unlink(conffile)
633      except:
634        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
635    return
636
637#-----------------------------------------------------------------------------------------------------
638  def configureScript(self):
639    '''Output a script in the conf directory which will reproduce the configuration'''
640    import nargs
641    import sys
642    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
643    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
644    if 'configModules' in args:
645      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
646        del args['configModules']
647    if 'optionsModule' in args:
648      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
649        del args['optionsModule']
650    if not 'PETSC_ARCH' in args:
651      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
652    f = file(scriptName, 'w')
653    f.write('#!'+sys.executable+'\n')
654    f.write('if __name__ == \'__main__\':\n')
655    f.write('  import sys\n')
656    f.write('  import os\n')
657    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
658    f.write('  import configure\n')
659    # pretty print repr(args.values())
660    f.write('  configure_options = [\n')
661    for itm in args.values():
662      f.write('    \''+str(itm)+'\',\n')
663    f.write('  ]\n')
664    f.write('  configure.petsc_configure(configure_options)\n')
665    f.close()
666    try:
667      os.chmod(scriptName, 0775)
668    except OSError, e:
669      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
670    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
671    return
672
673  def configureInstall(self):
674    '''Setup the directories for installation'''
675    if self.framework.argDB['prefix']:
676      self.installdir = self.framework.argDB['prefix']
677      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
678                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
679                                              '-@echo "========================================="'])
680    else:
681      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
682      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
683                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
684                                              '-@echo "========================================="'])
685      return
686
687  def configureGCOV(self):
688    if self.framework.argDB['with-gcov']:
689      self.addDefine('USE_GCOV','1')
690    return
691
692  def configureFortranFlush(self):
693    if hasattr(self.compilers, 'FC'):
694      for baseName in ['flush','flush_']:
695        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
696          self.addDefine('HAVE_'+baseName.upper(), 1)
697          return
698
699
700  def configure(self):
701    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
702      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
703    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
704      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
705    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
706    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
707    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
708    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
709    if self.libraries.math is None:
710      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
711    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
712      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
713    self.executeTest(self.configureInline)
714    self.executeTest(self.configurePrefetch)
715    self.executeTest(self.configureUnused)
716    self.executeTest(self.configureExpect);
717    self.executeTest(self.configureFunctionName);
718    self.executeTest(self.configureIntptrt);
719    self.executeTest(self.configureSolaris)
720    self.executeTest(self.configureLinux)
721    self.executeTest(self.configureWin32)
722    self.executeTest(self.configureDefaultArch)
723    self.executeTest(self.configureScript)
724    self.executeTest(self.configureInstall)
725    self.executeTest(self.configureGCOV)
726    self.executeTest(self.configureFortranFlush)
727    # dummy rules, always needed except for remote builds
728    self.addMakeRule('remote','')
729    self.addMakeRule('remoteclean','')
730
731    self.Dump()
732    self.dumpConfigInfo()
733    self.dumpMachineInfo()
734    self.dumpCMakeConfig()
735    self.dumpCMakeLists()
736    self.cmakeBoot()
737    self.framework.log.write('================================================================================\n')
738    self.logClear()
739    return
740