diff --git a/bin/BuildSystem/BuildSystemBase.py b/bin/BuildSystem/BuildSystemBase.py index 27ac48306..11ec24d8a 100644 --- a/bin/BuildSystem/BuildSystemBase.py +++ b/bin/BuildSystem/BuildSystemBase.py @@ -1,156 +1,163 @@ # # copyright (c) 2009 Ralf Habacker # """ \package BuildSystemBase""" from EmergeBase import * import compiler from graphviz import * import dependencies class BuildSystemBase(EmergeBase): """provides a generic interface for build systems and implements all stuff for all build systems""" debug = True def __init__(self, typeName=""): """constructor""" EmergeBase.__init__(self) self.supportsNinja = False self.supportsCCACHE = emergeSettings.getboolean("General","EMERGE_USE_CCACHE", False ) and compiler.isMinGW() self.supportsClang = emergeSettings.getboolean("General","UseClang", False ) self.buildSystemType = typeName self.envPath = "" if self.compiler() == "mingw": self.envPath = "mingw/bin" if self.compiler() == "mingw4": self.envPath = "mingw4/bin" def _getmakeProgram(self): if self.supportsNinja and emergeSettings.getboolean("General","EMERGE_USE_NINJA", False): return "ninja" EMERGE_MAKE_PROGRAM = emergeSettings.get("General", "EMERGE_MAKE_PROGRAM", "" ) if EMERGE_MAKE_PROGRAM != "" and self.subinfo.options.make.supportsMultijob: utils.debug( "set custom make program: %s" % EMERGE_MAKE_PROGRAM, 1 ) return EMERGE_MAKE_PROGRAM elif not self.subinfo.options.make.supportsMultijob: if "MAKE" in os.environ: del os.environ["MAKE"] if compiler.isMSVC() or compiler.isIntel() : return "nmake /NOLOGO" elif compiler.isMinGW(): return "mingw32-make" else: utils.die( "unknown %s compiler" % self.compiler() ) makeProgramm = property(_getmakeProgram) def compile(self): """convencience method - runs configure() and make()""" configure = getattr(self, 'configure') make = getattr(self, 'make') - return configure() and make() + + if not configure(): + return False + + if not self.compileFast: + return make() + + return True def configureSourceDir(self): """returns source dir used for configure step""" # pylint: disable=E1101 # this class never defines self.source, that happens only # in MultiSource. if hasattr(self,'source'): sourcedir = self.source.sourceDir() else: sourcedir = self.sourceDir() if self.subinfo.hasConfigurePath(): sourcedir = os.path.join(sourcedir, self.subinfo.configurePath()) return sourcedir def configureOptions(self, defines=""): """return options for configure command line""" if self.subinfo.options.configure.defines != None: defines += " %s" % self.subinfo.options.configure.defines if self.supportsCCACHE: defines += " %s" % self.ccacheOptions() if self.supportsClang: defines += " %s" % self.clangOptions() return defines def makeOptions(self, defines="", maybeVerbose=True): """return options for make command line""" if self.subinfo.options.make.ignoreErrors: defines += " -i" if self.subinfo.options.make.makeOptions: defines += " %s" % self.subinfo.options.make.makeOptions if maybeVerbose and utils.verbose() > 1: if self.supportsNinja and emergeSettings.getboolean("General","EMERGE_USE_NINJA", False ): defines += " -v " else: defines += " VERBOSE=1 V=1" return defines def dumpEmergeDependencies( self ): """dump emerge package dependencies""" output = dependencies.dumpDependencies( self.package ) outDir = self.buildDir() outFile = os.path.join( outDir, self.package + '-emerge.dot' ) if not os.path.exists( os.path.dirname( outFile ) ): os.makedirs( os.path.dirname( outFile ) ) with open( outFile, "w" ) as f: f.write( output ) graphviz = GraphViz( self ) if not graphviz.runDot( outFile, outFile + '.pdf', 'pdf' ): return False return graphviz.openOutput() def dumpDependencies(self): """dump package dependencies """ return self.dumpEmergeDependencies() def configure(self): return True def make(self): return True def install(self): # create post (un)install scripts for pkgtype in ['bin', 'lib', 'doc', 'src', 'dbg']: script = os.path.join( self.packageDir(), "post-install-%s.cmd" ) % pkgtype scriptName = "post-install-%s-%s.cmd" % ( self.package, pkgtype ) # are there any cases there installDir should be honored ? destscript = os.path.join( self.imageDir(), "manifest", scriptName ) if not os.path.exists( os.path.join( self.imageDir(), "manifest" ) ): utils.createDir( os.path.join( self.imageDir(), "manifest" ) ) if os.path.exists( script ): utils.copyFile( script, destscript ) script = os.path.join( self.packageDir(), "post-uninstall-%s.cmd" ) % pkgtype scriptName = "post-uninstall-%s-%s.cmd" % ( self.package, pkgtype ) # are there any cases there installDir should be honored ? destscript = os.path.join( self.imageDir(), "manifest", scriptName ) if not os.path.exists( os.path.join( self.imageDir(), "manifest" ) ): utils.createDir( os.path.join( self.imageDir(), "manifest" ) ) if os.path.exists( script ): utils.copyFile( script, destscript ) if self.subinfo.options.package.withDigests: if self.subinfo.options.package.packageFromSubDir: filesDir = os.path.join(self.imageDir(), self.subinfo.options.package.packageFromSubDir) else: filesDir = self.imageDir() return True def unittest( self ): """running unittests""" return True def ccacheOptions(self): return "" def clangOptions(self): return "" diff --git a/bin/EmergeBase.py b/bin/EmergeBase.py index 20a86d9e7..0dec42fed 100644 --- a/bin/EmergeBase.py +++ b/bin/EmergeBase.py @@ -1,300 +1,304 @@ # # copyright (c) 2009 Ralf Habacker # import os import sys import datetime from ctypes import * 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) utils.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.subinfo = mod.subinfo(self, portage.PortageInstance.options) 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 noCopy(self): return emergeSettings.getboolean("General", "EMERGE_NOCOPY", 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 compileFast(self): + return emergeSettings.getboolean("General", "CompileFast", False ) + @property def forced(self): return emergeSettings.getboolean("General", "EMERGE_FORCED", False ) @property def buildTests(self): return emergeSettings.getboolean("General", "EMERGE_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... utils.debug("converting " + directory + " to " + buf.value) return buf.value def buildType(self): """return currently selected build type""" return emergeSettings.get("General","EMERGE_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" # we assume that binary packages are for all compiler and targets ## \todo add image directory support for using binary packages for a specific compiler and build type if self.buildSystemType == 'binary': return directory 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): utils.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()) utils.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""" utils.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): utils.trace( "EmergeBase.enterBuildDir called") if ( not os.path.exists( self.buildDir() ) ): os.makedirs( self.buildDir() ) utils.debug("creating: %s" % self.buildDir()) os.chdir( self.buildDir() ) utils.debug("entering: %s" % self.buildDir()) def enterSourceDir(self): if ( not os.path.exists( self.sourceDir() ) ): return False utils.warning("entering the source directory!") os.chdir( self.sourceDir() ) utils.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: utils.warning( "while running %s cmd: %s" % (errorMessage, str(command)) ) else: utils.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/emerge.py b/bin/emerge.py index a7e34b6ce..381f404ba 100755 --- a/bin/emerge.py +++ b/bin/emerge.py @@ -1,459 +1,463 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # this will emerge some programs... # copyright: # Holger Schroeder # Patrick Spendrin # Hannah von Reth # The minimum python version for emerge please edit here # if you add code that changes this requirement import sys MIN_PY_VERSION = (3, 4, 0) if sys.version_info[ 0:3 ] < MIN_PY_VERSION: print( "Error: Python too old!", file = sys.stderr ) print( "Emerge needs at least Python Version %s.%s.%s" % MIN_PY_VERSION, file = sys.stderr ) print( "Please install it and adapt your kdesettings.bat", file = sys.stderr ) exit( 1 ) import time import datetime import traceback import argparse import compiler import portageSearch from InstallDB import * from EmergeConfig import * import jenkins def packageIsOutdated( category, package ): newest = portage.PortageInstance.getNewestVersion( category, package ) installed = installdb.getInstalledPackages( category, package ) for pack in installed: version = pack.getVersion( ) if newest != version: return True @utils.log def doExec( package, action, continueFlag = False ): utils.startTimer( "%s for %s" % ( action, package ), 1 ) utils.info("Action: %s for %s" % (action, package)) ret = package.execute( action ) utils.stopTimer( "%s for %s" % ( action, package ) ) return ret or continueFlag def handlePackage( category, packageName, buildAction, continueFlag, skipUpToDateVcs ): utils.debug_line( ) utils.info("Handling package: %s, build action: %s" % (packageName, buildAction)) success = True package = portage.getPackageInstance( category, packageName ) if package is None: raise portage.PortageException( "Package not found", category, packageName ) if buildAction in [ "all", "full-package", "update", "update-all" ]: success = success and doExec( package, "fetch", continueFlag ) if success and skipUpToDateVcs and package.subinfo.hasSvnTarget( ): revision = package.sourceVersion( ) for p in installdb.getInstalledPackages( category, packageName ): if p.getRevision( ) == revision: utils.info("Skipping further actions, package is up-to-date") return True success = success and doExec( package, "unpack", continueFlag ) success = success and doExec( package, "compile" ) success = success and doExec( package, "cleanimage" ) success = success and doExec( package, "install" ) if buildAction in [ "all", "update", "update-all" ]: success = success and doExec( package, "qmerge" ) if buildAction == "full-package": success = success and doExec( package, "package" ) success = success or continueFlag elif buildAction in [ "fetch", "unpack", "preconfigure", "configure", "compile", "make", "checkdigest", "dumpdeps", "test", "package", "unmerge", "cleanimage", "cleanbuild", "createpatch", "geturls", "print-revision" ]: success = doExec( package, buildAction, continueFlag ) elif buildAction == "install": success = doExec( package, "cleanimage" ) success = success and doExec( package, "install", continueFlag ) elif buildAction == "qmerge": #success = doExec( package, "cleanimage" ) #success = success and doExec( package, "install") success = success and doExec( package, "qmerge" ) elif buildAction == "generate-jenkins-job": success = jenkins.generateJob(package) elif buildAction == "version-dir": print( "%s-%s" % ( packageName, package.sourceVersion( ) ) ) success = True elif buildAction == "version-package": print( "%s-%s-%s" % ( packageName, compiler.getCompilerName( ), package.sourceVersion( ) ) ) success = True elif buildAction == "print-targets": portage.printTargets( category, packageName ) success = True else: success = utils.error( "could not understand this buildAction: %s" % buildAction ) return success def handleSinglePackage( packageName, args ): deplist = [ ] packageList = [ ] originalPackageList = [ ] categoryList = [ ] targetDict = dict( ) if args.action == "update-all": installedPackages = portage.PortageInstance.getInstallables( ) if portage.PortageInstance.isCategory( packageName ): utils.debug( "Updating installed packages from category " + packageName, 1 ) else: utils.debug( "Updating all installed packages", 1 ) packageList = [ ] for mainCategory, mainPackage in installedPackages: if portage.PortageInstance.isCategory( packageName ) and ( mainCategory != packageName ): continue if installdb.isInstalled( mainCategory, mainPackage, args.buildType ) \ and portage.isPackageUpdateable( mainCategory, mainPackage ): categoryList.append( mainCategory ) packageList.append( mainPackage ) utils.debug( "Will update packages: " + str( packageList ), 1 ) elif args.list_file: listFileObject = open( args.list_file, 'r' ) for line in listFileObject: if line.strip( ).startswith( '#' ): continue try: cat, pac, tar, _ = line.split( ',' ) except: continue categoryList.append( cat ) packageList.append( pac ) originalPackageList.append( pac ) targetDict[ cat + "/" + pac ] = tar elif packageName: packageList, categoryList = portage.getPackagesCategories( packageName ) for entry in packageList: utils.debug("Checking dependencies for: %s" % entry, 1) for mainCategory, entry in zip( categoryList, packageList ): deplist = portage.solveDependencies( mainCategory, entry, deplist, args.dependencyType, maxDetpth = args.dependencydepth ) # no package found if len( deplist ) == 0: category = "" if not packageName.find( "/" ) == -1: (category, package) = packageName.split( "/" ) portageSearch.printSearch( category, packageName ) return False for item in deplist: item.enabled = args.ignoreAllInstalled if args.ignoreInstalled and item.category in categoryList and item.package in packageList or packageIsOutdated( item.category, item.package ): item.enabled = True if item.category + "/" + item.package in targetDict: item.target = targetDict[ item.category + "/" + item.package ] if args.target in list( portage.PortageInstance.getAllTargets( item.category, item.package ).keys( ) ): # if no target or a wrong one is defined, simply set the default target here item.target = args.target utils.debug( "dependency: %s" % item, 1 ) if not deplist: utils.debug("", 1) utils.debug_line( 1 ) #for item in deplist: # cat = item[ 0 ] # pac = item[ 1 ] # ver = item[ 2 ] # if portage.isInstalled( cat, pac, ver, buildType) and updateAll and not portage.isPackageUpdateable( cat, pac, ver ): # print "remove:", cat, pac, ver # deplist.remove( item ) if args.action == "install-deps": # the first dependency is the package itself - ignore it # TODO: why are we our own dependency? del deplist[ 0 ] elif args.action == "update-direct-deps": for item in deplist: item.enabled = True deplist.reverse( ) # package[0] -> category # package[1] -> package # package[2] -> version info = deplist[ -1 ] if not portage.PortageInstance.isVirtualPackage( info.category, info.package ) and \ not args.action in [ "all", "install-deps" ,"generate-jenkins-job"] and\ not args.list_file or\ args.action in ["print-targets"]:#not all commands should be executed on the deps if we are a virtual packages # if a buildAction is given, then do not try to build dependencies # and do the action although the package might already be installed. # This is still a bit problematic since packageName might not be a valid # package # for list files, we also want to handle fetching & packaging per package if not handlePackage( info.category, info.package, args.action, args.doContinue, args.update_fast ): utils.notify( "Emerge %s failed" % args.action, "%s of %s/%s failed" % ( args.action, info.category, info.package), args.action ) return False utils.notify( "Emerge %s finished" % args.action, "%s of %s/%s finished" % ( args.action, info.category, info.package), args.action ) else: if args.dumpDepsFile: dumpDepsFileObject = open( args.dumpDepsFile, 'w+' ) dumpDepsFileObject.write( "# dependency dump of package %s\n" % ( packageName ) ) for info in deplist: isVCSTarget = False if args.dumpDepsFile: dumpDepsFileObject.write( ",".join( [ info.category, info.package, info.target, "" ] ) + "\n" ) isLastPackage = info == deplist[ -1 ] if args.outDateVCS or (args.outDatePackage and isLastPackage): isVCSTarget = portage.PortageInstance.getUpdatableVCSTargets( info.category, info.package ) != [ ] isInstalled = installdb.isInstalled( info.category, info.package ) if args.list_file and args.action != "all": info.enabled = info.package in originalPackageList if ( isInstalled and not info.enabled ) and not ( isInstalled and (args.outDateVCS or ( args.outDatePackage and isLastPackage) ) and isVCSTarget ): if utils.verbose( ) > 1 and info.package == packageName: utils.warning( "already installed %s/%s" % ( info.category, info.package) ) elif utils.verbose( ) > 2 and not info.package == packageName: utils.warning( "already installed %s/%s" % ( info.category, info.package ) ) else: # in case we only want to see which packages are still to be build, simply return the package name if args.probe: if utils.verbose( ) > 0: utils.warning( "pretending %s" % info ) else: if args.action in [ "install-deps", "update-direct-deps" ]: args.action = "all" if not handlePackage( info.category, info.package, args.action, args.doContinue, args.update_fast ): utils.error( "fatal error: package %s/%s %s failed" % \ ( info.category, info.package, args.action ) ) utils.notify( "Emerge build failed", "Build of %s/%s failed" % ( info.category, info.package), args.action ) return False utils.notify( "Emerge build finished", "Build of %s/%s finished" % ( info.category, info.package), args.action ) utils.new_line( ) return True def main( ): parser = argparse.ArgumentParser( prog = "emerge", description = "Emerge is a tool for building KDE-related software under Windows. emerge automates it, looks for the dependencies and fetches them automatically.\ Some options should be used with extreme caution since they will make your kde installation unusable in 999 out of 1000 cases.", epilog = """More information see the README or http://windows.kde.org/. Send feedback to .""" ) def addBuildaAction( x, help = None ): parser.add_argument( "--%s" % x, action = "store_const", dest = "action", const = x, default = "all", help = help ) parser.add_argument( "-p", "--probe", action = "store_true", help = "probing: emerge will only look which files it has to build according to the list of installed files and according to the dependencies of the package." ) parser.add_argument( "--list-file", action = "store", help = "Build all packages from the csv file provided" ) _def = emergeSettings.get( "General", "EMERGE_OPTIONS", "" ) if _def == "": _def = [] else: _def = _def.split( ";" ) parser.add_argument( "--options", action = "append", default = _def, help = "Set emerge property from string . An example for is \"cmake.openIDE=1\" see options.py for more informations." ) parser.add_argument( "-z", "--outDateVCS", action = "store_true", help = "if packages from version control system sources are installed, it marks them as out of date and rebuilds them (tags are not marked as out of date)." ) parser.add_argument( "-sz", "--outDatePackage", action = "store_true", help = "similar to -z, only that it acts only on the last package, and works as normal on the rest." ) parser.add_argument( "-q", "--stayquiet", action = "store_true", dest = "stayQuiet", help = "quiet: there should be no output - The verbose level should be 0" ) parser.add_argument( "-t", "--buildtests", action = "store_true", dest = "buildTests", default = emergeSettings.getboolean( "General", "EMERGE_BUILDTESTS", False ) ) parser.add_argument( "-c", "--continue", action = "store_true", dest = "doContinue" ) parser.add_argument( "--offline", action = "store_true", default = emergeSettings.getboolean( "General", "WorkOffline", False ), help = "do not try to connect to the internet: KDE packages will try to use an existing source tree and other packages would try to use existing packages in the download directory.\ If that doesn't work, the build will fail." ) parser.add_argument( "-f", "--force", action = "store_true", dest = "forced", default = emergeSettings.getboolean( "General", "EMERGE_FORCED", False ) ) parser.add_argument( "--buildtype", choices = [ "Release", "RelWithDebInfo", "MinSizeRel", "Debug" ], dest = "buildType", default = emergeSettings.get( "General", "EMERGE_BUILDTYPE", "RelWithDebInfo" ), help = "This will override the build type set by the environment option EMERGE_BUILDTYPE ." ) parser.add_argument( "-v", "--verbose", action = "count", default = int( emergeSettings.get( "EmergeDebug", "Verbose", "0" ) ), help = " verbose: increases the verbose level of emerge. Default is 1. verbose level 1 contains some notes from emerge, all output of cmake, make and other programs that are used.\ verbose level 2a dds an option VERBOSE=1 to make and emerge is more verbose highest level is verbose level 3." ) parser.add_argument( "--trace", action = "store", default = int( emergeSettings.get( "General", "EMERGE_TRACE", "0" ) ), type = int ) parser.add_argument( "-i", "--ignoreInstalled", action = "store_true", help = "ignore install: using this option will install a package over an existing install. This can be useful if you want to check some new code and your last build isn't that old." ) parser.add_argument( "-ia", "--ignoreAllInstalled", action = "store_true", help = "ignore all install: using this option will install all package over an existing install. This can be useful if you want to check some new code and your last build isn't that old." ) parser.add_argument( "--target", action = "store", help = "This will override the build of the default target. The default Target is marked with a star in the printout of --print-targets" ) parser.add_argument( "--search", action = "store_true", help = "This will search for a package or a description matching or similar to the search term." ) parser.add_argument( "--nocopy", action = "store_true", default = emergeSettings.getboolean( "General", "EMERGE_NOCOPY", False ), help = "this option is deprecated. In older releases emerge would have copied everything from the SVN source tree to a source directory under KDEROOT\\tmp - currently nocopy is applied\ by default if EMERGE_NOCOPY is not set to \"False\". Be aware that setting EMERGE_NOCOPY to \"False\" might slow down the build process, irritate you and increase the disk space roughly\ by the size of SVN source tree." ) parser.add_argument( "--noclean", action = "store_true", default = emergeSettings.getboolean( "General", "EMERGE_NOCLEAN", False ), help = "this option will try to use an existing build directory. Please handle this option with care - it will possibly break if the directory isn't existing." ) parser.add_argument( "--clean", action = "store_false", dest = "noclean", help = "oposite of --noclean" ) + parser.add_argument( "--compile-fast", action = "store_true", + default = emergeSettings.getboolean( "General", "CompileFast", False ), + help = "skip make() entirely (useful in case of `make` and `make install` redudancy) -- handle with care" ) parser.add_argument( "--patchlevel", action = "store", default = emergeSettings.get( "General", "EMERGE_PKGPATCHLVL", "" ), help = "This will add a patch level when used together with --package" ) parser.add_argument( "--log-dir", action = "store", default = emergeSettings.get( "General", "EMERGE_LOG_DIR", "" ), help = "This will log the build output to a logfile in LOG_DIR for each package. Logging information is appended to existing logs." ) parser.add_argument( "--dump-deps-file", action = "store", dest = "dumpDepsFile", help = "Output the dependencies of this package as a csv file suitable for emerge server." ) parser.add_argument( "--dt", action = "store", choices = [ "both", "runtime", "buildtime" ], default = "both", dest = "dependencyType" ) parser.add_argument( "--print-installed", action = "store_true", help = "This will show a list of all packages that are installed currently." ) parser.add_argument( "--print-installable", action = "store_true", help = "his will give you a list of packages that can be installed. Currently you don't need to enter the category and package: only the package will be enough." ) parser.add_argument( "--update-fast", action = "store_true", help = "If the package is installed from svn/git and the revision did not change all steps after fetch are skipped" ) parser.add_argument( "-d", "--dependencydepth", action = "store", type = int, default = -1, help = "By default emerge resolves the whole dependency graph, this option limits the depth of the graph, so a value of 1 would mean only dependencies defined in that package" ) for x in sorted( [ "fetch", "unpack", "preconfigure", "configure", "compile", "make", "install", "qmerge", "manifest", "package", "unmerge", "test", "checkdigest", "dumpdeps", "full-package", "cleanimage", "cleanbuild", "createpatch", "geturls", "version-dir", "version-package", "print-targets", "install-deps" ] ): addBuildaAction( x ) addBuildaAction( "print-revision", "Print the revision of the package and exit" ) addBuildaAction( "update", "Update a single package" ) addBuildaAction( "generate-jenkins-job") parser.add_argument( "packageNames", nargs = argparse.REMAINDER ) args = parser.parse_args( ) if args.stayQuiet == True or args.action in [ "version-dir", "version-package", "print-installable", "print-installed", "print-targets" ]: utils.setVerbose( -1 ) elif args.verbose: utils.setVerbose( args.verbose ) emergeSettings.set( "General", "WorkOffline", args.offline ) emergeSettings.set( "General", "EMERGE_NOCOPY", args.nocopy ) emergeSettings.set( "General", "EMERGE_NOCLEAN", args.noclean ) + emergeSettings.set( "General", "CompileFast", args.compile_fast ) emergeSettings.set( "General", "EMERGE_FORCED", args.forced ) emergeSettings.set( "General", "EMERGE_BUILDTESTS", args.buildTests ) emergeSettings.set( "General", "EMERGE_BUILDTYPE", args.buildType ) emergeSettings.set( "PortageVersions", "DefaultTarget", args.target ) emergeSettings.set( "General", "EMERGE_OPTIONS", ";".join( args.options ) ) emergeSettings.set( "General", "EMERGE_LOG_DIR", args.log_dir ) emergeSettings.set( "General", "EMERGE_TRACE", args.trace ) emergeSettings.set( "General", "EMERGE_PKGPATCHLVL", args.patchlevel ) portage.PortageInstance.options = args.options if args.search: for package in args.packageNames: category = "" if not package.find( "/" ) == -1: (category, package) = package.split( "/" ) portageSearch.printSearch( category, package ) return True if args.action in [ "install-deps", "update", "update-all", "package" ] or args.update_fast: args.ignoreInstalled = True if args.action in [ "update", "update-all" ]: args.noclean = True utils.debug( "buildAction: %s" % args.action ) utils.debug( "doPretend: %s" % args.probe, 1 ) utils.debug( "packageName: %s" % args.packageNames ) utils.debug( "buildType: %s" % args.buildType ) utils.debug( "buildTests: %s" % args.buildTests ) utils.debug( "verbose: %d" % utils.verbose( ), 1 ) utils.debug( "trace: %s" % args.trace, 1 ) utils.debug( "KDEROOT: %s" % EmergeStandardDirs.emergeRoot( ), 1 ) utils.debug_line( ) if args.print_installed: printInstalled( ) elif args.print_installable: portage.printInstallables( ) elif args.list_file: handleSinglePackage( "", args ) else: for x in args.packageNames: if not handleSinglePackage( x, args ): return False return True if __name__ == '__main__': succes = True try: utils.startTimer( "Emerge" ) doUpdateTitle = True def updateTitle( startTime, title ): while ( doUpdateTitle ): delta = datetime.datetime.now( ) - startTime utils.setConsoleTitle( "emerge %s %s" % (title, delta) ) time.sleep( 1 ) tittleThread = threading.Thread( target = updateTitle, args = (datetime.datetime.now( ), " ".join( sys.argv[ 1: ] ),) ) tittleThread.setDaemon( True ) tittleThread.start( ) succes = main( ) except KeyboardInterrupt: pass except portage.PortageException as e: utils.debug(e.exception, 1) utils.error(e) except Exception as e: print( e ) traceback.print_tb( e.__traceback__ ) finally: utils.stopTimer( "Emerge" ) doUpdateTitle = False if emergeSettings.getboolean( "EmergeDebug", "DumpSettings", False ): emergeSettings.dump( ) if not succes: exit( 1 )