diff --git a/bin/EmergeBase.py b/bin/EmergeBase.py index 58a86de56..984e69d46 100644 --- a/bin/EmergeBase.py +++ b/bin/EmergeBase.py @@ -1,291 +1,293 @@ # # copyright (c) 2009 Ralf Habacker # import os import sys import datetime from ctypes import * import EmergeDebug import utils import portage import compiler from EmergeConfig import * import utils ## @todo complete a release and binary merge dir below rootdir # 1. enable build type related otDmerge install settings # 2a. use different install databases for debug and release # 3. binary packages which are build type independent should be # marked in both databases or should have a separate install database # question: How to detect reliable this case ? class EmergeBase(object): """base class for emerge system - holds attributes and methods required by base classes""" def __init__( self): # TODO: some __init__ of subclasses need to already have been # called here. That is really the wrong way round. object.__init__(self) EmergeDebug.debug("EmergeBase.__init__ called", 2) - self.filename, self.category, self.subpackage, self.package, mod = portage.PortageInstance._CURRENT_MODULE#ugly workaround we need to replace the constructor if not hasattr(self, 'subinfo'): + self.filename, self.category, self.subpackage, self.package, mod = portage.PortageInstance._CURRENT_MODULE # ugly workaround we need to replace the constructor self.subinfo = mod.subinfo(self, portage.PortageInstance.options) - + self.subinfo.__evilHack = portage.PortageInstance._CURRENT_MODULE#ugly workaround we need to replace the constructor + else: + self.filename, self.category, self.subpackage, self.package, mod = self.subinfo.__evilHack if not hasattr(self, 'buildSystemType'): self.buildSystemType = None # if implicit build time dependency is wanted, depend on internal packages # for this class and all of its ancestor classes if emergeSettings.getboolean("General", "EMERGE_ENABLE_IMPLICID_BUILDTIME_DEPENDENCIES", False): for cls in type(self).mro(): className = cls.__name__ packageName = 'internal/%s' % className if os.path.exists(os.path.join(EmergeStandardDirs.emergeRoot() , 'emerge', 'portage', 'internal', className, '%s-internal.py' % className)): if self.subinfo and not packageName in self.subinfo.buildDependencies: self.subinfo.buildDependencies[packageName] = 'default' if hasattr(self,'alreadyCalled'): return self.alreadyCalled = True self.versioned = False self.CustomDefines = "" self.createCombinedPackage = False ## specifies if a build type related root directory should be used self.useBuildTypeRelatedMergeRoot = False if emergeSettings.getboolean("General","EMERGE_MERGE_ROOT_WITH_BUILD_TYPE", False): self.useBuildTypeRelatedMergeRoot = True self.isoDateToday = str( datetime.date.today() ).replace('-', '') def __str__(self): if self.subpackage: return "%s/%s/%s" % (self.category,self.subpackage,self.package) else: return "%s/%s" % (self.category,self.package) @property def noFetch(self): return emergeSettings.getboolean("General", "WorkOffline", False) @property def noFast(self): return emergeSettings.getboolean("General", "EMERGE_NOFAST", True ) @property def noClean(self): return emergeSettings.getboolean("General", "EMERGE_NOCLEAN", False ) @property def forced(self): return emergeSettings.getboolean("General", "EMERGE_FORCED", False ) @property def buildTests(self): return emergeSettings.getboolean("Compile", "BuildTests", False ) def __adjustPath(self, directory): """return adjusted path""" if not self.subinfo.options.useShortPathes: return directory path = c_char_p(directory) length = windll.kernel32.GetShortPathNameA(path, 0, 0) if length == 0: return directory buf = create_string_buffer('\000' * (length + 1)) windll.kernel32.GetShortPathNameA(path, byref(buf), length+1) # ignore function result... EmergeDebug.debug("converting " + directory + " to " + buf.value) return buf.value def buildType(self): """return currently selected build type""" return emergeSettings.get("Compile","BuildType") def compiler(self): """deprecated""" """return currently selected compiler""" return compiler.getCompilerName() def buildArchitecture(self): """return the target CPU architecture""" compiler.architecture() def workDirPattern(self): """return base directory name for package related work directory""" directory = "" if self.subinfo.options.useCompilerType == True: directory += "%s-" % compiler.getCompilerName() if self.subinfo.options.cmake.useIDE or self.subinfo.options.cmake.openIDE: directory += "ide-" if self.subinfo.options.useBuildType == False: directory += "%s" % (self.buildTarget) elif( self.buildType() == None ): directory += "%s-%s" % ("default", self.buildTarget) else: directory += "%s-%s" % (self.buildType(), self.buildTarget) return directory def imageDirPattern(self): """return base directory name for package related image directory""" directory = "image" if self.subinfo.options.useCompilerType == True: directory += '-' + compiler.getCompilerName() if self.subinfo.options.useBuildType == True: directory += '-' + self.buildType() directory += '-' + self.buildTarget return directory def sourceDir(self, dummyIndex=0): utils.abstract() def packageDir(self): """ add documentation """ return self.__adjustPath( portage.getDirname( self.category, self.package ) ) def buildRoot(self): """return absolute path to the root directory of the currently active package""" buildroot = os.path.join( EmergeStandardDirs.emergeRoot(), "build", self.category, self.package ) return self.__adjustPath(buildroot) def workDir(self): """return absolute path to the 'work' subdirectory of the currently active package""" _workDir = os.path.join( self.buildRoot(), "work" ) return self.__adjustPath(_workDir) def buildDir(self): EmergeDebug.debug("EmergeBase.buildDir() called", 2) builddir = os.path.join(self.workDir(), self.workDirPattern()) if self.subinfo.options.unpack.unpackIntoBuildDir and self.subinfo.hasTargetSourcePath(): builddir = os.path.join(builddir, self.subinfo.targetSourcePath()) EmergeDebug.debug("package builddir is: %s" % builddir, 2) return self.__adjustPath(builddir) def imageDir(self): """return absolute path to the install root directory of the currently active package """ imageDir = os.path.join( self.buildRoot(), self.imageDirPattern() ) return self.__adjustPath(imageDir) def installDir(self): """return absolute path to the install directory of the currently active package. This path may point to a subdir of imageDir() in case @ref info.targetInstallPath is used """ if self.subinfo.hasInstallPath(): installDir = os.path.join( self.imageDir(), self.subinfo.installPath()) elif self.subinfo.options.install.installPath: installDir = os.path.join(self.imageDir(), self.subinfo.options.install.installPath) else: installDir = self.imageDir() return self.__adjustPath(installDir) def mergeSourceDir(self): """return absolute path to the merge source directory of the currently active package. This path may point to a subdir of imageDir() in case @ref info.targetInstallPath for a specific target or @ref self.subinfo.options.merge.sourcePath is used """ if self.subinfo.hasMergeSourcePath(): directory = os.path.join( self.imageDir(), self.subinfo.mergeSourcePath() ) elif not self.subinfo.options.merge.sourcePath == None: directory = os.path.join( self.imageDir(), self.subinfo.options.merge.sourcePath ) else: directory = self.imageDir() return self.__adjustPath(directory) def mergeDestinationDir(self): """return absolute path to the merge destination directory of the currently active package. This path may point to a subdir of rootdir in case @ref info.targetMergePath for a specific build target or @ref self.subinfo.options.merge.destinationPath is used """ if self.subinfo.hasMergePath(): directory = os.path.join( EmergeStandardDirs.emergeRoot(), self.subinfo.mergePath() ) elif not self.subinfo.options.merge.destinationPath == None: directory = os.path.join( EmergeStandardDirs.emergeRoot(), self.subinfo.options.merge.destinationPath ) elif not self.useBuildTypeRelatedMergeRoot or self.subinfo.options.merge.ignoreBuildType: directory = EmergeStandardDirs.emergeRoot() elif self.buildType() == 'Debug': directory = os.path.join(EmergeStandardDirs.emergeRoot(),'debug') elif self.buildType() == 'Release': directory = os.path.join(EmergeStandardDirs.emergeRoot(),'release') elif self.buildType() == 'RelWithDebInfo': directory = os.path.join(EmergeStandardDirs.emergeRoot(),'relwithdebinfo') else: directory = EmergeStandardDirs.emergeRoot() return self.__adjustPath(directory) def packageDestinationDir( self, withBuildType=True ): """return absolute path to the directory where binary packages are placed into. Default is to optionally append build type subdirectory""" EmergeDebug.debug("EmergeBase.packageDestinationDir called", 2) dstpath = emergeSettings.get("General","EMERGE_PKGDSTDIR", os.path.join( EmergeStandardDirs.emergeRoot(), "tmp" ) ) if withBuildType: if emergeSettings.getboolean("General", "EMERGE_MERGE_ROOT_WITH_BUILD_TYPE", False ): dstpath = os.path.join( dstpath, self.buildType()) if not os.path.exists(dstpath): utils.createDir(dstpath) return dstpath @property def buildTarget(self): return self.subinfo.buildTarget @property def version(self): return self.subinfo.defaultTarget @property def rootdir(self): return EmergeStandardDirs.emergeRoot() def enterBuildDir(self): EmergeDebug.trace("EmergeBase.enterBuildDir called") if ( not os.path.exists( self.buildDir() ) ): os.makedirs( self.buildDir() ) EmergeDebug.debug("creating: %s" % self.buildDir()) os.chdir( self.buildDir() ) EmergeDebug.debug("entering: %s" % self.buildDir()) def enterSourceDir(self): if ( not os.path.exists( self.sourceDir() ) ): return False EmergeDebug.warning("entering the source directory!") os.chdir( self.sourceDir() ) EmergeDebug.debug("entering: %s" % self.sourceDir()) def system( self, command, errorMessage="", debuglevel=1, **kw): """convencience function for running system commands. This method prints a debug message and then runs a system command. If the system command returns with errors the method prints an error message and exits if @ref self.subinfo.options.exitOnErrors is true""" if utils.system( command, **kw): return True if self.subinfo.options.exitOnErrors: EmergeDebug.warning("while running %s cmd: %s" % (errorMessage, str(command))) else: EmergeDebug.warning("while running %s cmd: %s" % (errorMessage, str(command))) return False def proxySettings(self): host = emergeSettings.get("General", 'EMERGE_PROXY_HOST', "") port = emergeSettings.get("General", 'EMERGE_PROXY_PORT', "") username = emergeSettings.get("General", 'EMERGE_PROXY_USERNAME', "") password = emergeSettings.get("General", 'EMERGE_PROXY_PASSWORD', "") return [host, port, username, password] diff --git a/bin/Package/SourceOnlyPackageBase.py b/bin/Package/SourceOnlyPackageBase.py new file mode 100644 index 000000000..8bf05ca53 --- /dev/null +++ b/bin/Package/SourceOnlyPackageBase.py @@ -0,0 +1,34 @@ +from Package.PackageBase import * +from Source.MultiSource import * +from BuildSystem.BuildSystemBase import * +from Packager.PackagerBase import * + + +class SourceOnlyPackageBase( PackageBase, MultiSource, BuildSystemBase, PackagerBase ): + """provides a base class for source dependency packages""" + def __init__( self ): + EmergeDebug.debug("SourceOnlyPackageBase.__init__ called", 2) + PackageBase.__init__(self) + MultiSource.__init__(self) + BuildSystemBase.__init__(self, "") + PackagerBase.__init__(self) + +# from BuildSystemBase: + def configure( self ): + return True + + def install( self ): + return True + + def uninstall( self ): + return True + + def runTests( self ): + return True + + def make( self ): + return True + +# from PackagerBase: + def createPackage( self ): + return True \ No newline at end of file diff --git a/bin/Package/VirtualPackageBase.py b/bin/Package/VirtualPackageBase.py index e739e9587..7015be622 100644 --- a/bin/Package/VirtualPackageBase.py +++ b/bin/Package/VirtualPackageBase.py @@ -1,62 +1,40 @@ -import EmergeDebug -from Package.PackageBase import * -from Source.SourceBase import * -from BuildSystem.BuildSystemBase import * -from Packager.PackagerBase import * +from Package.SourceOnlyPackageBase import * import portage -class VirtualPackageBase( PackageBase, SourceBase, BuildSystemBase, PackagerBase ): +class VirtualPackageBase( SourceOnlyPackageBase): """provides a base class for virtual packages""" def __init__( self ): EmergeDebug.debug("VirtualPackageBase.__init__ called", 2) - PackageBase.__init__( self ) - SourceBase.__init__( self ) - BuildSystemBase.__init__( self, "" ) - PackagerBase.__init__( self ) + SourceOnlyPackageBase.__init__( self ) # from SourceBase: def fetch( self, dummyRepoSource=None): return True def unpack( self ): return True def createPatch( self ): return True def getUrls( self ): return True def repositoryUrl( self, dummyIndex=0 ): return "" def repositoryUrlCount( self ): return 0 def localFileNamesBase( self ): return [] -# from BuildSystemBase: - def configure( self ): - return True - - def install( self ): - return True - - def uninstall( self ): - return True - - def runTests( self ): - return True - - def make( self ): - return True # from PackagerBase: def createPackage( self ): for dep in self.subinfo.dependencies: category,package = dep.split( "/" ) if not portage.getPackageInstance(category,package).createPackage(): return False return True diff --git a/bin/Source/ArchiveSource.py b/bin/Source/ArchiveSource.py index 1cc2fd1d8..501d0171f 100644 --- a/bin/Source/ArchiveSource.py +++ b/bin/Source/ArchiveSource.py @@ -1,242 +1,241 @@ # # copyright (c) 2009 Ralf Habacker # import shutil import EmergeDebug from Source.SourceBase import * import EmergeHash class ArchiveSource(SourceBase): """ file download source""" - filenames = [] def __init__(self, subinfo=None): EmergeDebug.debug("ArchiveSource.__init__ called", 2) if subinfo: self.subinfo = subinfo SourceBase.__init__( self ) def repositoryUrl(self, index=0): """all repository pathes""" if self.subinfo.hasTarget(): return os.path.basename( self.subinfo.targetAt(index) ) else: return False def repositoryUrlCount(self): return self.subinfo.targetCount() def localFileNames(self): # pylint: disable=E0202 # but I have no idea why pylint thinks this overrides # MultiSource.localFileNames if self.subinfo.archiveName() == [""]: return self.localFileNamesBase() return self.subinfo.archiveName() def localFileNamesBase(self): """ collect local filenames """ EmergeDebug.debug("ArchiveSource.localFileNamesBase called", 2) filenames = [] for i in range(self.repositoryUrlCount()): filenames.append( os.path.basename( self.repositoryUrl( i ) ) ) return filenames def __checkFilesPresent(self, filenames): """check if all files for the current target are available""" for filename in filenames: path = os.path.join(EmergeStandardDirs.downloadDir(), filename) if self.subinfo.hasTargetDigests(): if not os.path.exists(path): return False elif self.subinfo.hasTargetDigestUrls(): algorithm = EmergeHash.HashAlgorithm.SHA1 if type(self.subinfo.targetDigestUrl()) == tuple: _, algorithm = self.subinfo.targetDigestUrl() if not os.path.exists(path + algorithm.fileEnding()): return False elif not os.path.exists(path): return False return True def fetch( self, dummyRepopath = None ): """fetch normal tarballs""" EmergeDebug.debug("ArchiveSource.fetch called", 2) filenames = self.localFileNames() if ( self.noFetch ): EmergeDebug.debug("skipping fetch (--offline)") return True self.setProxy() if self.subinfo.hasTarget(): if self.__checkFilesPresent(filenames): EmergeDebug.debug("files and digests available, no need to download files", 1) return True result = utils.getFiles( self.subinfo.target(), EmergeStandardDirs.downloadDir() , filenames = self.subinfo.archiveName() ) if not result: EmergeDebug.debug("failed to download files", 1) return False if result and self.subinfo.hasTargetDigestUrls(): if type(self.subinfo.targetDigestUrl()) == tuple: url, alg = self.subinfo.targetDigestUrl() return utils.getFiles(url, EmergeStandardDirs.downloadDir(), filenames = self.subinfo.archiveName()[0] + EmergeHash.HashAlgorithm.fileEndings().get(alg)) else: return utils.getFiles( self.subinfo.targetDigestUrl(), EmergeStandardDirs.downloadDir(), filenames = '' ) else: EmergeDebug.debug("no digestUrls present", 2) return True else: return utils.getFiles( "", EmergeStandardDirs.downloadDir() ) def checkDigest(self): EmergeDebug.debug("ArchiveSource.checkDigest called", 2) filenames = self.localFileNames() if self.subinfo.hasTargetDigestUrls(): EmergeDebug.debug("check digests urls", 1) if not EmergeHash.checkFilesDigests(EmergeStandardDirs.downloadDir(), filenames): EmergeDebug.error("invalid digest file") return False elif self.subinfo.hasTargetDigests(): EmergeDebug.debug("check digests", 1) digests, algorithm = self.subinfo.targetDigest() if not EmergeHash.checkFilesDigests( EmergeStandardDirs.downloadDir(), filenames, digests, algorithm): EmergeDebug.error("invalid digest file") return False else: EmergeDebug.debug("print source file digests", 1) EmergeHash.printFilesDigests(EmergeStandardDirs.downloadDir(), filenames, self.subinfo.buildTarget, algorithm = EmergeHash.HashAlgorithm.SHA256) return True def unpack(self): """unpacking all zipped(gz, zip, bz2) tarballs""" EmergeDebug.debug("ArchiveSource.unpack called", 2) filenames = self.localFileNames() # TODO: this might delete generated patches utils.cleanDirectory(self.workDir()) if not self.checkDigest(): return False binEndings = (".exe", ".bat", ".msi") for filename in filenames: if filename.endswith(binEndings): filePath = os.path.abspath( os.path.join(EmergeStandardDirs.downloadDir(), filename) ) if self.subinfo.options.unpack.runInstaller: _, ext = os.path.splitext( filename ) if ext == ".exe": return utils.system("%s" % filePath ) elif ( ext == ".msi" ): return utils.system("msiexec /package %s" % filePath ) if not utils.copyFile( filePath, os.path.join(self.workDir(), filename) ): return False else: if not utils.unpackFile( EmergeStandardDirs.downloadDir(), filename, self.workDir()): return False ret = self.applyPatches() if emergeSettings.getboolean("General","EMERGE_HOLD_ON_PATCH_FAIL",False): return ret return True def getUrls( self ): print(self.subinfo.target()) print(self.subinfo.targetDigestUrl()) return True def createPatch( self ): """ unpacking all zipped(gz, zip, bz2) tarballs a second time and making a patch """ diffExe = os.path.join( self.rootdir, "dev-utils", "bin", "diff.exe" ) if not os.path.exists( diffExe ): EmergeDebug.die("could not find diff tool, please run 'emerge diffutils'") # get the file paths of the tarballs filenames = self.localFileNames() destdir = self.workDir() # it makes no sense to make a diff against nothing if ( not os.path.exists( self.sourceDir() ) ): EmergeDebug.error("source directory doesn't exist, please run unpack first") return False EmergeDebug.debug("unpacking files into work root %s" % destdir, 1) # make a temporary directory so the original packages don't overwrite the already existing ones tmpdir = os.path.join( destdir, "tmp" ) unpackDir = tmpdir utils.cleanDirectory( unpackDir ) if ( not os.path.exists( unpackDir ) ): os.mkdir( unpackDir ) if ( not os.path.exists( unpackDir ) ): os.mkdir( unpackDir ) # unpack all packages for filename in filenames: EmergeDebug.debug("unpacking this file: %s" % filename, 1) if ( not utils.unpackFile( EmergeStandardDirs.downloadDir(), filename, unpackDir ) ): return False packagelist = os.listdir( tmpdir ) # apply all patches only ommitting the last one, this makes it possible to always work on the latest patch # for future work, it might be interesting to switch patches on and off at will, this probably needs an # own patch management though patchName = None if self.subinfo.hasTarget() or self.subinfo.hasSvnTarget(): patches = self.subinfo.patchesToApply() if not isinstance(patches, list): patches = list([patches]) for fileName, patchdepth in patches[:-1]: EmergeDebug.debug("applying patch %s with patchlevel: %s" % (fileName, patchdepth)) if not self.applyPatch( fileName, patchdepth, os.path.join( tmpdir, packagelist[ 0 ] ) ): return False if patches[-1][0]: patchName = os.path.join( self.buildRoot(), patches[-1][0] ) # move the packages up and rename them to be different from the original source directory for directory in packagelist: # if the source or dest directory already exists, remove the occurance instead if os.path.exists( os.path.join( destdir, directory + ".orig" ) ): shutil.rmtree( os.path.join( destdir, directory + ".orig" ) ) shutil.move( os.path.join( tmpdir, directory ), os.path.join( destdir, directory + ".orig" ) ) os.chdir( destdir ) for directory in packagelist: if not patchName: patchName = os.path.join( self.buildRoot(), "%s-%s.diff" % ( directory, \ str( datetime.date.today() ).replace('-', '') ) ) cmd = "diff -Nrub -x *~ -x *\.rej -x *\.orig -x*\.o %s.orig %s > %s || echo 0" % ( directory, directory, patchName ) if not self.system( cmd ): return False EmergeDebug.debug("patch created at %s" % patchName) # remove all directories that are not needed any more after making the patch # disabled for now #for directory in packagelist: # shutil.rmtree( directory + ".orig" ) # remove the temporary directory, it should be empty after all directories have been moved up os.rmdir( tmpdir ) return True def sourceVersion( self ): """ return a version based on the file name of the current target """ # we hope that the build target is equal to the version that is build return self.subinfo.buildTarget diff --git a/bin/Source/MultiSource.py b/bin/Source/MultiSource.py index c47c83235..834cb69cb 100644 --- a/bin/Source/MultiSource.py +++ b/bin/Source/MultiSource.py @@ -1,92 +1,98 @@ # # copyright (c) 2009 Ralf Habacker # import EmergeDebug import utils from Source.SourceFactory import * class MultiSource(object): """ provides multi source type api """ def __init__(self): object.__init__(self) EmergeDebug.trace("MultiSource __init__", 2) + self.__source = None + + @property + def source(self): # pylint: disable=E1101 # multiple inheritance: MultiSource is never the only # superclass, others define self.source, self.subinfo etc. # TODO: This code should mostly be in the class defining self.source etc. - self.source = SourceFactory(self.subinfo) - self.source.localFileNames = self.localFileNames.__get__(self, MultiSource) + if not self.__source: + self.__source = SourceFactory(self.subinfo) + self.__source.localFileNames = self.localFileNames.__get__(self, MultiSource) + return self.__source def localFileNames( self ): EmergeDebug.trace("MultiSource localFileNames", 2) if self.subinfo.archiveName() == "": return self.source.localFileNamesBase() if isinstance(self.subinfo.archiveName(), (list, tuple)): return self.subinfo.archiveName() else: return (self.subinfo.archiveName(), ) def fetch( self, repopath = None ): EmergeDebug.trace("MultiSource fetch", 2) return self.source.fetch( repopath ) def checkDigest(self): EmergeDebug.trace("MultiSource checkDigest", 2) return self.source.checkDigest() def unpack(self): EmergeDebug.trace("MultiSource unpack", 2) # pylint: disable=E1101 # multiple inheritance: MultiSource is never the only # superclass, others define self.buildSystemType. self.source.buildSystemType = self.buildSystemType return self.source.unpack() def checkoutDir(self): EmergeDebug.trace("MultiSource checkoutDir", 2) return self.source.checkoutDir() def sourceDir(self): EmergeDebug.trace("MultiSource sourceDir", 2) return self.source.sourceDir() def repositoryUrl(self, index=0): EmergeDebug.trace("MultiSource repositoryUrl", 2) return self.source.repositoryUrl(index) def repositoryUrlCount(self): EmergeDebug.trace("MultiSource repositoryUrlCount", 2) return self.source.repositoryUrlCount() def applyPatches(self): EmergeDebug.trace("MultiSource applyPatches", 2) return self.source.applyPatches() def applyPatch(self): raise Exception('MultiSource.applyPatch is deprecated. ' 'it calls self.source.applyPatch without arguments which must fail') # utils.trace( "MultiSource applyPatch", 2 ) # return self.source.applyPatch() def createPatch(self): EmergeDebug.trace("MultiSource createPatch", 2) return self.source.createPatch() def getUrls(self): EmergeDebug.trace("MultiSource getUrls", 2) return self.source.getUrls() def sourceVersion(self): EmergeDebug.trace("MultiSource sourceVersion", 2) return self.source.sourceVersion() def sourceRevision(self): EmergeDebug.trace("MultiSource sourceVersion", 2) return self.source.sourceRevision() def printSourceVersion(self): EmergeDebug.trace("MultiSource printSourceVersion", 2) print(self.source.sourceVersion()) return True diff --git a/bin/info.py b/bin/info.py index b2417088e..f429e8179 100644 --- a/bin/info.py +++ b/bin/info.py @@ -1,282 +1,278 @@ ## # # @package this module contains the information class # the current work here is to access members only # by methods to be able to separate the access from # the definition import datetime import os from collections import OrderedDict import EmergeDebug import utils import compiler from options import * import VersionInfo import EmergeHash class infoclass(object): """this module contains the information class""" def __init__( self, parent, optionList=[]): ### package options self.parent = parent self.options = Options(optionList) self.versionInfo = VersionInfo.VersionInfo(self) self.targets = OrderedDict() self.archiveNames = OrderedDict() # Specifiy that the fetched source should be placed into a # subdirectory of the default source directory self.targetInstSrc = OrderedDict() # Specifiy that the default source directory should have a suffix after # the package name. This is usefull for package which needs different sources. self.targetSrcSuffix = OrderedDict() self.targetConfigurePath = OrderedDict() self.targetInstallPath = OrderedDict() self.targetMergeSourcePath = OrderedDict() self.targetMergePath = OrderedDict() self.targetDigests = OrderedDict() self.targetDigestUrls = OrderedDict() ## \todo prelimary self.svnTargets = OrderedDict() # dependencies is the common way to define dependencies that are both # run time and build time dependencies, # runtimeDependencies and buildDependencies are not different when looking # at the build process itself, they will only make a difference when getting # output of the dependencies self.dependencies = OrderedDict() self.runtimeDependencies = OrderedDict() self.buildDependencies = OrderedDict() # a long and a short description for the package self.shortDescription = '' self.description = '' #a url to the projects homepage self.homepage = '' self.patchToApply = OrderedDict() # key: target. Value: list(['patchname', patchdepth]) or ('patchname',patchdepth) self.isoDateToday = str( datetime.date.today() ).replace('-', '') self.svnTargets['svnHEAD'] = False self.svnServer = None # this will result in the use of the default server (either anonsvn.kde.org or svn.kde.org) self._defaultTarget = None self.buildTarget = 'svnHEAD' self.setTargets() - self.setSVNTargets() self.setBuildTarget() self.setBuildOptions() # do this after buildTarget is set so that some dependencies can be set depending on self.buildTarget self.setDependencies() @property def package(self) -> str: return self.parent.package @property def category(self) -> str: return self.parent.category @property def defaultTarget(self) -> str: target = None if ("PortageVersions", "%s/%s" % ( self.category, self.package )) in emergeSettings: target = emergeSettings.get("PortageVersions", "%s/%s" % ( self.category, self.package )) elif ("PortageVersions", "DefaultTarget") in emergeSettings: target = emergeSettings.get("PortageVersions", "DefaultTarget") if target in list(self.targets.keys()) or target in list(self.svnTargets.keys()) : return target return self._defaultTarget @defaultTarget.setter def defaultTarget(self, value): self._defaultTarget = value def setDependencies( self ): """default method for setting dependencies, override to set individual targets""" def setTargets( self ): """default method for setting targets, override to set individual targets""" - def setSVNTargets( self ): - """default method for setting svn targets, override to set individual targets""" - def setBuildTarget( self, buildTarget = None): """setup current build target""" self.buildTarget = self.defaultTarget if not buildTarget == None: self.buildTarget = buildTarget if not self.buildTarget in list(self.targets.keys()) and not self.buildTarget in list(self.svnTargets.keys()) : self.buildTarget = self.defaultTarget def setBuildOptions( self ): """default method for setting build options, override to set individual targets""" return @staticmethod def getArchitecture() -> str: return "-%s" % compiler.architecture() def hasTarget( self ) -> bool: """return true if archive targets for the currently selected build target is available""" return self.buildTarget in list(self.targets.keys()) def target( self ) -> str: """return archive target""" if self.buildTarget in list(self.targets.keys()): return self.targets[self.buildTarget] return "" def archiveName( self ) -> [str]: """returns the archive file name""" if self.buildTarget in list(self.archiveNames.keys()): return self.archiveNames[self.buildTarget] if type(self.targets[self.buildTarget]) == list: return [os.path.split(x)[-1] for x in self.targets[self.buildTarget] ] else: return [os.path.split(self.targets[self.buildTarget])[-1]] def hasMultipleTargets( self ) -> bool: """return whether we used a list of targets""" return type( self.targets[self.buildTarget] ) == list def targetCount( self ) -> int: """return the number of targets given either in a list, or split by a space character""" if self.hasMultipleTargets(): return len( self.targets[self.buildTarget] ) else: return len( self.targets[self.buildTarget].split() ) def targetAt( self, index ) -> str: """return the specified target at a specific position, or an empty string if out of bounds""" if self.targetCount() <= index: return "" if self.hasMultipleTargets(): return self.targets[self.buildTarget][index] else: return self.targets[self.buildTarget].split()[index] def hasSvnTarget( self ) -> bool: """return true if version system based target for the currently selected build target is available""" return self.buildTarget in list(self.svnTargets.keys()) def svnTarget( self ) -> str: """return version system based target for the currently selected build target""" if self.buildTarget in list(self.svnTargets.keys()): return self.svnTargets[self.buildTarget] return "" def targetSourceSuffix(self) -> str: """return local source path suffix for the recent target""" if (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetSrcSuffix.keys()): return self.targetSrcSuffix[ self.buildTarget ] def hasTargetSourcePath(self) -> bool: """return true if relative path appendable to local source path is given for the recent target""" return (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetInstSrc.keys()) def targetSourcePath(self) -> str: """return relative path appendable to local source path for the recent target""" if (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetInstSrc.keys()): return self.targetInstSrc[ self.buildTarget ] def hasConfigurePath(self) -> bool: """return true if relative path appendable to local source path is given for the recent target""" return (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetConfigurePath.keys()) def configurePath(self) -> str: """return relative path appendable to local source path for the recent target""" if (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) and \ self.buildTarget in list(self.targetConfigurePath.keys()): return self.targetConfigurePath[ self.buildTarget ] def hasInstallPath(self) -> bool: """return true if relative path appendable to local install path is given for the recent target""" return (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetInstallPath.keys()) def installPath(self) -> str: """return relative path appendable to local install path for the recent target""" if (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetInstallPath.keys()): return self.targetInstallPath[ self.buildTarget ] EmergeDebug.die("no install path for this build target defined") def hasMergePath(self) -> bool: """return true if relative path appendable to local merge path is given for the recent target""" return (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetMergePath.keys()) def mergePath(self) -> str: """return relative path appendable to local merge path for the recent target""" if (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetMergePath.keys()): return self.targetMergePath[ self.buildTarget ] def hasMergeSourcePath(self) -> bool: """return true if relative path appendable to local merge source path is given for the recent target""" return (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetMergeSourcePath.keys()) def mergeSourcePath(self) -> str: """return relative path appendable to local merge source path for the recent target""" if (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetMergeSourcePath.keys()): return self.targetMergeSourcePath[ self.buildTarget ] def hasPatches(self) -> bool: """return state for having patches for the recent target""" return (len( self.targets ) or len( self.svnTargets )) and self.buildTarget in list(self.patchToApply.keys()) def patchesToApply(self) -> [tuple]: """return patch informations for the recent build target""" if self.hasPatches(): out = self.patchToApply[ self.buildTarget ] return out if type(out) == list else [out] return [("", "")] def hasTargetDigests(self) -> bool: """return state if target has digest(s) for the recent build target""" return (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetDigests.keys()) def targetDigest(self) -> ([str], EmergeHash.HashAlgorithm): """return digest(s) for the recent build target. The return value could be a string or a list""" if self.hasTargetDigests(): out = self.targetDigests[ self.buildTarget ] if type(out) == str: out = [out] if not type(out) == tuple: out = (out, EmergeHash.HashAlgorithm.SHA1) return out return None def hasTargetDigestUrls(self) -> bool: """return state if target has digest url(s) for the recent build target""" return (self.buildTarget in list(self.targets.keys()) or self.buildTarget in list(self.svnTargets.keys())) \ and self.buildTarget in list(self.targetDigestUrls.keys()) def targetDigestUrl(self) -> ([str], EmergeHash.HashAlgorithm): """return digest url(s) for the recent build target. The return value could be a string or a list""" if self.hasTargetDigestUrls(): out = self.targetDigestUrls[ self.buildTarget ] if type(out) == str: out = [out] if not type(out) == tuple: out = (out, EmergeHash.HashAlgorithm.SHA1) return out return None diff --git a/bin/portage.py b/bin/portage.py index dbfae6b84..298db9562 100644 --- a/bin/portage.py +++ b/bin/portage.py @@ -1,649 +1,649 @@ ## @package portage # @brief contains portage tree related functions # @note this file should replace all other related portage related files import builtins from enum import Enum import importlib from collections import OrderedDict import EmergeDebug from EmergePackageObject import PackageObjectBase from EmergeConfig import * import InstallDB import utils class DependencyType(Enum): Runtime = "runtime" Buildtime = "buildtime" Both = "both" class PortageCache(object): _rootDirCache = dict() class PortageException(Exception,PackageObjectBase): def __init__(self, message, category, package , exception = None): Exception.__init__(self, message) subpackage, package = getSubPackage(category,package) PackageObjectBase.__init__(self,category,subpackage,package) self.exception = exception def __hash__(self): return self.__str__().__hash__() def __str__(self): return "%s failed: %s" % (PackageObjectBase.__str__(self),Exception.__str__(self)) class DependencyPackage(PackageObjectBase): """ This class wraps each package and constructs the dependency tree original code is from dependencies.py, integration will come later... """ def __init__( self, category, name, autoExpand = True, parent = None ): subpackage, package = getSubPackage(category,name) PackageObjectBase.__init__(self,category,subpackage,package,version = PortageInstance.getDefaultTarget(category,package)) self.category = category self.runtimeChildren = [] self.buildChildren = [] if parent is None: self._dependencyList = dict() else: self._dependencyList = parent._dependencyList if autoExpand: self.__readChildren() @property def name(self): return self.package def __hash__(self): return self.__str__().__hash__() def __eq__( self, other ): return self.category == other.category and self.name == other.name def __ne__( self, other ): return self.category != other.category or self.name != other.name def __str__(self): return "%s: %s" % (PackageObjectBase.__str__(self), self.version) def __readChildren( self ): runtimeDependencies, buildDependencies = readChildren( self.category, self.name ) self.runtimeChildren = self.__readDependenciesForChildren( list(runtimeDependencies.keys()) ) self.buildChildren = self.__readDependenciesForChildren( list(buildDependencies.keys()) ) def __readDependenciesForChildren( self, deps): children = [] if deps: for line in deps: ( category, package ) = line.split( "/" ) EmergeDebug.debug("category: %s, name: %s" % (category, package), 2) try: version = PortageInstance.getNewestVersion( category, package ) except PortageException as e: EmergeDebug.warning("%s for %s/%s as a dependency of %s/%s" % (e, e.category, e.package, self.category , self.name)) continue if not line in self._dependencyList.keys(): p = DependencyPackage( category, package, False, self ) EmergeDebug.debug("adding package %s/%s-%s" % (category, package, version), 2) self._dependencyList[ line ] = p p.__readChildren() else: p = self._dependencyList[ line ] children.append( p ) return children def getDependencies( self, depList = [], depType=DependencyType.Both, single = set(), maxDepth = -1, depth = 0, ignoredPackages = None): """ returns all dependencies """ if depType == DependencyType.Runtime: children = self.runtimeChildren elif depType == DependencyType.Buildtime: children = self.buildChildren else: children = self.runtimeChildren + self.buildChildren single.add(self) for p in children: if not p in single and not p in depList\ and not PortageInstance.ignores.match(p.fullName())\ and not p.fullName() in (ignoredPackages or []): if maxDepth == -1: p.getDependencies( depList, depType, single ) elif depth < maxDepth: p.getDependencies( depList, depType, single, maxDepth = maxDepth, depth = depth + 1 ) #if self.category != internalCategory: if not self in depList and not PortageInstance.ignores.match(PackageObjectBase.__str__(self)): depList.append( self ) return depList def buildType(): """return currently selected build type""" return emergeSettings.get("Compile","BuildType") def rootDirectories(): # this function should return all currently set portage directories if ("General", "EMERGE_PORTAGE_ROOT" ) in emergeSettings: rootDirs = emergeSettings.get("General", "EMERGE_PORTAGE_ROOT" ).split( ";" ) else: rootDirs = [] if len( rootDirs ) == 0: rootDirs = [ os.path.join( EmergeStandardDirs.emergeRoot(), "emerge", "portage" ) ] return rootDirs def rootDirForCategory( category ): """this function should return the portage directory where it finds the first occurance of the category throws exception if not found """ # this function should return the portage directory where it finds the # first occurance of a category or the default value for i in rootDirectories(): if category and os.path.exists( os.path.join( i, category ) ): return i EmergeDebug.die("can't find category %s" % category) def rootDirForPackage( category, package ): """returns the portage directory where it finds the first occurance of this package """ name = "%s/%s" % ( category, package ) if not name in PortageCache._rootDirCache: for i in rootDirectories(): if os.path.exists( os.path.join( i, category, package ) ): PortageCache._rootDirCache[ name ] = i return PortageCache._rootDirCache[ name ] def getFullPackage( package ): """tries to find a package and returns either category / subpackage / package or category / package returns an empty list if not found """ category = PortageInstance.getCategory( package ) if not category: return [] if package in PortageInstance.subpackages: _cat, subpackage = PortageInstance.subpackages[ package ][0].split('/') if not _cat == category: return [] return [category, subpackage, package] else: return [category, package] def getDirname( category, package ): """ return absolute pathname for a given category and package """ subpackage, package = getSubPackage( category, package ) if category and package: if subpackage: return os.path.join( rootDirForPackage( category, subpackage ), category, subpackage, package ) else: return os.path.join( rootDirForPackage( category, package ), category, package ) else: EmergeDebug.die("broken category or package %s/%s" % (category, package)) def getFilename( category, package ): """ return absolute filename for a given category, package """ return os.path.join( getDirname( category, package ), "%s.py" % package ) def VCSDirs(): return [ '.svn', 'CVS', '.hg', '.git' ] class Portage(object): #cache for pacages _packageDict = OrderedDict() options = "" def __init__( self ): """ """ self.categories = {} self.subpackages = {} self.portages = {} self._CURRENT_MODULE = ()#todo refactor package constructor self.ignores = re.compile("a^") if ("Portage", "Ignores") in emergeSettings: self.ignores = Portage.generateIgnoreList(emergeSettings.get("Portage", "Ignores").split(";")) @staticmethod def generateIgnoreList(ignores): return re.compile("(%s)" % "|".join( ["^%s$" % entry for entry in ignores])) def addPortageDir( self, directory ): """ adds the categories and packages of a portage directory """ if not os.path.exists( directory ): return categoryList = os.listdir( directory ) # remove vcs directories for vcsdir in VCSDirs(): if vcsdir in categoryList: categoryList.remove( vcsdir ) if "__pycache__" in categoryList: categoryList.remove( "__pycache__" ) dontBuildCategoryList = self.getDontBuildPackagesList( os.path.join( directory ) ) self.portages[ directory ] = [] for category in categoryList: if not os.path.isdir( os.path.join( directory, category ) ): continue self.portages[ directory ].append( category ) packageList = os.listdir( os.path.join( directory, category ) ) # remove vcs directories for vcsdir in VCSDirs(): if vcsdir in packageList: packageList.remove( vcsdir ) if "__pycache__" in packageList: packageList.remove( "__pycache__" ) dontBuildPackageList = self.getDontBuildPackagesList( os.path.join( directory, category ) ) if not category in list(self.categories.keys()): self.categories[ category ] = [] for package in packageList: if not os.path.isdir( os.path.join( directory, category, package ) ): continue if not package in self.categories[ category ]: _enabled = not category in dontBuildCategoryList and not package in dontBuildPackageList self.categories[ category ].append( PackageObjectBase( category=category, package=package, enabled=_enabled ) ) subPackageList = os.listdir( os.path.join( directory, category, package ) ) # remove vcs directories for vcsdir in VCSDirs(): if vcsdir in subPackageList: subPackageList.remove( vcsdir ) if "__pycache__" in subPackageList: subPackageList.remove( "__pycache__" ) for subPackage in subPackageList: if not os.path.isdir( os.path.join( directory, category, package, subPackage ) ) or subPackage in VCSDirs(): continue dontBuildSubPackageList = self.getDontBuildPackagesList( os.path.join( directory, category, package ) ) if not subPackage in list(self.subpackages.keys()): self.subpackages[ subPackage ] = [] if not subPackage in self.categories[ category ]: _enabled = not category in dontBuildCategoryList and not package in dontBuildPackageList and not subPackage in dontBuildSubPackageList self.categories[ category ].append( PackageObjectBase( category=category, subpackage=package, package=subPackage, enabled=_enabled ) ) self.subpackages[ subPackage ].append( category + "/" + package ) def getCategory( self, package ): """ returns the category of this package """ EmergeDebug.debug("getCategory: %s" % package, 2) for cat in list(self.categories.keys()): if package in self.categories[ cat ]: EmergeDebug.debug("getCategory: found category %s for package %s" % (cat, package), 3) return cat return False def isCategory( self, category ): """ returns whether a certain category exists """ return category in list(self.categories.keys()) def isPackage( self, category, package ): """ returns whether a certain package exists within a category """ return package in self.categories[ category ] def isVirtualPackage( self, category, package ): """ check if that package is of VirtualPackageBase """ if not self.isPackage( category, package ): return False mod = getPackageInstance(category,package) for baseClassObject in mod.__class__.__bases__: if baseClassObject.__name__ == 'VirtualPackageBase': return True return False def getDontBuildPackagesList( self, path ): """ get a list of packages from a dont_build file""" plist = [] if os.path.exists( os.path.join( path, "dont_build.txt" ) ): with open( os.path.join( path, "dont_build.txt" ), "r" ) as f: for line in f: if line.strip().startswith('#'): continue if not line.strip() == "": plist.append(line.strip()) return plist def getAllPackages( self, category ): """returns all packages of a category except those that are listed in a file 'dont_build.txt' in the category directory in case the category doesn't exist, nothing is returned""" if self.isCategory( category ): plist = [] for _p in self.categories[ category ]: if _p: plist.append(_p.package) return plist else: return def getPackageInstance(self, category, package): """return instance of class Package from package file""" fileName = getFilename( category, package ) pack = None mod = None if fileName.endswith(".py") and os.path.isfile(fileName): if not fileName in self._packageDict: EmergeDebug.debug("module to import: %s" % fileName, 2) if not os.path.isfile( fileName ): try: mod = builtins.__import__( fileName ) except ImportError as e: EmergeDebug.warning('import failed for module %s: %s' % (fileName, str(e))) mod = None else: modulename = os.path.basename( fileName )[:-3].replace('.', '_') loader = importlib.machinery.SourceFileLoader(modulename, fileName) try: mod = loader.load_module() except Exception as e: raise PortageException("Failed to load file %s" % fileName, category, package, e) if not mod is None: subpackage, package = getSubPackage( category, package ) self._CURRENT_MODULE = ( fileName, category,subpackage, package, mod ) pack = mod.Package( ) self._packageDict[ fileName ] = pack else: raise PortageException("Failed to find package", category, package) else: pack = self._packageDict[ fileName ] return pack def getDefaultTarget( self, category, package ): """ returns the default package of a specified package """ EmergeDebug.debug("getDefaultTarget: importing file %s" % getFilename(category, package), 2) if not ( category and package ): return dict() info = _getSubinfo( category, package ) if not info is None: return info.defaultTarget else: return None def getAllTargets( self, category, package ): """ returns all targets of a specified package """ EmergeDebug.debug("getAllTargets: importing file %s" % getFilename(category, package), 2) if not ( category and package ): return dict() info = _getSubinfo( category, package ) if not info is None: - tagDict = info.svnTargets + tagDict = info.svnTargets.copy() tagDict.update( info.targets ) EmergeDebug.debug(tagDict, 2) return tagDict else: return dict() def getAllVCSTargets( self, category, package ): """ returns all version control system targets of a specified package, excluding those which do contain tags """ EmergeDebug.debug("getAllVCSTargets: importing file %s" % getFilename(category, package), 1) info = _getSubinfo( category, package ) if not info is None: tagDict = info.svnTargets for key in tagDict: EmergeDebug.debug('%s: %s' % (key, tagDict[key]), 2) return tagDict else: return dict() def getUpdatableVCSTargets( self, category, package ): """ check if the targets are tags or not """ targetDict = PortageInstance.getAllVCSTargets( category, package ) retList = [] for key in targetDict: url = targetDict[ key ] if url: sourceType = utils.getVCSType( url ) if sourceType == "svn": # for svn, ignore tags if not url.startswith( "tags/" ) and not "/tags/" in url: retList.append( key ) elif sourceType == "git": _, branch, tag = utils.splitVCSUrl( url ) if tag == "" and not branch.endswith("-patched"): retList.append( key ) elif not sourceType == "": # for all other vcs types, simply rebuild everything for now retList.append( key ) return retList def getNewestVersion( self, category, package ): """ returns the newest version of this category/package """ if( category == None ): raise PortageException( "Empty category", category, package ) if not self.isCategory( category ): raise PortageException( "Could not find category", category, package ) if not self.isPackage( category, package ): raise PortageException( "Could not find package", category, package ) installed = InstallDB.installdb.getInstalledPackages(category, package ) newest = PortageInstance.getDefaultTarget( category, package ) for pack in installed: version = pack.getVersion() if not version or not newest: continue if utils.parse_version(newest) < utils.parse_version(version): newest = version return newest def getInstallables( self ): """ get all the packages that are within the portage directory """ instList = list() for category in list(self.categories.keys()): for package in self.categories[ category ]: instList.append(package) return instList # when importing this, this static Object should get added PortageInstance = Portage() for _dir in rootDirectories(): PortageInstance.addPortageDir( _dir ) def getSubPackage( category, package ): """ returns package and subpackage names """ """ in case no subpackage could be found, None is returned """ if package in list(PortageInstance.subpackages.keys()): for entry in PortageInstance.subpackages[ package ]: cat, pac = entry.split("/") if cat == category: return pac, package return None, package def getPackageInstance(category, package): """return instance of class Package from package file""" return PortageInstance.getPackageInstance(category, package) def getDependencies( category, package, runtimeOnly = False ): """returns the dependencies of this package as list of strings: category/package""" subpackage, package = getSubPackage( category, package ) if subpackage: EmergeDebug.debug("solving package %s/%s/%s %s" % (category, subpackage, package, getFilename( category, package ))) else: EmergeDebug.debug("solving package %s/%s %s" % (category, package, getFilename(category, package))) subpackage = package deps = [] for pkg in [ subpackage ]: info = _getSubinfo(category, pkg) if not info is None: depDict = info.dependencies depDict.update( info.runtimeDependencies ) if not runtimeOnly: depDict.update( info.buildDependencies ) for line in list(depDict.keys()): (category, package) = line.split( "/" ) version = PortageInstance.getNewestVersion( category, package ) deps.append( [ category, package, version, depDict[ line ] ] ) return deps def parseListFile( filename ): """parses a csv file used for building a list of specific packages""" categoryList = [] packageList = [] infoDict = {} listFileObject = open( filename, 'r' ) for line in listFileObject: if line.strip().startswith('#'): continue try: cat, pac, tar, plvl = line.split( ',' ) except: continue categoryList.append( cat ) packageList.append( pac ) infoDict[ cat + "/" + pac ] = (tar, plvl) return categoryList, packageList, infoDict def solveDependencies( category, package, depList, depType = DependencyType.Both, maxDepth = -1, ignoredPackages = None ): depList.reverse() if ( category == "" ): category = PortageInstance.getCategory( package ) EmergeDebug.debug("found package in category %s" % category, 2) pac = DependencyPackage( category, package, parent = None ) depList = pac.getDependencies( depList, depType=depType, maxDepth = maxDepth, single = set(), ignoredPackages = ignoredPackages ) depList.reverse() return depList def printTargets( category, package ): targetsDict = PortageInstance.getAllTargets( category, package ) defaultTarget = PortageInstance.getDefaultTarget( category, package ) if 'svnHEAD' in targetsDict and not targetsDict['svnHEAD']: del targetsDict['svnHEAD'] targetsDictKeys = list(targetsDict.keys()) targetsDictKeys.sort() for i in targetsDictKeys: if defaultTarget == i: print('*', end=' ') else: print(' ', end=' ') print(i) def _getSubinfo( category, package ): pack = getPackageInstance( category, package ) if pack: return pack.subinfo return None def readChildren( category, package ): EmergeDebug.debug("solving package %s/%s %s" % (category, package, getFilename(category, package)), 2) subinfo = _getSubinfo( category, package ) if subinfo is None: return OrderedDict(), OrderedDict() runtimeDependencies = subinfo.runtimeDependencies buildDependencies = subinfo.buildDependencies commonDependencies = subinfo.dependencies runtimeDependencies.update(commonDependencies) buildDependencies.update(commonDependencies) return runtimeDependencies, buildDependencies def isPackageUpdateable( category, package ): EmergeDebug.debug("isPackageUpdateable: importing file %s" % getFilename(category, package), 2) subinfo = _getSubinfo( category, package ) if not subinfo is None: if len( subinfo.svnTargets ) == 1 and not subinfo.svnTargets[ list(subinfo.svnTargets.keys())[0] ]: return False return len( subinfo.svnTargets ) > 0 else: return False def alwaysTrue( *dummyArgs): """we sometimes need a function that always returns True""" return True def getHostAndTarget( hostEnabled, targetEnabled ): """used for messages""" msg = "" if hostEnabled or targetEnabled: msg += "(" if hostEnabled: msg += "H" if hostEnabled and targetEnabled: msg += "/" if targetEnabled: msg += "T" msg += ")" return msg def printCategoriesPackagesAndVersions( lines, condition, hostEnabled=alwaysTrue, targetEnabled=alwaysTrue ): """prints a number of 'lines', each consisting of category, package and version field""" def printLine( cat, pack, ver, hnt="" ): catlen = 25 packlen = 25 print(cat + " " * ( catlen - len( cat ) ) + pack + " " * ( packlen - len( pack ) ) + ver, hnt) printLine( 'Category', 'Package', 'Version' ) printLine( '--------', '-------', '-------' ) for category, package, version in lines: if condition( category, package, version ): printLine( category, package, version ) def printInstallables(): """get all the packages that can be installed""" data = list() for p in PortageInstance.getInstallables(): data.append((p.category,p.package, p.version)) printCategoriesPackagesAndVersions( data, alwaysTrue ) def printPackagesForFileSearch(filename): packages = InstallDB.installdb.getPackagesForFileSearch(filename) for pId, filename in packages: category, packageName, version = pId.getPackageInfo() print("%s/%s: %s" % (category, packageName, filename)) def getPackagesCategories(packageName, defaultCategory = None): EmergeDebug.trace("getPackagesCategories for package name %s" % packageName) if defaultCategory is None: defaultCategory = emergeSettings.get("General","EMERGE_DEFAULTCATEGORY","kde") packageList, categoryList = [], [] if len( packageName.split( "/" ) ) == 1: if PortageInstance.isCategory( packageName ): EmergeDebug.debug("isCategory=True", 2) packageList = PortageInstance.getAllPackages( packageName ) categoryList = [ packageName ] * len(packageList) else: EmergeDebug.debug("isCategory=False", 2) if PortageInstance.isCategory( defaultCategory ) and PortageInstance.isPackage( defaultCategory, packageName ): # prefer the default category packageList = [ packageName ] categoryList = [ defaultCategory ] else: if PortageInstance.getCategory( packageName ): packageList = [ packageName ] categoryList = [ PortageInstance.getCategory( packageName ) ] elif len( packageName.split( "/" ) ) == 2: [ cat, pac ] = packageName.split( "/" ) if PortageInstance.isCategory( cat ): categoryList = [ cat ] else: return packageList, categoryList if len( categoryList ) > 0 and PortageInstance.isPackage( categoryList[0], pac ): packageList = [ pac ] if len( categoryList ) and len( packageList ): EmergeDebug.debug("added package %s/%s" % (categoryList[0], pac), 2) else: EmergeDebug.error("unknown packageName") return packageList, categoryList diff --git a/portage/dev-util/llvm-meta/clang/clang.py b/portage/dev-util/llvm-meta/clang/clang.py index fd396fff2..a14773e97 100644 --- a/portage/dev-util/llvm-meta/clang/clang.py +++ b/portage/dev-util/llvm-meta/clang/clang.py @@ -1,43 +1,33 @@ # -*- coding: utf-8 -*- import info import portage class subinfo(info.infoclass): def setTargets( self ): self.versionInfo.setDefaultValues( packageName = "cfe", gitUrl = "[git]http://llvm.org/git/clang.git") self.targetDigests['3.7.0'] = '4ff8100565528b13d99a73f807e9b426c3b3bed9' for ver in self.svnTargets.keys() | self.targets.keys(): self.patchToApply[ver] = [("fix_shortpath.patch", 1)] if ver in ["3.7.0", "3.7.1", "release_37"]: self.patchToApply[ ver ] += [("0014-use-DESTDIR-on-windows.patch", 1)] else: self.patchToApply[ver] += [("fix-plugins.diff", 1)] if compiler.isMinGW(): self.patchToApply[ ver ] += [("0012-Set-the-x86-arch-name-to-i686-for-mingw-w64.patch", 1), ("0015-Fix-the-calling-convention-of-Mingw64-long-double-va.patch", 1), ("0016-Teach-mingw-toolchain-driver-to-properly-emit-static.patch", 1), ("0017-Fix-PR23472-by-emitting-initialized-variable-and-its.patch", 1)] def setDependencies( self ): self.buildDependencies['virtual/base'] = 'default' self.dependencies['win32libs/libxml2'] = 'default' - self.dependencies['util/llvm'] = 'default' + self.dependencies['dev-util/llvm'] = 'default' -from Package.CMakePackageBase import * +from Package.SourceOnlyPackageBase import * -class Package(CMakePackageBase): +class Package(SourceOnlyPackageBase): def __init__( self, **args ): - CMakePackageBase.__init__(self) - - - def configure( self, defines=""): - return True - - def make( self ): - return True - - def install( self): - return True + SourceOnlyPackageBase.__init__(self) diff --git a/portage/dev-util/llvm-meta/lld/lld.py b/portage/dev-util/llvm-meta/lld/lld.py index 5ab97d9c2..1c93cc616 100644 --- a/portage/dev-util/llvm-meta/lld/lld.py +++ b/portage/dev-util/llvm-meta/lld/lld.py @@ -1,26 +1,17 @@ # -*- coding: utf-8 -*- import info class subinfo(info.infoclass): def setTargets( self ): self.versionInfo.setDefaultValues( ) def setDependencies( self ): self.buildDependencies['virtual/base'] = 'default' self.dependencies["dev-util/llvm"] = "default" -from Package.CMakePackageBase import * +from Package.SourceOnlyPackageBase import * -class Package(CMakePackageBase): +class Package(SourceOnlyPackageBase): def __init__( self, **args ): - CMakePackageBase.__init__(self) + SourceOnlyPackageBase.__init__(self) - - def configure( self, defines=""): - return True - - def make( self ): - return True - - def install( self): - return True diff --git a/portage/dev-util/llvm-meta/llvm/llvm.py b/portage/dev-util/llvm-meta/llvm/llvm.py index dc3d94504..efd9e45dd 100644 --- a/portage/dev-util/llvm-meta/llvm/llvm.py +++ b/portage/dev-util/llvm-meta/llvm/llvm.py @@ -1,68 +1,79 @@ # -*- coding: utf-8 -*- import info from Package import CMakePackageBase class subinfo(info.infoclass): def setTargets( self ): self.versionInfo.setDefaultValues( ) self.targetDigests['3.7.0'] = '0355c2fe01a8d17c3315069e6f2ef80c281e7dad' for ver in self.svnTargets.keys() | self.targets.keys(): if ver in ["3.7.0", "3.7.1", "release_37"]: self.patchToApply[ ver ] = [("0002-use-DESTDIR-on-windows.patch", 1)] if ver in ["release_38"]: self.patchToApply[ver] = [("use-DESTDIR-on-windows-3.8.patch", 1)] def setDependencies( self ): self.buildDependencies['virtual/base'] = 'default' from Package.CMakePackageBase import * class Package(CMakePackageBase): def __init__( self, **args ): CMakePackageBase.__init__(self) self.clang = portage.getPackageInstance('dev-util', 'clang') self.lld = portage.getPackageInstance('dev-util', 'lld') self.subPackages = [self.clang, self.lld] self.subinfo.options.configure.defines = '-DLLVM_TARGETS_TO_BUILD="X86"' self.subinfo.options.configure.defines += " -DLLVM_EXTERNAL_LLD_SOURCE_DIR=\"%s\"" % self.lld.sourceDir().replace("\\", "/") self.subinfo.options.configure.defines += " -DLLVM_EXTERNAL_CLANG_SOURCE_DIR=\"%s\"" % self.clang.sourceDir().replace("\\", "/") if compiler.isMinGW(): self.subinfo.options.configure.defines += " -DBUILD_SHARED_LIBS=ON" def fetch(self): if not CMakePackageBase.fetch(self): return False for p in self.subPackages: if not p.fetch(): return False return True def unpack(self): if not CMakePackageBase.unpack(self): return False for p in self.subPackages: if not p.unpack(): return False return True def configureOptions(self, defines=""): options = CMakePackageBase.configureOptions(self, defines) # just expect that we don't want to debug our compiler options += ' -DCMAKE_BUILD_TYPE=Release' return options def install(self): if not CMakePackageBase.install(self): return False if compiler.isMinGW(): files = os.listdir(os.path.join(self.buildDir(), "lib")) for f in files: if f.endswith("dll.a"): src = os.path.join(self.buildDir(), "lib", f) dest = os.path.join(self.imageDir(), "lib", f) if not os.path.exists(dest): utils.copyFile(src, dest, False) + + # the build system is broken so.... + src = os.path.join(self.imageDir(), "bin", "clang.exe") + if compiler.isMinGW(): + dest = os.path.join(self.imageDir(), "bin", "clang++.exe") + elif compiler.isMSVC(): + dest = os.path.join(self.imageDir(), "bin", "clang-cl.exe") + else: + EmergeDebug.error("Unknown compiler") + if not os.path.exists(dest): + utils.copyFile(src, dest) return True \ No newline at end of file