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