xref: /petsc/config/PETSc/Configure.py (revision f3fe499b4cc4d64bf04aa4f5e4963dcc4eb56541)
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    self.addMakeMacro('PCC_LINKER_LIBS',self.libraries.toStringNoDupes(self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' '))+self.CHUD.LIBS)
130
131    if hasattr(self.compilers, 'FC'):
132      self.setCompilers.pushLanguage('FC')
133      # need FPPFLAGS in config/setCompilers
134      self.addDefine('HAVE_FORTRAN','1')
135      self.addMakeMacro('FPP_FLAGS',self.setCompilers.CPPFLAGS)
136
137      # compiler values
138      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
139      self.setCompilers.popLanguage()
140      # .o or .obj
141      self.addMakeMacro('FC_SUFFIX','o')
142
143      # executable linker values
144      self.setCompilers.pushLanguage('FC')
145      # Cannot have NAG f90 as the linker - so use pcc_linker as fc_linker
146      fc_linker = self.setCompilers.getLinker()
147      if config.setCompilers.Configure.isNAG(fc_linker):
148        self.addMakeMacro('FC_LINKER',pcc_linker)
149      else:
150        self.addMakeMacro('FC_LINKER',fc_linker)
151      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
152      # apple requires this shared library linker flag on SOME versions of the os
153      if self.setCompilers.getLinkerFlags().find('-Wl,-commons,use_dylibs') > -1:
154        self.addMakeMacro('DARWIN_COMMONS_USE_DYLIBS',' -Wl,-commons,use_dylibs ')
155      self.setCompilers.popLanguage()
156
157      # F90 Modules
158      if self.setCompilers.fortranModuleIncludeFlag:
159        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
160      else: # for non-f90 compilers like g77
161        self.addMakeMacro('FC_MODULE_FLAG', '-I')
162      if self.setCompilers.fortranModuleIncludeFlag:
163        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
164    else:
165      self.addMakeMacro('FC','')
166
167    # shared library linker values
168    self.setCompilers.pushLanguage(self.languages.clanguage)
169    # need to fix BuildSystem to collect these separately
170    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
171    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
172    self.setCompilers.popLanguage()
173    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
174    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
175    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
176      self.addMakeMacro('SL_LINKER_SUFFIX', '')
177      self.addDefine('SLSUFFIX','""')
178    else:
179      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
180      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
181
182    #SL_LINKER_LIBS is currently same as PCC_LINKER_LIBS - so simplify
183    self.addMakeMacro('SL_LINKER_LIBS','${PCC_LINKER_LIBS}')
184    #self.addMakeMacro('SL_LINKER_LIBS',self.libraries.toStringNoDupes(self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' ')))
185
186#-----------------------------------------------------------------------------------------------------
187
188    # CONLY or CPP. We should change the PETSc makefiles to do this better
189    if self.languages.clanguage == 'C': lang = 'CONLY'
190    else: lang = 'CXXONLY'
191    self.addMakeMacro('PETSC_LANGUAGE',lang)
192
193    # real or complex
194    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
195    # double or float
196    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
197
198    if self.framework.argDB['with-batch']:
199      self.addMakeMacro('PETSC_WITH_BATCH','1')
200
201    # Test for compiler-specific macros that need to be defined.
202    if self.setCompilers.isCray('CC'):
203      self.addDefine('HAVE_CRAYC','1')
204
205#-----------------------------------------------------------------------------------------------------
206    if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket'):
207      self.addDefine('USE_SOCKET_VIEWER','1')
208
209#-----------------------------------------------------------------------------------------------------
210    # print include and lib for external packages
211    self.framework.packages.reverse()
212    includes = []
213    libs = []
214    for i in self.framework.packages:
215      if i.useddirectly:
216        self.addDefine('HAVE_'+i.PACKAGE, 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
217      if not isinstance(i.lib, list):
218        i.lib = [i.lib]
219      libs.extend(i.lib)
220      self.addMakeMacro(i.PACKAGE+'_LIB', self.libraries.toStringNoDupes(i.lib))
221      if hasattr(i,'include'):
222        if not isinstance(i.include,list):
223          i.include = [i.include]
224        includes.extend(i.include)
225        self.addMakeMacro(i.PACKAGE+'_INCLUDE',self.headers.toStringNoDupes(i.include))
226    self.addMakeMacro('PACKAGES_LIBS',self.libraries.toStringNoDupes(libs+self.libraries.math))
227    self.PACKAGES_LIBS = self.libraries.toStringNoDupes(libs+self.libraries.math)
228    self.addMakeMacro('PACKAGES_INCLUDES',self.headers.toStringNoDupes(includes))
229    self.PACKAGES_INCLUDES = self.headers.toStringNoDupes(includes)
230    if hasattr(self.compilers, 'FC'):
231      if self.compilers.fortranIsF90:
232        self.addMakeMacro('PACKAGES_MODULES_INCLUDES',self.headers.toStringModulesNoDupes(includes))
233
234    self.addMakeMacro('DESTDIR',self.installdir)
235    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir,'lib')+'"')
236
237    if self.framework.argDB['with-single-library']:
238      # overrides the values set in conf/variables
239      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
240      self.addMakeMacro('PETSC_SYS_LIB_BASIC','-lpetsc')
241      self.addMakeMacro('PETSC_VEC_LIB_BASIC','-lpetsc')
242      self.addMakeMacro('PETSC_MAT_LIB_BASIC','-lpetsc')
243      self.addMakeMacro('PETSC_DM_LIB_BASIC','-lpetsc')
244      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
245      self.addMakeMacro('PETSC_SNES_LIB_BASIC','-lpetsc')
246      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
247      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
248      self.addMakeMacro('PETSC_CONTRIB_BASIC','-lpetsc')
249      self.addMakeMacro('SHLIBS','libpetsc')
250      self.addDefine('USE_SINGLE_LIBRARY', '1')
251
252    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
253      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
254
255    # add a makefile entry for configure options
256    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
257    return
258
259  def dumpConfigInfo(self):
260    import time
261    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
262    fd.write('static const char *petscconfigureruntime = "'+time.ctime(time.time())+'";\n')
263    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
264    fd.close()
265    return
266
267  def dumpMachineInfo(self):
268    import platform
269    import time
270    import script
271    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
272    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
273    fd.write('\"-----------------------------------------\\n\"\n')
274    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
275    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
276    fd.write('\"Using PETSc directory: %s\\n\"\n' % (self.petscdir.dir))
277    fd.write('\"Using PETSc arch: %s\\n\"\n' % (self.arch.arch))
278    fd.write('\"-----------------------------------------\\n\";\n')
279    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
280    self.setCompilers.pushLanguage(self.languages.clanguage)
281    fd.write('\"Using C compiler: %s %s ${COPTFLAGS} ${CFLAGS}\\n\"\n' % (self.setCompilers.getCompiler(), self.setCompilers.getCompilerFlags()))
282    self.setCompilers.popLanguage()
283    if hasattr(self.compilers, 'FC'):
284      self.setCompilers.pushLanguage('FC')
285      fd.write('\"Using Fortran compiler: %s %s ${FOPTFLAGS} ${FFLAGS} %s\\n\"\n' % (self.setCompilers.getCompiler(), self.setCompilers.getCompilerFlags(), self.setCompilers.CPPFLAGS))
286      self.setCompilers.popLanguage()
287    fd.write('\"-----------------------------------------\\n\";\n')
288    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
289    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.PACKAGES_INCLUDES))
290    fd.write('\"-----------------------------------------\\n\";\n')
291    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
292    self.setCompilers.pushLanguage(self.languages.clanguage)
293    fd.write('\"Using C linker: %s\\n\"\n' % (self.setCompilers.getLinker()))
294    self.setCompilers.popLanguage()
295    if hasattr(self.compilers, 'FC'):
296      self.setCompilers.pushLanguage('FC')
297      fd.write('\"Using Fortran linker: %s\\n\"\n' % (self.setCompilers.getLinker()))
298      self.setCompilers.popLanguage()
299    fd.write('\"Using libraries: %s%s -L%s %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.PACKAGES_LIBS, self.libraries.toStringNoDupes(self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' '))+self.CHUD.LIBS))
300    fd.write('\"-----------------------------------------\\n\";\n')
301    fd.close()
302    return
303
304  def dumpCMakeConfig(self):
305    '''
306    Writes configuration-specific values to ${PETSC_ARCH}/conf/PETScConfig.cmake.
307    This file is private to PETSc and should not be included by third parties
308    (a suitable file can be produced later by CMake, but this is not it).
309    '''
310    def cmakeset(fd,key,val=True):
311      if val == True: val = 'YES'
312      if val == False: val = 'NO'
313      fd.write('set (' + key + ' ' + val + ')\n')
314    def ensurelist(a):
315      if isinstance(a,list):
316        return a
317      else:
318        return [a]
319    def libpath(lib):
320      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
321      if lib.startswith('-L'): return lib[2:]
322      if lib.startswith('-R'): return lib[2:]
323      if lib.startswith('-Wl,-rpath,'):
324        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
325        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
326        # corresponding library.
327        return lib[len('-Wl,-rpath,'):]
328      if lib.startswith('-'): return ''
329      return os.path.dirname(lib)
330    def cleanlib(lib):
331      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
332      if lib.startswith('-l'):  return lib[2:]
333      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
334      lib = os.path.splitext(os.path.basename(lib))[0]
335      if lib.startswith('lib'): return lib[3:]
336      return lib
337    def nub(lst):
338      unique = []
339      for elem in lst:
340        if elem not in unique and elem != '':
341          unique.append(elem)
342      return unique
343    def cmakeexpand(varname):
344      return r'"${' + varname + r'}"'
345    def uniqextend(list,new):
346      for x in ensurelist(new):
347        if x not in list:
348          list.append(x)
349    def notstandardinclude(path):
350      return path not in '/usr/include /usr/local/include'.split()
351    def writeMacroDefinitions(fd):
352      if self.mpi.usingMPIUni:
353        cmakeset(fd,'PETSC_HAVE_MPIUNI')
354      for pkg in self.framework.packages:
355        if pkg.useddirectly:
356          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE)
357      for name,val in self.functions.defines.items():
358        cmakeset(fd,'PETSC_'+name,val)
359      for dct in [self.defines, self.libraryoptions.defines]:
360        for k,v in dct.items():
361          if k.startswith('USE_'):
362            cmakeset(fd,'PETSC_' + k, v)
363      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
364      cmakeset(fd,'PETSC_USE_SCALAR_' + self.scalartypes.precision.upper())
365      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
366      if hasattr(self.compilers, 'FC'):
367        cmakeset(fd,'PETSC_HAVE_FORTRAN')
368        if self.compilers.fortranIsF90:
369          cmakeset(fd,'PETSC_USING_F90')
370      if self.sharedlibraries.useShared:
371        cmakeset(fd,'BUILD_SHARED_LIBS')
372    def writeBuildFlags(fd):
373      lib_paths = []
374      lib_libs  = []
375      includes  = []
376      libvars   = []
377      for pkg in self.framework.packages:
378        libs = ensurelist(pkg.lib)
379        lib_paths.extend(map(libpath,libs))
380        lib_libs.extend(map(cleanlib,libs))
381        uniqextend(includes,pkg.include)
382      if self.libraries.math: lib_libs.extend(map(cleanlib,self.libraries.math))
383      if self.libraries.rt: lib_libs.extend(map(cleanlib,self.libraries.rt))
384      for libname in nub(lib_libs):
385        libvar = 'PETSC_' + libname.upper() + '_LIB'
386        addpath = ''
387        for lpath in nub(lib_paths):
388          addpath += '"' + str(lpath) + '" '
389        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
390        libvars.append(libvar)
391      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
392      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
393      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',filter(notstandardinclude,includes))) + ')\n')
394    fd = open(os.path.join(self.arch.arch,'conf','PETScConfig.cmake'), 'w')
395    writeMacroDefinitions(fd)
396    writeBuildFlags(fd)
397    fd.close()
398    return
399
400  def dumpCMakeLists(self):
401    import sys
402    if sys.version_info >= (2,5):
403      sys.path.insert(0,os.path.join(self.petscdir.dir,'bin','maint'))
404      import cmakegen
405      del sys.path[0]
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      sys.path.insert(0,os.path.join(self.petscdir.dir,'bin','maint'))
415      import cmakeboot
416      del sys.path[0]
417      try:
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
422  def configurePrefetch(self):
423    '''Sees if there are any prefetch functions supported'''
424    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
425      self.addDefine('Prefetch(a,b,c)', ' ')
426      return
427    self.pushLanguage(self.languages.clanguage)
428    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,(int)0);\n'):
429      self.addDefine('HAVE_XMMINTRIN_H', 1)
430      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(int)(c))')
431    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,(int)0);\n'):
432      self.addDefine('HAVE_XMMINTRIN_H', 1)
433      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(int)(c))')
434    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
435      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
436    else:
437      self.addDefine('Prefetch(a,b,c)', ' ')
438    self.popLanguage()
439
440  def configureUnused(self):
441    '''Sees if __attribute((unused)) is supported'''
442    if self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
443      self.addDefine('UNUSED', ' ')
444      return
445    self.pushLanguage(self.languages.clanguage)
446    if self.checkLink('__attribute((unused)) static int myfunc(void){ return 1;}', 'int i = myfunc();\n'):
447      self.addDefine('UNUSED', '__attribute((unused))')
448    else:
449      self.addDefine('UNUSED', ' ')
450    self.popLanguage()
451
452  def configureExpect(self):
453    '''Sees if the __builtin_expect directive is supported'''
454    self.pushLanguage(self.languages.clanguage)
455    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
456      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
457    self.popLanguage()
458
459  def configureIntptrt(self):
460    '''Determine what to use for uintptr_t'''
461    def staticAssertSizeMatchesVoidStar(inc,typename):
462      # The declaration is an error if either array size is negative.
463      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
464      return self.checkCompile(inc, '#define SZ (sizeof(void*)-sizeof(%s))\nint type_is_too_large[SZ],type_is_too_small[-SZ];'%typename)
465    self.pushLanguage(self.languages.clanguage)
466    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
467      self.addDefine('UINTPTR_T', 'uintptr_t')
468    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
469      self.addDefine('UINTPTR_T', 'unsigned long long')
470    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
471      self.addDefine('UINTPTR_T', 'size_t')
472    elif staticAssertSizeMatchesVoidStar('','unsigned'):
473      self.addDefine('UINTPTR_T', 'unsigned')
474    self.popLanguage()
475
476  def configureInline(self):
477    '''Get a generic inline keyword, depending on the language'''
478    if self.languages.clanguage == 'C':
479      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
480      self.addDefine('RESTRICT', self.compilers.cRestrict)
481    elif self.languages.clanguage == 'Cxx':
482      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
483      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
484    return
485
486  def configureSolaris(self):
487    '''Solaris specific stuff'''
488    if self.arch.hostOsBase.startswith('solaris'):
489      if os.path.isdir(os.path.join('/usr','ucblib')):
490        try:
491          flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
492        except AttributeError:
493          flag = None
494        if flag is None:
495          self.compilers.LIBS += ' -L/usr/ucblib'
496        else:
497          self.compilers.LIBS += ' '+flag+'/usr/ucblib'
498    return
499
500  def configureLinux(self):
501    '''Linux specific stuff'''
502    if self.arch.hostOsBase == 'linux':
503      self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
504    return
505
506  def configureWin32(self):
507    '''Win32 non-cygwin specific stuff'''
508    kernel32=0
509    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
510      self.addDefine('HAVE_WINDOWS_H',1)
511      self.addDefine('HAVE_GETCOMPUTERNAME',1)
512      kernel32=1
513    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
514      self.addDefine('HAVE_WINDOWS_H',1)
515      self.addDefine('HAVE_GETCOMPUTERNAME',1)
516      kernel32=1
517    if kernel32:
518      if self.framework.argDB['with-windows-graphics']:
519        self.addDefine('USE_WINDOWS_GRAPHICS',1)
520      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
521        self.addDefine('HAVE_LOADLIBRARY',1)
522      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
523        self.addDefine('HAVE_GETPROCADDRESS',1)
524      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
525        self.addDefine('HAVE_FREELIBRARY',1)
526      if self.checkLink('#include <Windows.h>','GetLastError()'):
527        self.addDefine('HAVE_GETLASTERROR',1)
528      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
529        self.addDefine('HAVE_SETLASTERROR',1)
530      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
531        self.addDefine('USE_NT_TIME',1)
532    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
533      self.addDefine('HAVE_GET_USER_NAME',1)
534    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
535      self.addDefine('HAVE_GET_USER_NAME',1)
536
537    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
538      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
539    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
540      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
541
542    self.types.check('int32_t', 'int')
543    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
544      self.addTypedef('int', 'uid_t')
545      self.addTypedef('int', 'gid_t')
546    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
547      self.framework.addDefine('R_OK', '04')
548      self.framework.addDefine('W_OK', '02')
549      self.framework.addDefine('X_OK', '01')
550    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
551      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
552      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
553    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
554      self.addDefine('HAVE_LARGE_INTEGER_U',1)
555
556    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
557    if self.checkCompile('#include <Windows.h>\n',''):
558      self.addDefine('HAVE_O_BINARY',1)
559
560    if self.compilers.CC.find('win32fe') >= 0:
561      self.addDefine('PATH_SEPARATOR','\';\'')
562      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
563      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
564      self.addDefine('CANNOT_START_DEBUGGER',1)
565    else:
566      self.addDefine('PATH_SEPARATOR','\':\'')
567      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
568      self.addDefine('DIR_SEPARATOR','\'/\'')
569    return
570
571#-----------------------------------------------------------------------------------------------------
572  def configureDefaultArch(self):
573    conffile = os.path.join('conf', 'petscvariables')
574    if self.framework.argDB['with-default-arch']:
575      fd = file(conffile, 'w')
576      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
577      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
578      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
579      fd.close()
580      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
581    elif os.path.isfile(conffile):
582      try:
583        os.unlink(conffile)
584      except:
585        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
586    return
587
588#-----------------------------------------------------------------------------------------------------
589  def configureScript(self):
590    '''Output a script in the conf directory which will reproduce the configuration'''
591    import nargs
592    import sys
593    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
594    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
595    if 'configModules' in args:
596      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
597        del args['configModules']
598    if 'optionsModule' in args:
599      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
600        del args['optionsModule']
601    if not 'PETSC_ARCH' in args:
602      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
603    f = file(scriptName, 'w')
604    f.write('#!'+sys.executable+'\n')
605    f.write('if __name__ == \'__main__\':\n')
606    f.write('  import sys\n')
607    f.write('  import os\n')
608    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
609    f.write('  import configure\n')
610    # pretty print repr(args.values())
611    f.write('  configure_options = [\n')
612    for itm in args.values():
613      f.write('    \''+str(itm)+'\',\n')
614    f.write('  ]\n')
615    f.write('  configure.petsc_configure(configure_options)\n')
616    f.close()
617    try:
618      os.chmod(scriptName, 0775)
619    except OSError, e:
620      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
621    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
622    return
623
624  def configureInstall(self):
625    '''Setup the directories for installation'''
626    if self.framework.argDB['prefix']:
627      self.installdir = self.framework.argDB['prefix']
628      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
629                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
630                                              '-@echo "========================================="'])
631    else:
632      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
633      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
634                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
635                                              '-@echo "========================================="'])
636      return
637
638  def configureGCOV(self):
639    if self.framework.argDB['with-gcov']:
640      self.addDefine('USE_GCOV','1')
641    return
642
643  def configureFortranFlush(self):
644    if hasattr(self.compilers, 'FC'):
645      for baseName in ['flush','flush_']:
646        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
647          self.addDefine('HAVE_'+baseName.upper(), 1)
648          return
649
650
651  def configure(self):
652    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
653      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
654    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
655      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
656    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
657    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
658    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
659    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
660    if self.libraries.math is None:
661      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
662    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
663      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
664    self.executeTest(self.configureInline)
665    self.executeTest(self.configurePrefetch)
666    self.executeTest(self.configureUnused)
667    self.executeTest(self.configureExpect);
668    self.executeTest(self.configureIntptrt);
669    self.executeTest(self.configureSolaris)
670    self.executeTest(self.configureLinux)
671    self.executeTest(self.configureWin32)
672    self.executeTest(self.configureDefaultArch)
673    self.executeTest(self.configureScript)
674    self.executeTest(self.configureInstall)
675    self.executeTest(self.configureGCOV)
676    self.executeTest(self.configureFortranFlush)
677    # dummy rules, always needed except for remote builds
678    self.addMakeRule('remote','')
679    self.addMakeRule('remoteclean','')
680
681    self.Dump()
682    self.dumpConfigInfo()
683    self.dumpMachineInfo()
684    self.dumpCMakeConfig()
685    self.dumpCMakeLists()
686    self.cmakeBoot()
687    self.framework.log.write('================================================================================\n')
688    self.logClear()
689    return
690