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