1f8833479SBarry Smith#!/usr/bin/env python 2f8833479SBarry Smith''' 3f8833479SBarry Smith This is the first try for a hierarchically configured module. The idea is to 4f8833479SBarry Smithadd the configure objects from a previously executed framework into the current 5f8833479SBarry Smithframework. However, this necessitates a reorganization of the activities in the 6f8833479SBarry Smithmodule. 7f8833479SBarry Smith 8f8833479SBarry Smith We must now have three distinct phases: location, construction, and testing. 9f8833479SBarry SmithThis is very similar to the current compiler checks. The construction phase is 10f8833479SBarry Smithoptional, and only necessary when the package has not been previously configured. 11f8833479SBarry SmithThe phases will necessarily interact, as an installtion must be located before 12f8833479SBarry Smithtesting, however anothe should be located if the testing fails. 13f8833479SBarry Smith 14f8833479SBarry Smith We will give each installation a unique key, which is returned by the location 15f8833479SBarry Smithmethod. This will allow us to identify working installations, as well as those 16f8833479SBarry Smiththat failed testing. 17f8833479SBarry Smith 18f8833479SBarry Smith There is a wierd role reversal that can happen. If we look for PETSc, but 19f8833479SBarry Smithcannot find it, it is reasonable to ask to have it automatically downloaded. 20f8833479SBarry SmithHowever, in this case, rather than using the configure objects from the existing 21f8833479SBarry SmithPETSc, we contribute objects to the PETSc which will be built. 22f8833479SBarry Smith 23f8833479SBarry Smith''' 24f8833479SBarry Smithfrom __future__ import generators 25f8833479SBarry Smithimport user 26f8833479SBarry Smithimport config.base 27f8833479SBarry Smith 28f8833479SBarry Smithimport re 29f8833479SBarry Smithimport os 30f8833479SBarry Smith 31f8833479SBarry Smithclass InvalidPETScError(RuntimeError): 32f8833479SBarry Smith pass 33f8833479SBarry Smith 34f8833479SBarry Smithclass Configure(config.base.Configure): 35f8833479SBarry Smith def __init__(self, framework): 36f8833479SBarry Smith config.base.Configure.__init__(self, framework) 37f8833479SBarry Smith self.headerPrefix = '' 38f8833479SBarry Smith self.substPrefix = '' 39f8833479SBarry Smith self.location = None 40f8833479SBarry Smith self.trial = {} 41f8833479SBarry Smith self.working = {} 42f8833479SBarry Smith return 43f8833479SBarry Smith 44f8833479SBarry Smith def __str__(self): 45f8833479SBarry Smith if self.found: 46f8833479SBarry Smith desc = ['PETSc:'] 47f8833479SBarry Smith desc.append(' Type: '+self.name) 48f8833479SBarry Smith desc.append(' Version: '+self.version) 49f8833479SBarry Smith desc.append(' Includes: '+str(self.include)) 50f8833479SBarry Smith desc.append(' Library: '+str(self.lib)) 51f8833479SBarry Smith return '\n'.join(desc)+'\n' 52f8833479SBarry Smith else: 53f8833479SBarry Smith return '' 54f8833479SBarry Smith 55f8833479SBarry Smith def setupHelp(self, help): 56f8833479SBarry Smith import nargs 57f8833479SBarry Smith help.addArgument('PETSc', '-with-petsc=<bool>', nargs.ArgBool(None, 1, 'Activate PETSc')) 58f8833479SBarry Smith # Location options 59f8833479SBarry Smith help.addArgument('PETSc', '-with-petsc-dir=<root dir>', nargs.ArgDir(None, None, 'Specify the root directory of the PETSc installation')) 60f8833479SBarry Smith help.addArgument('PETSc', '-with-petsc-arch=<arch>', nargs.Arg(None, None, 'Specify PETSC_ARCH')) 61f8833479SBarry Smith # Construction options 62ce0b2093SBarry Smith help.addArgument('PETSc', '-download-petsc=<bool>', nargs.ArgBool(None, 0, 'Install PETSc')) 63f8833479SBarry Smith # Testing options 64f8833479SBarry Smith help.addArgument('PETSc', '-with-petsc-shared=<bool>', nargs.ArgBool(None, 1, 'Require that the PETSc library be shared')) 65f8833479SBarry Smith return 66f8833479SBarry Smith 67f8833479SBarry Smith def setupPackageDependencies(self, framework): 68f8833479SBarry Smith import sys 69f8833479SBarry Smith 70f8833479SBarry Smith petscConf = None 71f8833479SBarry Smith for (name, (petscDir, petscArch)) in self.getLocations(): 729275508cSBarry Smith petscPythonDir = os.path.join(petscDir, 'config') 73f8833479SBarry Smith sys.path.append(petscPythonDir) 74f8833479SBarry Smith confPath = os.path.join(petscDir, petscArch,'conf') 75f8833479SBarry Smith petscConf = framework.loadFramework(confPath) 76f8833479SBarry Smith if petscConf: 77f8833479SBarry Smith self.logPrint('Loaded PETSc-AS configuration ('+name+') from '+confPath) 78f8833479SBarry Smith self.location = (petscDir, petscArch) 79f8833479SBarry Smith self.trial[self.location] = name 80f8833479SBarry Smith break 81f8833479SBarry Smith else: 82f8833479SBarry Smith self.logPrint('PETSc-AS has no cached configuration in '+confPath) 83f8833479SBarry Smith sys.path.reverse() 84f8833479SBarry Smith sys.path.remove(petscPythonDir) 85f8833479SBarry Smith sys.path.reverse() 86f8833479SBarry Smith if not petscConf: 87f8833479SBarry Smith self.downloadPETSc() 88f8833479SBarry Smith framework.addPackageDependency(petscConf, confPath) 89f8833479SBarry Smith return 90f8833479SBarry Smith 91f8833479SBarry Smith def setupDependencies(self, framework): 92f8833479SBarry Smith config.base.Configure.setupDependencies(self, framework) 93f8833479SBarry Smith self.languages = framework.require('PETSc.utilities.languages', self) 94f8833479SBarry Smith self.compilers = framework.require('config.compilers', self) 95f8833479SBarry Smith self.headers = framework.require('config.headers', self) 96f8833479SBarry Smith self.libraries = framework.require('config.libraries', self) 97f8833479SBarry Smith self.blaslapack = framework.require('PETSc.packages.BlasLapack', self) 98f8833479SBarry Smith self.mpi = framework.require('PETSc.packages.MPI', self) 99f8833479SBarry Smith return 100f8833479SBarry Smith 101f8833479SBarry Smith def getPETScArch(self, petscDir): 102f8833479SBarry Smith '''Return the allowable PETSc architectures for a given root''' 103f8833479SBarry Smith if 'with-petsc-arch' in self.framework.argDB: 104f8833479SBarry Smith yield self.framework.argDB['with-petsc-arch'] 105f8833479SBarry Smith elif 'PETSC_ARCH' in os.environ: 106f8833479SBarry Smith yield os.environ['PETSC_ARCH'] 107f8833479SBarry Smith else: 108f8833479SBarry Smith raise InvalidPETScError('Must set PETSC_ARCH or use --with-petsc-arch') 109f8833479SBarry Smith return 110f8833479SBarry Smith 111f8833479SBarry Smith def getLocations(self): 112f8833479SBarry Smith '''Return all allowable locations for PETSc''' 113f8833479SBarry Smith if hasattr(self, '_configured'): 114f8833479SBarry Smith key =(self.dir, self.arch) 115f8833479SBarry Smith yield (self.working[key], key) 116f8833479SBarry Smith raise InvalidPETScError('Configured PETSc is not usable') 117f8833479SBarry Smith if self.framework.argDB['download-petsc'] == 1: 118f8833479SBarry Smith yield self.downloadPETSc() 119f8833479SBarry Smith raise InvalidPETScError('Downloaded PETSc is not usable') 120f8833479SBarry Smith if 'with-petsc-dir' in self.framework.argDB: 121f8833479SBarry Smith petscDir = self.framework.argDB['with-petsc-dir'] 122f8833479SBarry Smith for petscArch in self.getPETScArch(petscDir): 123f8833479SBarry Smith yield ('User specified installation root', (petscDir, petscArch)) 124f8833479SBarry Smith raise InvalidPETScError('No working architecitures in '+str(petscDir)) 125f8833479SBarry Smith elif 'PETSC_DIR' in os.environ: 126f8833479SBarry Smith petscDir = os.environ['PETSC_DIR'] 127f8833479SBarry Smith for petscArch in self.getPETScArch(petscDir): 128f8833479SBarry Smith yield ('User specified installation root', (petscDir, petscArch)) 129f8833479SBarry Smith raise InvalidPETScError('No working architecitures in '+str(petscDir)) 130f8833479SBarry Smith else: 131f8833479SBarry Smith for petscArch in self.getPETScArch(petscDir): 132f8833479SBarry Smith yield ('Default compiler locations', ('', petscArch)) 133f8833479SBarry Smith petscDirRE = re.compile(r'(PETSC|pets)c(-.*)?') 134f8833479SBarry Smith trialDirs = [] 135f8833479SBarry Smith for packageDir in self.framework.argDB['package-dirs']: 136f8833479SBarry Smith if os.path.isdir(packageDir): 137f8833479SBarry Smith for d in os.listdir(packageDir): 138f8833479SBarry Smith if petscDirRE.match(d): 139f8833479SBarry Smith trialDirs.append(('Package directory installation root', os.path.join(packageDir, d))) 140f8833479SBarry Smith usrLocal = os.path.join('/usr', 'local') 141f8833479SBarry Smith if os.path.isdir(os.path.join('/usr', 'local')): 142f8833479SBarry Smith trialDirs.append(('Frequent user install location (/usr/local)', usrLocal)) 143f8833479SBarry Smith for d in os.listdir(usrLocal): 144f8833479SBarry Smith if petscDirRE.match(d): 145f8833479SBarry Smith trialDirs.append(('Frequent user install location (/usr/local/'+d+')', os.path.join(usrLocal, d))) 146f8833479SBarry Smith if 'HOME' in os.environ and os.path.isdir(os.environ['HOME']): 147f8833479SBarry Smith for d in os.listdir(os.environ['HOME']): 148f8833479SBarry Smith if petscDirRE.match(d): 149f8833479SBarry Smith trialDirs.append(('Frequent user install location (~/'+d+')', os.path.join(os.environ['HOME'], d))) 150f8833479SBarry Smith return 151f8833479SBarry Smith 152f8833479SBarry Smith def downloadPETSc(self): 153f8833479SBarry Smith if self.framework.argDB['download-petsc'] == 0: 154f8833479SBarry Smith raise RuntimeError('No functioning PETSc located') 155f8833479SBarry Smith # Download and build PETSc 156f8833479SBarry Smith # Use only the already configured objects from this run 157f8833479SBarry Smith raise RuntimeError('Not implemented') 158f8833479SBarry Smith 159f8833479SBarry Smith def getDir(self): 160f8833479SBarry Smith if self.location: 161f8833479SBarry Smith return self.location[0] 162f8833479SBarry Smith return None 163f8833479SBarry Smith dir = property(getDir, doc = 'The PETSc root directory') 164f8833479SBarry Smith 165f8833479SBarry Smith def getArch(self): 166f8833479SBarry Smith if self.location: 167f8833479SBarry Smith return self.location[1] 168f8833479SBarry Smith return None 169f8833479SBarry Smith arch = property(getArch, doc = 'The PETSc architecture') 170f8833479SBarry Smith 171f8833479SBarry Smith def getFound(self): 172f8833479SBarry Smith return self.location and self.location in self.working 173f8833479SBarry Smith found = property(getFound, doc = 'Did we find a valid PETSc installation') 174f8833479SBarry Smith 175f8833479SBarry Smith def getName(self): 176f8833479SBarry Smith if self.location and self.location in self.working: 177f8833479SBarry Smith return self.working[self.location][0] 178f8833479SBarry Smith return None 179f8833479SBarry Smith name = property(getName, doc = 'The PETSc installation type') 180f8833479SBarry Smith 181f8833479SBarry Smith def getInclude(self, useTrial = 0): 182f8833479SBarry Smith if self.location and self.location in self.working: 183f8833479SBarry Smith return self.working[self.location][1] 184f8833479SBarry Smith elif useTrial and self.location and self.location in self.trial: 185f8833479SBarry Smith return self.trial[self.location][1] 186f8833479SBarry Smith return None 187f8833479SBarry Smith include = property(getInclude, doc = 'The PETSc include directories') 188f8833479SBarry Smith 189f8833479SBarry Smith def getLib(self, useTrial = 0): 190f8833479SBarry Smith if self.location and self.location in self.working: 191f8833479SBarry Smith return self.working[self.location][2] 192f8833479SBarry Smith elif useTrial and self.location and self.location in self.trial: 193f8833479SBarry Smith return self.trial[self.location][2] 194f8833479SBarry Smith return None 195f8833479SBarry Smith lib = property(getLib, doc = 'The PETSc libraries') 196f8833479SBarry Smith 197f8833479SBarry Smith def getVersion(self): 198f8833479SBarry Smith if self.location and self.location in self.working: 199f8833479SBarry Smith return self.working[self.location][3] 200f8833479SBarry Smith return None 201f8833479SBarry Smith version = property(getVersion, doc = 'The PETSc version') 202f8833479SBarry Smith 203f8833479SBarry Smith def getOtherIncludes(self): 204f8833479SBarry Smith if not hasattr(self, '_otherIncludes'): 205f8833479SBarry Smith includes = [] 206f8833479SBarry Smith includes.extend([self.headers.getIncludeArgument(inc) for inc in self.mpi.include]) 207f8833479SBarry Smith return ' '.join(includes) 208f8833479SBarry Smith return self._otherIncludes 209f8833479SBarry Smith def setOtherIncludes(self, otherIncludes): 210f8833479SBarry Smith self._otherIncludes = otherIncludes 211f8833479SBarry Smith otherIncludes = property(getOtherIncludes, setOtherIncludes, doc = 'Includes needed to compile PETSc') 212f8833479SBarry Smith 213f8833479SBarry Smith def getOtherLibs(self): 214f8833479SBarry Smith if not hasattr(self, '_otherLibs'): 215f8833479SBarry Smith libs = self.compilers.flibs[:] 216f8833479SBarry Smith libs.extend(self.mpi.lib) 217f8833479SBarry Smith libs.extend(self.blaslapack.lib) 218f8833479SBarry Smith return libs 219f8833479SBarry Smith return self._otherLibs 220f8833479SBarry Smith def setOtherLibs(self, otherLibs): 221f8833479SBarry Smith self._otherLibs = otherLibs 222f8833479SBarry Smith otherLibs = property(getOtherLibs, setOtherLibs, doc = 'Libraries needed to link PETSc') 223f8833479SBarry Smith 224f8833479SBarry Smith def checkLib(self, libraries): 225f8833479SBarry Smith '''Check for PETSc creation functions in libraries, which can be a list of libraries or a single library 226f8833479SBarry Smith - PetscInitialize from libpetsc 227f8833479SBarry Smith - VecCreate from libpetscvec 228f8833479SBarry Smith - MatCreate from libpetscmat 229*9a42bb27SBarry Smith - DMDestroy from libpetscdm 230f8833479SBarry Smith - KSPCreate from libpetscksp 231f8833479SBarry Smith - SNESCreate from libpetscsnes 232f8833479SBarry Smith - TSCreate from libpetscts 233f8833479SBarry Smith ''' 234f8833479SBarry Smith if not isinstance(libraries, list): libraries = [libraries] 235f8833479SBarry Smith oldLibs = self.compilers.LIBS 236f8833479SBarry Smith self.libraries.pushLanguage(self.languages.clanguage) 237f8833479SBarry Smith found = (self.libraries.check(libraries, 'PetscInitializeNoArguments', otherLibs = self.otherLibs, prototype = 'int PetscInitializeNoArguments(void);', cxxMangle = not self.languages.cSupport) and 238f8833479SBarry Smith self.libraries.check(libraries, 'VecDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_Vec *Vec;int VecDestroy(Vec);', call = 'VecDestroy((Vec) 0)', cxxMangle = not self.languages.cSupport) and 239f8833479SBarry Smith self.libraries.check(libraries, 'MatDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_Mat *Mat;int MatDestroy(Mat);', call = 'MatDestroy((Mat) 0)', cxxMangle = not self.languages.cSupport) and 240*9a42bb27SBarry Smith self.libraries.check(libraries, 'DMDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_DM *DA;int DMDestroy(DA);', call = 'DMDestroy((DA) 0)', cxxMangle = not self.languages.cSupport) and 241f8833479SBarry Smith self.libraries.check(libraries, 'KSPDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_KSP *KSP;int KSPDestroy(KSP);', call = 'KSPDestroy((KSP) 0)', cxxMangle = not self.languages.cSupport) and 242f8833479SBarry Smith self.libraries.check(libraries, 'SNESDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_SNES *SNES;int SNESDestroy(SNES);', call = 'SNESDestroy((SNES) 0)', cxxMangle = not self.languages.cSupport) and 243f8833479SBarry Smith self.libraries.check(libraries, 'TSDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_TS *TS;int TSDestroy(TS);', call = 'TSDestroy((TS) 0)', cxxMangle = not self.languages.cSupport)) 244f8833479SBarry Smith self.libraries.popLanguage() 245f8833479SBarry Smith self.compilers.LIBS = oldLibs 246f8833479SBarry Smith return found 247f8833479SBarry Smith 248f8833479SBarry Smith def checkInclude(self, includeDir): 249d382aafbSBarry Smith '''Check that petscsys.h is present''' 250f8833479SBarry Smith oldFlags = self.compilers.CPPFLAGS 251f8833479SBarry Smith self.compilers.CPPFLAGS += ' '.join([self.headers.getIncludeArgument(inc) for inc in includeDir]) 252f8833479SBarry Smith if self.otherIncludes: 253f8833479SBarry Smith self.compilers.CPPFLAGS += ' '+self.otherIncludes 254f8833479SBarry Smith self.pushLanguage(self.languages.clanguage) 255d382aafbSBarry Smith found = self.checkPreprocess('#include <petscsys.h>\n') 256f8833479SBarry Smith self.popLanguage() 257f8833479SBarry Smith self.compilers.CPPFLAGS = oldFlags 258f8833479SBarry Smith return found 259f8833479SBarry Smith 260f8833479SBarry Smith def checkPETScLink(self, includes, body, cleanup = 1, codeBegin = None, codeEnd = None, shared = None): 261f8833479SBarry Smith '''Analogous to checkLink(), but the PETSc includes and libraries are automatically provided''' 262f8833479SBarry Smith success = 0 263f8833479SBarry Smith oldFlags = self.compilers.CPPFLAGS 264f8833479SBarry Smith self.compilers.CPPFLAGS += ' '.join([self.headers.getIncludeArgument(inc) for inc in self.getInclude(useTrial = 1)]) 265f8833479SBarry Smith if self.otherIncludes: 266f8833479SBarry Smith self.compilers.CPPFLAGS += ' '+self.otherIncludes 267f8833479SBarry Smith oldLibs = self.compilers.LIBS 268f8833479SBarry Smith self.compilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.getLib(useTrial = 1)+self.otherLibs])+' '+self.compilers.LIBS 269f8833479SBarry Smith if self.checkLink(includes, body, cleanup, codeBegin, codeEnd, shared): 270f8833479SBarry Smith success = 1 271f8833479SBarry Smith self.compilers.CPPFLAGS = oldFlags 272f8833479SBarry Smith self.compilers.LIBS = oldLibs 273f8833479SBarry Smith return success 274f8833479SBarry Smith 275f8833479SBarry Smith def checkWorkingLink(self): 276f8833479SBarry Smith '''Checking that we can link a PETSc executable''' 277f8833479SBarry Smith self.pushLanguage(self.languages.clanguage) 278f8833479SBarry Smith if not self.checkPETScLink('#include <petsclog.h>\n', 'PetscLogDouble time;\nPetscErrorCode ierr;\n\nierr = PetscGetTime(&time); CHKERRQ(ierr);\n'): 279f8833479SBarry Smith self.logPrint('PETSc cannot link, which indicates a problem with the PETSc installation') 280f8833479SBarry Smith return 0 281f8833479SBarry Smith self.logPrint('PETSc can link with '+self.languages.clanguage) 282f8833479SBarry Smith self.popLanguage() 283f8833479SBarry Smith 284f8833479SBarry Smith if hasattr(self.compilers, 'CXX') and self.languages.clanguage == 'C': 285f8833479SBarry Smith self.pushLanguage('C++') 286f8833479SBarry Smith self.sourceExtension = '.C' 287d382aafbSBarry Smith if not self.checkPETScLink('#define PETSC_USE_EXTERN_CXX\n#include <petscsys.h>\n', 'PetscLogDouble time;\nPetscErrorCode ierr;\n\nierr = PetscGetTime(&time); CHKERRQ(ierr);\n'): 288f8833479SBarry Smith self.logPrint('PETSc cannot link C++ but can link C, which indicates a problem with the PETSc installation') 289f8833479SBarry Smith self.popLanguage() 290f8833479SBarry Smith return 0 291f8833479SBarry Smith self.popLanguage() 292f8833479SBarry Smith self.logPrint('PETSc can link with C++') 293f8833479SBarry Smith 294f8833479SBarry Smith if hasattr(self.compilers, 'FC'): 295f8833479SBarry Smith self.pushLanguage('FC') 296f8833479SBarry Smith self.sourceExtension = '.F' 297f8833479SBarry Smith if not self.checkPETScLink('', ' integer ierr\n real time\n call PetscGetTime(time, ierr)\n'): 298f8833479SBarry Smith self.logPrint('PETSc cannot link Fortran, but can link C, which indicates a problem with the PETSc installation\nRun with -with-fc=0 if you do not wish to use Fortran') 299f8833479SBarry Smith self.popLanguage() 300f8833479SBarry Smith return 0 301f8833479SBarry Smith self.popLanguage() 302f8833479SBarry Smith self.logPrint('PETSc can link with Fortran') 303f8833479SBarry Smith return 1 304f8833479SBarry Smith 305f8833479SBarry Smith def checkSharedLibrary(self, libraries): 306f8833479SBarry Smith '''Check that the libraries for PETSc are shared libraries''' 307f8833479SBarry Smith if config.setCompilers.Configure.isDarwin(): 308f8833479SBarry Smith # on Apple if you list the MPI libraries again you will generate multiply defined errors 309f8833479SBarry Smith # since they are already copied into the PETSc dynamic library. 310f8833479SBarry Smith self.setOtherLibs([]) 311f8833479SBarry Smith self.pushLanguage(self.languages.clanguage) 312ace3abfcSBarry Smith isShared = self.libraries.checkShared('#include <petscsys.h>\n', 'PetscInitialize', 'PetscInitialized', 'PetscFinalize', checkLink = self.checkPETScLink, libraries = libraries, initArgs = '&argc, &argv, 0, 0', boolType = 'PetscBool ', executor = self.mpi.mpiexec) 313f8833479SBarry Smith self.popLanguage() 314f8833479SBarry Smith return isShared 315f8833479SBarry Smith 316f8833479SBarry Smith def configureVersion(self): 317f8833479SBarry Smith '''Determine the PETSc version''' 318f8833479SBarry Smith majorRE = re.compile(r'^#define PETSC_VERSION_MAJOR([\s]+)(?P<versionNum>\d+)[\s]*$'); 319f8833479SBarry Smith minorRE = re.compile(r'^#define PETSC_VERSION_MINOR([\s]+)(?P<versionNum>\d+)[\s]*$'); 320f8833479SBarry Smith subminorRE = re.compile(r'^#define PETSC_VERSION_SUBMINOR([\s]+)(?P<versionNum>\d+)[\s]*$'); 321f8833479SBarry Smith patchRE = re.compile(r'^#define PETSC_VERSION_PATCH([\s]+)(?P<patchNum>\d+)[\s]*$'); 322f8833479SBarry Smith dateRE = re.compile(r'^#define PETSC_VERSION_DATE([\s]+)"(?P<date>(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d\d?, \d\d\d\d)"[\s]*$'); 323f8833479SBarry Smith input = file(os.path.join(self.dir, 'include', 'petscversion.h')) 324f8833479SBarry Smith lines = [] 325f8833479SBarry Smith majorNum = 'Unknown' 326f8833479SBarry Smith minorNum = 'Unknown' 327f8833479SBarry Smith subminorNum = 'Unknown' 328f8833479SBarry Smith patchNum = 'Unknown' 329f8833479SBarry Smith self.date = 'Unknown' 330f8833479SBarry Smith for line in input.readlines(): 331f8833479SBarry Smith m1 = majorRE.match(line) 332f8833479SBarry Smith m2 = minorRE.match(line) 333f8833479SBarry Smith m3 = subminorRE.match(line) 334f8833479SBarry Smith m4 = patchRE.match(line) 335f8833479SBarry Smith m5 = dateRE.match(line) 336f8833479SBarry Smith if m1: 337f8833479SBarry Smith majorNum = int(m1.group('versionNum')) 338f8833479SBarry Smith elif m2: 339f8833479SBarry Smith minorNum = int(m2.group('versionNum')) 340f8833479SBarry Smith elif m3: 341f8833479SBarry Smith subminorNum = int(m3.group('versionNum')) 342f8833479SBarry Smith 343f8833479SBarry Smith if m4: 344f8833479SBarry Smith patchNum = int(m4.group('patchNum'))+1 345f8833479SBarry Smith lines.append('#define PETSC_VERSION_PATCH'+m4.group(1)+str(patchNum)+'\n') 346f8833479SBarry Smith elif m5: 347f8833479SBarry Smith self.date = time.strftime('%b %d, %Y', time.localtime(time.time())) 348f8833479SBarry Smith lines.append('#define PETSC_VERSION_DATE'+m5.group(1)+'"'+self.date+'"\n') 349f8833479SBarry Smith else: 350f8833479SBarry Smith lines.append(line) 351f8833479SBarry Smith input.close() 352f8833479SBarry Smith self.logPrint('Found PETSc version (%s,%s,%s) patch %s on %s' % (majorNum, minorNum, subminorNum, patchNum, self.date)) 353f8833479SBarry Smith return '%d.%d.%d' % (majorNum, minorNum, subminorNum) 354f8833479SBarry Smith 355f8833479SBarry Smith def includeGuesses(self, path = None): 356f8833479SBarry Smith '''Return all include directories present in path or its ancestors''' 357f8833479SBarry Smith if not path: 358f8833479SBarry Smith yield [] 359f8833479SBarry Smith while path: 360f8833479SBarry Smith dir = os.path.join(path, 'include') 361f8833479SBarry Smith if os.path.isdir(dir): 362f8833479SBarry Smith yield [dir, os.path.join(path, self.arch,'include')] 363f8833479SBarry Smith if path == '/': 364f8833479SBarry Smith return 365f8833479SBarry Smith path = os.path.dirname(path) 366f8833479SBarry Smith return 367f8833479SBarry Smith 368f8833479SBarry Smith def libraryGuesses(self, root = None): 369f8833479SBarry Smith '''Return standard library name guesses for a given installation root''' 370f8833479SBarry Smith libs = ['ts', 'snes', 'ksp', 'dm', 'mat', 'vec', ''] 371f8833479SBarry Smith if root: 372f8833479SBarry Smith d = os.path.join(root, 'lib', self.arch) 373f8833479SBarry Smith if not os.path.isdir(d): 374f8833479SBarry Smith self.logPrint('', 3, 'petsc') 375f8833479SBarry Smith return 376f8833479SBarry Smith yield [os.path.join(d, 'libpetsc'+lib+'.a') for lib in libs] 377f8833479SBarry Smith else: 378f8833479SBarry Smith yield ['libpetsc'+lib+'.a' for lib in libs] 379f8833479SBarry Smith return 380f8833479SBarry Smith 381f8833479SBarry Smith def configureLibrary(self): 382f8833479SBarry Smith '''Find a working PETSc 383f8833479SBarry Smith - Right now, C++ builds are required to use PETSC_USE_EXTERN_CXX''' 384f8833479SBarry Smith for location, name in self.trial.items(): 385f8833479SBarry Smith self.framework.logPrintDivider() 386f8833479SBarry Smith self.framework.logPrint('Checking for a functional PETSc in '+name+', location/origin '+str(location)) 387f8833479SBarry Smith lib = None 388f8833479SBarry Smith include = None 389f8833479SBarry Smith found = 0 390f8833479SBarry Smith for libraries in self.libraryGuesses(location[0]): 391f8833479SBarry Smith if self.checkLib(libraries): 392f8833479SBarry Smith lib = libraries 393f8833479SBarry Smith for includeDir in self.includeGuesses(location[0]): 394f8833479SBarry Smith if self.checkInclude(includeDir): 395f8833479SBarry Smith include = includeDir 396f8833479SBarry Smith self.trial[location] = (name, include, lib, 'Unknown') 397f8833479SBarry Smith if self.executeTest(self.checkWorkingLink): 398f8833479SBarry Smith found = 1 399f8833479SBarry Smith break 400f8833479SBarry Smith else: 401f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 402f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkWorkingLink test') 403f8833479SBarry Smith else: 404f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 405f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkInclude test with includeDir: '+str(includeDir)) 406f8833479SBarry Smith if not found: 407f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 408f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkIncludes test') 409f8833479SBarry Smith continue 410f8833479SBarry Smith else: 411f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 412f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkLib test with libraries: '+str(libraries)) 413f8833479SBarry Smith continue 414f8833479SBarry Smith if self.framework.argDB['with-petsc-shared']: 415f8833479SBarry Smith if not self.executeTest(self.checkSharedLibrary, [libraries]): 416f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 417f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkSharedLibrary test with libraries: '+str(libraries)) 418f8833479SBarry Smith found = 0 419f8833479SBarry Smith if found: 420f8833479SBarry Smith break 421f8833479SBarry Smith if found: 422f8833479SBarry Smith version = self.executeTest(self.configureVersion) 423f8833479SBarry Smith self.working[location] = (name, include, lib, version) 424f8833479SBarry Smith break 425f8833479SBarry Smith if found: 426f8833479SBarry Smith self.logPrint('Choose PETSc '+self.version+' in '+self.name) 427f8833479SBarry Smith else: 428f8833479SBarry Smith raise RuntimeError('Could not locate any functional PETSc') 429f8833479SBarry Smith return 430f8833479SBarry Smith 431f8833479SBarry Smith def setOutput(self): 432f8833479SBarry Smith '''Add defines and substitutions 433f8833479SBarry Smith - HAVE_PETSC is defined if a working PETSc is found 434f8833479SBarry Smith - PETSC_INCLUDE and PETSC_LIB are command line arguments for the compile and link''' 435f8833479SBarry Smith if self.found: 436f8833479SBarry Smith self.addDefine('HAVE_PETSC', 1) 437f8833479SBarry Smith self.addSubstitution('PETSC_INCLUDE', ' '.join([self.headers.getIncludeArgument(inc) for inc in self.include])) 438f8833479SBarry Smith self.addSubstitution('PETSC_LIB', ' '.join(map(self.libraries.getLibArgument, self.lib))) 439f8833479SBarry Smith return 440f8833479SBarry Smith 441f8833479SBarry Smith def configure(self): 442f8833479SBarry Smith self.executeTest(self.configureLibrary) 443f8833479SBarry Smith self.setOutput() 444f8833479SBarry Smith return 445f8833479SBarry Smith 446f8833479SBarry Smithif __name__ == '__main__': 447f8833479SBarry Smith import config.framework 448f8833479SBarry Smith import sys 449f8833479SBarry Smith framework = config.framework.Framework(sys.argv[1:]) 450f8833479SBarry Smith framework.setup() 451f8833479SBarry Smith framework.addChild(Configure(framework)) 452f8833479SBarry Smith framework.configure() 453f8833479SBarry Smith framework.dumpSubstitutions() 454