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