1df3bd252SSatish Balay#!/usr/bin/env python3 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. 11*d5b43468SJose E. RomanThe phases will necessarily interact, as an installation must be located before 12*d5b43468SJose E. Romantesting, however another 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 18*d5b43468SJose E. Roman There is a weird 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 config.base 26f8833479SBarry Smith 27f8833479SBarry Smithimport re 28f8833479SBarry Smithimport os 29f8833479SBarry Smith 30f8833479SBarry Smithclass InvalidPETScError(RuntimeError): 31f8833479SBarry Smith pass 32f8833479SBarry Smith 33f8833479SBarry Smithclass Configure(config.base.Configure): 34f8833479SBarry Smith def __init__(self, framework): 35f8833479SBarry Smith config.base.Configure.__init__(self, framework) 36f8833479SBarry Smith self.headerPrefix = '' 37f8833479SBarry Smith self.substPrefix = '' 38f8833479SBarry Smith self.location = None 39f8833479SBarry Smith self.trial = {} 40f8833479SBarry Smith self.working = {} 41f8833479SBarry Smith return 42f8833479SBarry Smith 43f8833479SBarry Smith def __str__(self): 44f8833479SBarry Smith if self.found: 45f8833479SBarry Smith desc = ['PETSc:'] 46f8833479SBarry Smith desc.append(' Type: '+self.name) 47f8833479SBarry Smith desc.append(' Version: '+self.version) 48f8833479SBarry Smith desc.append(' Includes: '+str(self.include)) 49f8833479SBarry Smith desc.append(' Library: '+str(self.lib)) 50f8833479SBarry Smith return '\n'.join(desc)+'\n' 51f8833479SBarry Smith else: 52f8833479SBarry Smith return '' 53f8833479SBarry Smith 54f8833479SBarry Smith def setupHelp(self, help): 55f8833479SBarry Smith import nargs 56f8833479SBarry Smith help.addArgument('PETSc', '-with-petsc=<bool>', nargs.ArgBool(None, 1, 'Activate PETSc')) 57f8833479SBarry Smith # Location options 58f8833479SBarry Smith help.addArgument('PETSc', '-with-petsc-dir=<root dir>', nargs.ArgDir(None, None, 'Specify the root directory of the PETSc installation')) 59f8833479SBarry Smith help.addArgument('PETSc', '-with-petsc-arch=<arch>', nargs.Arg(None, None, 'Specify PETSC_ARCH')) 60f8833479SBarry Smith # Construction options 61ce0b2093SBarry Smith help.addArgument('PETSc', '-download-petsc=<bool>', nargs.ArgBool(None, 0, 'Install PETSc')) 62f8833479SBarry Smith # Testing options 63f8833479SBarry Smith help.addArgument('PETSc', '-with-petsc-shared=<bool>', nargs.ArgBool(None, 1, 'Require that the PETSc library be shared')) 64f8833479SBarry Smith return 65f8833479SBarry Smith 66f8833479SBarry Smith def setupPackageDependencies(self, framework): 67f8833479SBarry Smith import sys 68f8833479SBarry Smith 69f8833479SBarry Smith petscConf = None 70f8833479SBarry Smith for (name, (petscDir, petscArch)) in self.getLocations(): 719275508cSBarry Smith petscPythonDir = os.path.join(petscDir, 'config') 72f8833479SBarry Smith sys.path.append(petscPythonDir) 73af0996ceSBarry Smith confPath = os.path.join(petscDir, petscArch,'lib','petsc','conf') 74f8833479SBarry Smith petscConf = framework.loadFramework(confPath) 75f8833479SBarry Smith if petscConf: 76f8833479SBarry Smith self.logPrint('Loaded PETSc-AS configuration ('+name+') from '+confPath) 77f8833479SBarry Smith self.location = (petscDir, petscArch) 78f8833479SBarry Smith self.trial[self.location] = name 79f8833479SBarry Smith break 80f8833479SBarry Smith else: 81f8833479SBarry Smith self.logPrint('PETSc-AS has no cached configuration in '+confPath) 82f8833479SBarry Smith sys.path.reverse() 83f8833479SBarry Smith sys.path.remove(petscPythonDir) 84f8833479SBarry Smith sys.path.reverse() 85f8833479SBarry Smith if not petscConf: 86f8833479SBarry Smith self.downloadPETSc() 87f8833479SBarry Smith framework.addPackageDependency(petscConf, confPath) 88f8833479SBarry Smith return 89f8833479SBarry Smith 90f8833479SBarry Smith def setupDependencies(self, framework): 91f8833479SBarry Smith config.base.Configure.setupDependencies(self, framework) 929d310bb7SBarry Smith self.languages = framework.require('PETSc.options.languages', self) 93f8833479SBarry Smith self.compilers = framework.require('config.compilers', self) 94f8833479SBarry Smith self.headers = framework.require('config.headers', self) 95f8833479SBarry Smith self.libraries = framework.require('config.libraries', self) 9606e08bc7SBarry Smith self.blaslapack = framework.require('config.packages.BlasLapack', self) 9706e08bc7SBarry Smith self.mpi = framework.require('config.packages.MPI', self) 98f8833479SBarry Smith return 99f8833479SBarry Smith 100f8833479SBarry Smith def getPETScArch(self, petscDir): 101f8833479SBarry Smith '''Return the allowable PETSc architectures for a given root''' 102f8833479SBarry Smith if 'with-petsc-arch' in self.framework.argDB: 103f8833479SBarry Smith yield self.framework.argDB['with-petsc-arch'] 104f8833479SBarry Smith elif 'PETSC_ARCH' in os.environ: 105f8833479SBarry Smith yield os.environ['PETSC_ARCH'] 106f8833479SBarry Smith else: 107f8833479SBarry Smith raise InvalidPETScError('Must set PETSC_ARCH or use --with-petsc-arch') 108f8833479SBarry Smith return 109f8833479SBarry Smith 110f8833479SBarry Smith def getLocations(self): 111f8833479SBarry Smith '''Return all allowable locations for PETSc''' 112f8833479SBarry Smith if hasattr(self, '_configured'): 113f8833479SBarry Smith key =(self.dir, self.arch) 114f8833479SBarry Smith yield (self.working[key], key) 115f8833479SBarry Smith raise InvalidPETScError('Configured PETSc is not usable') 116f8833479SBarry Smith if self.framework.argDB['download-petsc'] == 1: 117f8833479SBarry Smith yield self.downloadPETSc() 118f8833479SBarry Smith raise InvalidPETScError('Downloaded PETSc is not usable') 119f8833479SBarry Smith if 'with-petsc-dir' in self.framework.argDB: 120f8833479SBarry Smith petscDir = self.framework.argDB['with-petsc-dir'] 121f8833479SBarry Smith for petscArch in self.getPETScArch(petscDir): 122f8833479SBarry Smith yield ('User specified installation root', (petscDir, petscArch)) 123f8833479SBarry Smith raise InvalidPETScError('No working architecitures in '+str(petscDir)) 124f8833479SBarry Smith elif 'PETSC_DIR' in os.environ: 125f8833479SBarry Smith petscDir = os.environ['PETSC_DIR'] 126f8833479SBarry Smith for petscArch in self.getPETScArch(petscDir): 127f8833479SBarry Smith yield ('User specified installation root', (petscDir, petscArch)) 128f8833479SBarry Smith raise InvalidPETScError('No working architecitures in '+str(petscDir)) 129f8833479SBarry Smith else: 130f8833479SBarry Smith for petscArch in self.getPETScArch(petscDir): 131f8833479SBarry Smith yield ('Default compiler locations', ('', petscArch)) 132f8833479SBarry Smith petscDirRE = re.compile(r'(PETSC|pets)c(-.*)?') 133f8833479SBarry Smith trialDirs = [] 1340aa1f76dSSatish Balay for packageDir in self.framework.argDB['with-packages-search-path']: 135f8833479SBarry Smith if os.path.isdir(packageDir): 136f8833479SBarry Smith for d in os.listdir(packageDir): 137f8833479SBarry Smith if petscDirRE.match(d): 138f8833479SBarry Smith trialDirs.append(('Package directory installation root', os.path.join(packageDir, d))) 139f8833479SBarry Smith usrLocal = os.path.join('/usr', 'local') 140f8833479SBarry Smith if os.path.isdir(os.path.join('/usr', 'local')): 141f8833479SBarry Smith trialDirs.append(('Frequent user install location (/usr/local)', usrLocal)) 142f8833479SBarry Smith for d in os.listdir(usrLocal): 143f8833479SBarry Smith if petscDirRE.match(d): 144f8833479SBarry Smith trialDirs.append(('Frequent user install location (/usr/local/'+d+')', os.path.join(usrLocal, d))) 145f8833479SBarry Smith if 'HOME' in os.environ and os.path.isdir(os.environ['HOME']): 146f8833479SBarry Smith for d in os.listdir(os.environ['HOME']): 147f8833479SBarry Smith if petscDirRE.match(d): 148f8833479SBarry Smith trialDirs.append(('Frequent user install location (~/'+d+')', os.path.join(os.environ['HOME'], d))) 149f8833479SBarry Smith return 150f8833479SBarry Smith 151f8833479SBarry Smith def downloadPETSc(self): 152f8833479SBarry Smith if self.framework.argDB['download-petsc'] == 0: 153f8833479SBarry Smith raise RuntimeError('No functioning PETSc located') 154f8833479SBarry Smith # Download and build PETSc 155f8833479SBarry Smith # Use only the already configured objects from this run 156f8833479SBarry Smith raise RuntimeError('Not implemented') 157f8833479SBarry Smith 158f8833479SBarry Smith def getDir(self): 159f8833479SBarry Smith if self.location: 160f8833479SBarry Smith return self.location[0] 161f8833479SBarry Smith return None 162f8833479SBarry Smith dir = property(getDir, doc = 'The PETSc root directory') 163f8833479SBarry Smith 164f8833479SBarry Smith def getArch(self): 165f8833479SBarry Smith if self.location: 166f8833479SBarry Smith return self.location[1] 167f8833479SBarry Smith return None 168f8833479SBarry Smith arch = property(getArch, doc = 'The PETSc architecture') 169f8833479SBarry Smith 170f8833479SBarry Smith def getFound(self): 171f8833479SBarry Smith return self.location and self.location in self.working 172f8833479SBarry Smith found = property(getFound, doc = 'Did we find a valid PETSc installation') 173f8833479SBarry Smith 174f8833479SBarry Smith def getName(self): 175f8833479SBarry Smith if self.location and self.location in self.working: 176f8833479SBarry Smith return self.working[self.location][0] 177f8833479SBarry Smith return None 178f8833479SBarry Smith name = property(getName, doc = 'The PETSc installation type') 179f8833479SBarry Smith 180f8833479SBarry Smith def getInclude(self, useTrial = 0): 181f8833479SBarry Smith if self.location and self.location in self.working: 182f8833479SBarry Smith return self.working[self.location][1] 183f8833479SBarry Smith elif useTrial and self.location and self.location in self.trial: 184f8833479SBarry Smith return self.trial[self.location][1] 185f8833479SBarry Smith return None 186f8833479SBarry Smith include = property(getInclude, doc = 'The PETSc include directories') 187f8833479SBarry Smith 188f8833479SBarry Smith def getLib(self, useTrial = 0): 189f8833479SBarry Smith if self.location and self.location in self.working: 190f8833479SBarry Smith return self.working[self.location][2] 191f8833479SBarry Smith elif useTrial and self.location and self.location in self.trial: 192f8833479SBarry Smith return self.trial[self.location][2] 193f8833479SBarry Smith return None 194f8833479SBarry Smith lib = property(getLib, doc = 'The PETSc libraries') 195f8833479SBarry Smith 196f8833479SBarry Smith def getVersion(self): 197f8833479SBarry Smith if self.location and self.location in self.working: 198f8833479SBarry Smith return self.working[self.location][3] 199f8833479SBarry Smith return None 200f8833479SBarry Smith version = property(getVersion, doc = 'The PETSc version') 201f8833479SBarry Smith 202f8833479SBarry Smith def getOtherIncludes(self): 203f8833479SBarry Smith if not hasattr(self, '_otherIncludes'): 204f8833479SBarry Smith includes = [] 205f8833479SBarry Smith includes.extend([self.headers.getIncludeArgument(inc) for inc in self.mpi.include]) 206f8833479SBarry Smith return ' '.join(includes) 207f8833479SBarry Smith return self._otherIncludes 208f8833479SBarry Smith def setOtherIncludes(self, otherIncludes): 209f8833479SBarry Smith self._otherIncludes = otherIncludes 210f8833479SBarry Smith otherIncludes = property(getOtherIncludes, setOtherIncludes, doc = 'Includes needed to compile PETSc') 211f8833479SBarry Smith 212f8833479SBarry Smith def getOtherLibs(self): 213f8833479SBarry Smith if not hasattr(self, '_otherLibs'): 214f8833479SBarry Smith libs = self.compilers.flibs[:] 215f8833479SBarry Smith libs.extend(self.mpi.lib) 216f8833479SBarry Smith libs.extend(self.blaslapack.lib) 217f8833479SBarry Smith return libs 218f8833479SBarry Smith return self._otherLibs 219f8833479SBarry Smith def setOtherLibs(self, otherLibs): 220f8833479SBarry Smith self._otherLibs = otherLibs 221f8833479SBarry Smith otherLibs = property(getOtherLibs, setOtherLibs, doc = 'Libraries needed to link PETSc') 222f8833479SBarry Smith 223f8833479SBarry Smith def checkLib(self, libraries): 224f8833479SBarry Smith '''Check for PETSc creation functions in libraries, which can be a list of libraries or a single library 225f8833479SBarry Smith - PetscInitialize from libpetsc 226f8833479SBarry Smith - VecCreate from libpetscvec 227f8833479SBarry Smith - MatCreate from libpetscmat 2289a42bb27SBarry Smith - DMDestroy from libpetscdm 229f8833479SBarry Smith - KSPCreate from libpetscksp 230f8833479SBarry Smith - SNESCreate from libpetscsnes 231f8833479SBarry Smith - TSCreate from libpetscts 232f8833479SBarry Smith ''' 233f8833479SBarry Smith if not isinstance(libraries, list): libraries = [libraries] 234f8833479SBarry Smith oldLibs = self.compilers.LIBS 235f8833479SBarry Smith self.libraries.pushLanguage(self.languages.clanguage) 2362c280183SJed Brown found = (self.libraries.check(libraries, 'PetscInitializeNoArguments', otherLibs = self.otherLibs, prototype = 'int PetscInitializeNoArguments(void);') and 2372c280183SJed Brown self.libraries.check(libraries, 'VecDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_Vec *Vec;int VecDestroy(Vec*);', call = 'VecDestroy((Vec*) 0)') and 2382c280183SJed Brown self.libraries.check(libraries, 'MatDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_Mat *Mat;int MatDestroy(Mat*);', call = 'MatDestroy((Mat*) 0)') and 2392c280183SJed Brown self.libraries.check(libraries, 'DMDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_DM *DA;int DMDestroy(DA*);', call = 'DMDestroy((DA*) 0)') and 2402c280183SJed Brown self.libraries.check(libraries, 'KSPDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_KSP *KSP;int KSPDestroy(KSP*);', call = 'KSPDestroy((KSP*) 0)') and 2412c280183SJed Brown self.libraries.check(libraries, 'SNESDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_SNES *SNES;int SNESDestroy(SNES*);', call = 'SNESDestroy((SNES*) 0)') and 2422c280183SJed Brown self.libraries.check(libraries, 'TSDestroy', otherLibs = self.otherLibs, prototype = 'typedef struct _p_TS *TS;int TSDestroy(TS*);', call = 'TSDestroy((TS*) 0)')) 243f8833479SBarry Smith self.libraries.popLanguage() 244f8833479SBarry Smith self.compilers.LIBS = oldLibs 245f8833479SBarry Smith return found 246f8833479SBarry Smith 247f8833479SBarry Smith def checkInclude(self, includeDir): 248d382aafbSBarry Smith '''Check that petscsys.h is present''' 249f8833479SBarry Smith oldFlags = self.compilers.CPPFLAGS 250f8833479SBarry Smith self.compilers.CPPFLAGS += ' '.join([self.headers.getIncludeArgument(inc) for inc in includeDir]) 251f8833479SBarry Smith if self.otherIncludes: 252f8833479SBarry Smith self.compilers.CPPFLAGS += ' '+self.otherIncludes 253f8833479SBarry Smith self.pushLanguage(self.languages.clanguage) 254d382aafbSBarry Smith found = self.checkPreprocess('#include <petscsys.h>\n') 255f8833479SBarry Smith self.popLanguage() 256f8833479SBarry Smith self.compilers.CPPFLAGS = oldFlags 257f8833479SBarry Smith return found 258f8833479SBarry Smith 259f8833479SBarry Smith def checkPETScLink(self, includes, body, cleanup = 1, codeBegin = None, codeEnd = None, shared = None): 260f8833479SBarry Smith '''Analogous to checkLink(), but the PETSc includes and libraries are automatically provided''' 261f8833479SBarry Smith success = 0 262f8833479SBarry Smith oldFlags = self.compilers.CPPFLAGS 263f8833479SBarry Smith self.compilers.CPPFLAGS += ' '.join([self.headers.getIncludeArgument(inc) for inc in self.getInclude(useTrial = 1)]) 264f8833479SBarry Smith if self.otherIncludes: 265f8833479SBarry Smith self.compilers.CPPFLAGS += ' '+self.otherIncludes 266f8833479SBarry Smith oldLibs = self.compilers.LIBS 267f8833479SBarry Smith self.compilers.LIBS = ' '.join([self.libraries.getLibArgument(lib) for lib in self.getLib(useTrial = 1)+self.otherLibs])+' '+self.compilers.LIBS 268f8833479SBarry Smith if self.checkLink(includes, body, cleanup, codeBegin, codeEnd, shared): 269f8833479SBarry Smith success = 1 270f8833479SBarry Smith self.compilers.CPPFLAGS = oldFlags 271f8833479SBarry Smith self.compilers.LIBS = oldLibs 272f8833479SBarry Smith return success 273f8833479SBarry Smith 274f8833479SBarry Smith def checkWorkingLink(self): 275f8833479SBarry Smith '''Checking that we can link a PETSc executable''' 276f8833479SBarry Smith self.pushLanguage(self.languages.clanguage) 2779566063dSJacob Faibussowitsch if not self.checkPETScLink('#include <petsctime.h>\n', 'PetscLogDouble time;\n\nPetscCall(PetscTime(&time));\n'): 278f8833479SBarry Smith self.logPrint('PETSc cannot link, which indicates a problem with the PETSc installation') 279f8833479SBarry Smith return 0 280f8833479SBarry Smith self.logPrint('PETSc can link with '+self.languages.clanguage) 281f8833479SBarry Smith self.popLanguage() 282f8833479SBarry Smith 283f8833479SBarry Smith if hasattr(self.compilers, 'CXX') and self.languages.clanguage == 'C': 284f8833479SBarry Smith self.pushLanguage('C++') 285f8833479SBarry Smith self.sourceExtension = '.C' 2869566063dSJacob Faibussowitsch if not self.checkPETScLink('#include <petsctime.h>\n', 'PetscLogDouble time;\n\nPetscCall(PetscTime(&time));\n'): 287f8833479SBarry Smith self.logPrint('PETSc cannot link C++ but can link C, which indicates a problem with the PETSc installation') 288f8833479SBarry Smith self.popLanguage() 289f8833479SBarry Smith return 0 290f8833479SBarry Smith self.popLanguage() 291f8833479SBarry Smith self.logPrint('PETSc can link with C++') 292f8833479SBarry Smith 293f8833479SBarry Smith if hasattr(self.compilers, 'FC'): 294f8833479SBarry Smith self.pushLanguage('FC') 295f8833479SBarry Smith self.sourceExtension = '.F' 2968563dfccSBarry Smith if not self.checkPETScLink('', ' integer ierr\n real time\n call PetscTime(time, ierr)\n'): 297f8833479SBarry 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') 298f8833479SBarry Smith self.popLanguage() 299f8833479SBarry Smith return 0 300f8833479SBarry Smith self.popLanguage() 301f8833479SBarry Smith self.logPrint('PETSc can link with Fortran') 302f8833479SBarry Smith return 1 303f8833479SBarry Smith 304f8833479SBarry Smith def checkSharedLibrary(self, libraries): 305f8833479SBarry Smith '''Check that the libraries for PETSc are shared libraries''' 3067fca349cSMatthew G. Knepley if config.setCompilers.Configure.isDarwin(self.log): 307f8833479SBarry Smith # on Apple if you list the MPI libraries again you will generate multiply defined errors 308f8833479SBarry Smith # since they are already copied into the PETSc dynamic library. 309f8833479SBarry Smith self.setOtherLibs([]) 310f8833479SBarry Smith self.pushLanguage(self.languages.clanguage) 311ace3abfcSBarry 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) 312f8833479SBarry Smith self.popLanguage() 313f8833479SBarry Smith return isShared 314f8833479SBarry Smith 315f8833479SBarry Smith def configureVersion(self): 316f8833479SBarry Smith '''Determine the PETSc version''' 317f8833479SBarry Smith majorRE = re.compile(r'^#define PETSC_VERSION_MAJOR([\s]+)(?P<versionNum>\d+)[\s]*$'); 318f8833479SBarry Smith minorRE = re.compile(r'^#define PETSC_VERSION_MINOR([\s]+)(?P<versionNum>\d+)[\s]*$'); 319f8833479SBarry Smith subminorRE = re.compile(r'^#define PETSC_VERSION_SUBMINOR([\s]+)(?P<versionNum>\d+)[\s]*$'); 320f8833479SBarry 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]*$'); 321c6ef1b5bSJed Brown input = open(os.path.join(self.dir, 'include', 'petscversion.h')) 322f8833479SBarry Smith lines = [] 323f8833479SBarry Smith majorNum = 'Unknown' 324f8833479SBarry Smith minorNum = 'Unknown' 325f8833479SBarry Smith subminorNum = 'Unknown' 326f8833479SBarry Smith self.date = 'Unknown' 327f8833479SBarry Smith for line in input.readlines(): 328f8833479SBarry Smith m1 = majorRE.match(line) 329f8833479SBarry Smith m2 = minorRE.match(line) 330f8833479SBarry Smith m3 = subminorRE.match(line) 331f8833479SBarry Smith m5 = dateRE.match(line) 332f8833479SBarry Smith if m1: 333f8833479SBarry Smith majorNum = int(m1.group('versionNum')) 334f8833479SBarry Smith elif m2: 335f8833479SBarry Smith minorNum = int(m2.group('versionNum')) 336f8833479SBarry Smith elif m3: 337f8833479SBarry Smith subminorNum = int(m3.group('versionNum')) 338f8833479SBarry Smith 33966d79e26SBarry Smith if m5: 340f8833479SBarry Smith self.date = time.strftime('%b %d, %Y', time.localtime(time.time())) 341f8833479SBarry Smith lines.append('#define PETSC_VERSION_DATE'+m5.group(1)+'"'+self.date+'"\n') 342f8833479SBarry Smith else: 343f8833479SBarry Smith lines.append(line) 344f8833479SBarry Smith input.close() 34566d79e26SBarry Smith self.logPrint('Found PETSc version (%s,%s,%s) on %s' % (majorNum, minorNum, subminorNum, self.date)) 346f8833479SBarry Smith return '%d.%d.%d' % (majorNum, minorNum, subminorNum) 347f8833479SBarry Smith 348f8833479SBarry Smith def includeGuesses(self, path = None): 349f8833479SBarry Smith '''Return all include directories present in path or its ancestors''' 350f8833479SBarry Smith if not path: 351f8833479SBarry Smith yield [] 352f8833479SBarry Smith while path: 353f8833479SBarry Smith dir = os.path.join(path, 'include') 354f8833479SBarry Smith if os.path.isdir(dir): 355f8833479SBarry Smith yield [dir, os.path.join(path, self.arch,'include')] 356f8833479SBarry Smith if path == '/': 357f8833479SBarry Smith return 358f8833479SBarry Smith path = os.path.dirname(path) 359f8833479SBarry Smith return 360f8833479SBarry Smith 361f8833479SBarry Smith def libraryGuesses(self, root = None): 362f8833479SBarry Smith '''Return standard library name guesses for a given installation root''' 363f8833479SBarry Smith libs = ['ts', 'snes', 'ksp', 'dm', 'mat', 'vec', ''] 364f8833479SBarry Smith if root: 365f8833479SBarry Smith d = os.path.join(root, 'lib', self.arch) 366f8833479SBarry Smith if not os.path.isdir(d): 367f8833479SBarry Smith self.logPrint('', 3, 'petsc') 368f8833479SBarry Smith return 369f8833479SBarry Smith yield [os.path.join(d, 'libpetsc'+lib+'.a') for lib in libs] 370f8833479SBarry Smith else: 371f8833479SBarry Smith yield ['libpetsc'+lib+'.a' for lib in libs] 372f8833479SBarry Smith return 373f8833479SBarry Smith 374f8833479SBarry Smith def configureLibrary(self): 3752c280183SJed Brown '''Find a working PETSc''' 376f8833479SBarry Smith for location, name in self.trial.items(): 377f8833479SBarry Smith self.framework.logPrintDivider() 378f8833479SBarry Smith self.framework.logPrint('Checking for a functional PETSc in '+name+', location/origin '+str(location)) 379f8833479SBarry Smith lib = None 380f8833479SBarry Smith include = None 381f8833479SBarry Smith found = 0 382f8833479SBarry Smith for libraries in self.libraryGuesses(location[0]): 383f8833479SBarry Smith if self.checkLib(libraries): 384f8833479SBarry Smith lib = libraries 385f8833479SBarry Smith for includeDir in self.includeGuesses(location[0]): 386f8833479SBarry Smith if self.checkInclude(includeDir): 387f8833479SBarry Smith include = includeDir 388f8833479SBarry Smith self.trial[location] = (name, include, lib, 'Unknown') 389f8833479SBarry Smith if self.executeTest(self.checkWorkingLink): 390f8833479SBarry Smith found = 1 391f8833479SBarry Smith break 392f8833479SBarry Smith else: 393f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 394f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkWorkingLink test') 395f8833479SBarry Smith else: 396f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 397f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkInclude test with includeDir: '+str(includeDir)) 398f8833479SBarry Smith if not found: 399f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 400f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkIncludes test') 401f8833479SBarry Smith continue 402f8833479SBarry Smith else: 403f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 404f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkLib test with libraries: '+str(libraries)) 405f8833479SBarry Smith continue 406f8833479SBarry Smith if self.framework.argDB['with-petsc-shared']: 407f8833479SBarry Smith if not self.executeTest(self.checkSharedLibrary, [libraries]): 408f8833479SBarry Smith self.framework.logPrintDivider(single = 1) 409f8833479SBarry Smith self.framework.logPrint('PETSc in '+name+', location/origin '+str(location)+' failed checkSharedLibrary test with libraries: '+str(libraries)) 410f8833479SBarry Smith found = 0 411f8833479SBarry Smith if found: 412f8833479SBarry Smith break 413f8833479SBarry Smith if found: 414f8833479SBarry Smith version = self.executeTest(self.configureVersion) 415f8833479SBarry Smith self.working[location] = (name, include, lib, version) 416f8833479SBarry Smith break 417f8833479SBarry Smith if found: 418f8833479SBarry Smith self.logPrint('Choose PETSc '+self.version+' in '+self.name) 419f8833479SBarry Smith else: 420f8833479SBarry Smith raise RuntimeError('Could not locate any functional PETSc') 421f8833479SBarry Smith return 422f8833479SBarry Smith 423f8833479SBarry Smith def setOutput(self): 424f8833479SBarry Smith '''Add defines and substitutions 425f8833479SBarry Smith - HAVE_PETSC is defined if a working PETSc is found 426f8833479SBarry Smith - PETSC_INCLUDE and PETSC_LIB are command line arguments for the compile and link''' 427f8833479SBarry Smith if self.found: 428f8833479SBarry Smith self.addDefine('HAVE_PETSC', 1) 429f8833479SBarry Smith self.addSubstitution('PETSC_INCLUDE', ' '.join([self.headers.getIncludeArgument(inc) for inc in self.include])) 430f8833479SBarry Smith self.addSubstitution('PETSC_LIB', ' '.join(map(self.libraries.getLibArgument, self.lib))) 431f8833479SBarry Smith return 432f8833479SBarry Smith 433f8833479SBarry Smith def configure(self): 434f8833479SBarry Smith self.executeTest(self.configureLibrary) 435f8833479SBarry Smith self.setOutput() 436f8833479SBarry Smith return 437f8833479SBarry Smith 438f8833479SBarry Smithif __name__ == '__main__': 439f8833479SBarry Smith import config.framework 440f8833479SBarry Smith import sys 441f8833479SBarry Smith framework = config.framework.Framework(sys.argv[1:]) 442f8833479SBarry Smith framework.setup() 443f8833479SBarry Smith framework.addChild(Configure(framework)) 444f8833479SBarry Smith framework.configure() 445f8833479SBarry Smith framework.dumpSubstitutions() 446