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