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) 74af0996ceSBarry Smith confPath = os.path.join(petscDir, petscArch,'lib','petsc','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) 939d310bb7SBarry Smith self.languages = framework.require('PETSc.options.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) 9706e08bc7SBarry Smith self.blaslapack = framework.require('config.packages.BlasLapack', self) 9806e08bc7SBarry Smith self.mpi = framework.require('config.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 = [] 135*0aa1f76dSSatish Balay for packageDir in self.framework.argDB['with-packages-search-path']: 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 2299a42bb27SBarry 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) 2372c280183SJed Brown found = (self.libraries.check(libraries, 'PetscInitializeNoArguments', otherLibs = self.otherLibs, prototype = 'int PetscInitializeNoArguments(void);') and 2382c280183SJed Brown self.libraries.check(libraries, 'VecDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_Vec *Vec;int VecDestroy(Vec*);', call = 'VecDestroy((Vec*) 0)') and 2392c280183SJed Brown self.libraries.check(libraries, 'MatDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_Mat *Mat;int MatDestroy(Mat*);', call = 'MatDestroy((Mat*) 0)') and 2402c280183SJed Brown self.libraries.check(libraries, 'DMDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_DM *DA;int DMDestroy(DA*);', call = 'DMDestroy((DA*) 0)') and 2412c280183SJed Brown self.libraries.check(libraries, 'KSPDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_KSP *KSP;int KSPDestroy(KSP*);', call = 'KSPDestroy((KSP*) 0)') and 2422c280183SJed Brown self.libraries.check(libraries, 'SNESDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_SNES *SNES;int SNESDestroy(SNES*);', call = 'SNESDestroy((SNES*) 0)') and 2432c280183SJed Brown self.libraries.check(libraries, 'TSDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_TS *TS;int TSDestroy(TS*);', call = 'TSDestroy((TS*) 0)')) 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) 2788563dfccSBarry Smith if not self.checkPETScLink('#include <petsctime.h>\n', 'PetscLogDouble time;\nPetscErrorCode ierr;\n\nierr = PetscTime(&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' 2878563dfccSBarry Smith if not self.checkPETScLink('#include <petsctime.h>\n', 'PetscLogDouble time;\nPetscErrorCode ierr;\n\nierr = PetscTime(&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' 2978563dfccSBarry Smith if not self.checkPETScLink('', ' integer ierr\n real time\n call PetscTime(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''' 3077fca349cSMatthew G. Knepley if config.setCompilers.Configure.isDarwin(self.log): 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 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]*$'); 322f8833479SBarry Smith input = file(os.path.join(self.dir, 'include', 'petscversion.h')) 323f8833479SBarry Smith lines = [] 324f8833479SBarry Smith majorNum = 'Unknown' 325f8833479SBarry Smith minorNum = 'Unknown' 326f8833479SBarry Smith subminorNum = 'Unknown' 327f8833479SBarry Smith self.date = 'Unknown' 328f8833479SBarry Smith for line in input.readlines(): 329f8833479SBarry Smith m1 = majorRE.match(line) 330f8833479SBarry Smith m2 = minorRE.match(line) 331f8833479SBarry Smith m3 = subminorRE.match(line) 332f8833479SBarry Smith m5 = dateRE.match(line) 333f8833479SBarry Smith if m1: 334f8833479SBarry Smith majorNum = int(m1.group('versionNum')) 335f8833479SBarry Smith elif m2: 336f8833479SBarry Smith minorNum = int(m2.group('versionNum')) 337f8833479SBarry Smith elif m3: 338f8833479SBarry Smith subminorNum = int(m3.group('versionNum')) 339f8833479SBarry Smith 34066d79e26SBarry Smith if m5: 341f8833479SBarry Smith self.date = time.strftime('%b %d, %Y', time.localtime(time.time())) 342f8833479SBarry Smith lines.append('#define PETSC_VERSION_DATE'+m5.group(1)+'"'+self.date+'"\n') 343f8833479SBarry Smith else: 344f8833479SBarry Smith lines.append(line) 345f8833479SBarry Smith input.close() 34666d79e26SBarry Smith self.logPrint('Found PETSc version (%s,%s,%s) on %s' % (majorNum, minorNum, subminorNum, self.date)) 347f8833479SBarry Smith return '%d.%d.%d' % (majorNum, minorNum, subminorNum) 348f8833479SBarry Smith 349f8833479SBarry Smith def includeGuesses(self, path = None): 350f8833479SBarry Smith '''Return all include directories present in path or its ancestors''' 351f8833479SBarry Smith if not path: 352f8833479SBarry Smith yield [] 353f8833479SBarry Smith while path: 354f8833479SBarry Smith dir = os.path.join(path, 'include') 355f8833479SBarry Smith if os.path.isdir(dir): 356f8833479SBarry Smith yield [dir, os.path.join(path, self.arch,'include')] 357f8833479SBarry Smith if path == '/': 358f8833479SBarry Smith return 359f8833479SBarry Smith path = os.path.dirname(path) 360f8833479SBarry Smith return 361f8833479SBarry Smith 362f8833479SBarry Smith def libraryGuesses(self, root = None): 363f8833479SBarry Smith '''Return standard library name guesses for a given installation root''' 364f8833479SBarry Smith libs = ['ts', 'snes', 'ksp', 'dm', 'mat', 'vec', ''] 365f8833479SBarry Smith if root: 366f8833479SBarry Smith d = os.path.join(root, 'lib', self.arch) 367f8833479SBarry Smith if not os.path.isdir(d): 368f8833479SBarry Smith self.logPrint('', 3, 'petsc') 369f8833479SBarry Smith return 370f8833479SBarry Smith yield [os.path.join(d, 'libpetsc'+lib+'.a') for lib in libs] 371f8833479SBarry Smith else: 372f8833479SBarry Smith yield ['libpetsc'+lib+'.a' for lib in libs] 373f8833479SBarry Smith return 374f8833479SBarry Smith 375f8833479SBarry Smith def configureLibrary(self): 3762c280183SJed Brown '''Find a working PETSc''' 377f8833479SBarry Smith for location, name in self.trial.items(): 378f8833479SBarry Smith self.framework.logPrintDivider() 379f8833479SBarry Smith self.framework.logPrint('Checking for a functional PETSc in '+name+', location/origin '+str(location)) 380f8833479SBarry Smith lib = None 381f8833479SBarry Smith include = None 382f8833479SBarry Smith found = 0 383f8833479SBarry Smith for libraries in self.libraryGuesses(location[0]): 384f8833479SBarry Smith if self.checkLib(libraries): 385f8833479SBarry Smith lib = libraries 386f8833479SBarry Smith for includeDir in self.includeGuesses(location[0]): 387f8833479SBarry Smith if self.checkInclude(includeDir): 388f8833479SBarry Smith include = includeDir 389f8833479SBarry Smith self.trial[location] = (name, include, lib, 'Unknown') 390f8833479SBarry Smith if self.executeTest(self.checkWorkingLink): 391f8833479SBarry Smith found = 1 392f8833479SBarry Smith break 393f8833479SBarry Smith else: 394f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 395f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkWorkingLink test') 396f8833479SBarry Smith else: 397f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 398f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkInclude test with includeDir: '+str(includeDir)) 399f8833479SBarry Smith if not found: 400f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 401f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkIncludes test') 402f8833479SBarry Smith continue 403f8833479SBarry Smith else: 404f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 405f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkLib test with libraries: '+str(libraries)) 406f8833479SBarry Smith continue 407f8833479SBarry Smith if self.framework.argDB['with-petsc-shared']: 408f8833479SBarry Smith if not self.executeTest(self.checkSharedLibrary, [libraries]): 409f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 410f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkSharedLibrary test with libraries: '+str(libraries)) 411f8833479SBarry Smith found = 0 412f8833479SBarry Smith if found: 413f8833479SBarry Smith break 414f8833479SBarry Smith if found: 415f8833479SBarry Smith version = self.executeTest(self.configureVersion) 416f8833479SBarry Smith self.working[location] = (name, include, lib, version) 417f8833479SBarry Smith break 418f8833479SBarry Smith if found: 419f8833479SBarry Smith self.logPrint('Choose PETSc '+self.version+' in '+self.name) 420f8833479SBarry Smith else: 421f8833479SBarry Smith raise RuntimeError('Could not locate any functional PETSc') 422f8833479SBarry Smith return 423f8833479SBarry Smith 424f8833479SBarry Smith def setOutput(self): 425f8833479SBarry Smith '''Add defines and substitutions 426f8833479SBarry Smith - HAVE_PETSC is defined if a working PETSc is found 427f8833479SBarry Smith - PETSC_INCLUDE and PETSC_LIB are command line arguments for the compile and link''' 428f8833479SBarry Smith if self.found: 429f8833479SBarry Smith self.addDefine('HAVE_PETSC', 1) 430f8833479SBarry Smith self.addSubstitution('PETSC_INCLUDE', ' '.join([self.headers.getIncludeArgument(inc) for inc in self.include])) 431f8833479SBarry Smith self.addSubstitution('PETSC_LIB', ' '.join(map(self.libraries.getLibArgument, self.lib))) 432f8833479SBarry Smith return 433f8833479SBarry Smith 434f8833479SBarry Smith def configure(self): 435f8833479SBarry Smith self.executeTest(self.configureLibrary) 436f8833479SBarry Smith self.setOutput() 437f8833479SBarry Smith return 438f8833479SBarry Smith 439f8833479SBarry Smithif __name__ == '__main__': 440f8833479SBarry Smith import config.framework 441f8833479SBarry Smith import sys 442f8833479SBarry Smith framework = config.framework.Framework(sys.argv[1:]) 443f8833479SBarry Smith framework.setup() 444f8833479SBarry Smith framework.addChild(Configure(framework)) 445f8833479SBarry Smith framework.configure() 446f8833479SBarry Smith framework.dumpSubstitutions() 447