diff options
Diffstat (limited to 'bitbake-dev')
24 files changed, 503 insertions, 374 deletions
diff --git a/bitbake-dev/bin/bitbake b/bitbake-dev/bin/bitbake index cabdf2b452..33ae1b96e9 100755 --- a/bitbake-dev/bin/bitbake +++ b/bitbake-dev/bin/bitbake @@ -26,9 +26,8 @@ import sys, os, getopt, re, time, optparse, xmlrpclib sys.path.insert(0,os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib')) import bb from bb import cooker -from bb import daemonize from bb import ui -from bb.ui import uievent + __version__ = "1.9.0" @@ -144,11 +143,14 @@ Default BBFILES are the .bb files in the current directory.""" ) configuration.pkgs_to_build = [] configuration.pkgs_to_build.extend(args[1:]) + #server = bb.server.xmlrpc + server = bb.server.none + # Save a logfile for cooker into the current working directory. When the # server is daemonized this logfile will be truncated. cooker_logfile = os.path.join (os.getcwd(), "cooker.log") - cooker = bb.cooker.BBCooker(configuration, bb.server.xmlrpc) + cooker = bb.cooker.BBCooker(configuration, server) # Clear away any spurious environment variables. But don't wipe the # environment totally. This is necessary to ensure the correct operation @@ -157,19 +159,15 @@ Default BBFILES are the .bb files in the current directory.""" ) cooker.parseCommandLine() + serverinfo = server.BitbakeServerInfo(cooker.server) - - - host = cooker.server.host - port = cooker.server.port - - daemonize.createDaemon(cooker.serve, cooker_logfile) + server.BitBakeServerFork(serverinfo, cooker.serve, cooker_logfile) del cooker + sys.excepthook = print_exception + # Setup a connection to the server (cooker) - server = xmlrpclib.Server("http://%s:%s" % (host, port), allow_none=True) - # Setup an event receiving queue - eventHandler = uievent.BBUIEventQueue(server) + serverConnection = server.BitBakeServerConnection(serverinfo) # Launch the UI if configuration.ui: @@ -182,30 +180,16 @@ Default BBFILES are the .bb files in the current directory.""" ) # suggest a fixed set this allows you to have flexibility in which # ones are available. exec "from bb.ui import " + ui - exec "return_value = " + ui + ".init(server, eventHandler)" + exec "return_value = " + ui + ".init(serverConnection.connection, serverConnection.events)" except ImportError: print "FATAL: Invalid user interface '%s' specified. " % ui print "Valid interfaces are 'ncurses', 'depexp' or the default, 'knotty'." except Exception, e: print "FATAL: Unable to start to '%s' UI: %s." % (configuration.ui, e.message) finally: - # Don't wait for server indefinitely - import socket - socket.setdefaulttimeout(2) - try: - eventHandler.system_quit() - except: - pass - try: - server.terminateServer() - except: - pass + serverConnection.terminate() return return_value if __name__ == "__main__": - print """WARNING, WARNING, WARNING -This is a Bitbake from the Unstable/Development 1.9 Branch. This software is a work in progress and should only be used by Bitbake developers/testers""" - ret = main() sys.exit(ret) - diff --git a/bitbake-dev/lib/bb/build.py b/bitbake-dev/lib/bb/build.py index 65e8118b4f..6d80b4b549 100644 --- a/bitbake-dev/lib/bb/build.py +++ b/bitbake-dev/lib/bb/build.py @@ -55,7 +55,7 @@ class TaskBase(event.Event): def __init__(self, t, d ): self._task = t self._package = bb.data.getVar("PF", d, 1) - event.Event.__init__(self, d) + event.Event.__init__(self) self._message = "package %s: task %s: %s" % (bb.data.getVar("PF", d, 1), t, bb.event.getName(self)[4:]) def getTask(self): @@ -286,9 +286,9 @@ def exec_task(task, d): data.setVar('OVERRIDES', 'task-%s:%s' % (task[3:], old_overrides), localdata) data.update_data(localdata) data.expandKeys(localdata) - event.fire(TaskStarted(task, localdata)) + event.fire(TaskStarted(task, localdata), localdata) exec_func(task, localdata) - event.fire(TaskSucceeded(task, localdata)) + event.fire(TaskSucceeded(task, localdata), localdata) except FuncFailed, message: # Try to extract the optional logfile try: @@ -298,7 +298,7 @@ def exec_task(task, d): msg = message bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % message ) failedevent = TaskFailed(msg, logfile, task, d) - event.fire(failedevent) + event.fire(failedevent, d) raise EventException("Function failed in task: %s" % message, failedevent) # make stamp, or cause event and raise exception diff --git a/bitbake-dev/lib/bb/command.py b/bitbake-dev/lib/bb/command.py index 1a1bf00b33..2bb5365c0c 100644 --- a/bitbake-dev/lib/bb/command.py +++ b/bitbake-dev/lib/bb/command.py @@ -94,9 +94,9 @@ class Command: def finishAsyncCommand(self, error = None): if error: - bb.event.fire(bb.command.CookerCommandFailed(self.cooker.configuration.event_data, error)) + bb.event.fire(bb.command.CookerCommandFailed(error), self.cooker.configuration.event_data) else: - bb.event.fire(bb.command.CookerCommandCompleted(self.cooker.configuration.event_data)) + bb.event.fire(bb.command.CookerCommandCompleted(), self.cooker.configuration.event_data) self.currentAsyncCommand = None @@ -247,24 +247,24 @@ class CookerCommandCompleted(bb.event.Event): """ Cooker command completed """ - def __init__(self, data): - bb.event.Event.__init__(self, data) + def __init__(self): + bb.event.Event.__init__(self) class CookerCommandFailed(bb.event.Event): """ Cooker command completed """ - def __init__(self, data, error): - bb.event.Event.__init__(self, data) + def __init__(self, error): + bb.event.Event.__init__(self) self.error = error class CookerCommandSetExitCode(bb.event.Event): """ Set the exit code for a cooker command """ - def __init__(self, data, exitcode): - bb.event.Event.__init__(self, data) + def __init__(self, exitcode): + bb.event.Event.__init__(self) self.exitcode = int(exitcode) diff --git a/bitbake-dev/lib/bb/cooker.py b/bitbake-dev/lib/bb/cooker.py index 1bf7d4bd14..25131b7406 100644 --- a/bitbake-dev/lib/bb/cooker.py +++ b/bitbake-dev/lib/bb/cooker.py @@ -245,7 +245,7 @@ class BBCooker: def compareRevisions(self): ret = bb.fetch.fetcher_compare_revisons(self.configuration.data) - bb.event.fire(bb.command.CookerCommandSetExitCode(self.configuration.event_data, ret)) + bb.event.fire(bb.command.CookerCommandSetExitCode(ret), self.configuration.event_data) def showEnvironment(self, buildfile = None, pkgs_to_build = []): """ @@ -403,7 +403,7 @@ class BBCooker: Generate an event with the result """ depgraph = self.generateDepTreeData(pkgs_to_build, task) - bb.event.fire(bb.event.DepTreeGenerated(self.configuration.data, depgraph)) + bb.event.fire(bb.event.DepTreeGenerated(depgraph), self.configuration.data) def generateDotGraphFiles(self, pkgs_to_build, task): """ @@ -544,7 +544,7 @@ class BBCooker: bb.fetch.fetcher_init(self.configuration.data) - bb.event.fire(bb.event.ConfigParsed(self.configuration.data)) + bb.event.fire(bb.event.ConfigParsed(), self.configuration.data) except IOError, e: bb.msg.fatal(bb.msg.domain.Parsing, "Error when parsing %s: %s" % (afile, str(e))) @@ -657,7 +657,7 @@ class BBCooker: taskdata.add_provider(self.configuration.data, self.status, item) buildname = bb.data.getVar("BUILDNAME", self.configuration.data) - bb.event.fire(bb.event.BuildStarted(buildname, [item], self.configuration.event_data)) + bb.event.fire(bb.event.BuildStarted(buildname, [item]), self.configuration.event_data) # Execute the runqueue runlist = [[item, "do_%s" % task]] @@ -680,7 +680,7 @@ class BBCooker: retval = False if not retval: self.command.finishAsyncCommand() - bb.event.fire(bb.event.BuildCompleted(buildname, item, self.configuration.event_data, failures)) + bb.event.fire(bb.event.BuildCompleted(buildname, item, failures), self.configuration.event_data) return False return 0.5 @@ -716,14 +716,14 @@ class BBCooker: retval = False if not retval: self.command.finishAsyncCommand() - bb.event.fire(bb.event.BuildCompleted(buildname, targets, self.configuration.event_data, failures)) + bb.event.fire(bb.event.BuildCompleted(buildname, targets, failures), self.configuration.event_data) return None return 0.5 self.buildSetVars() buildname = bb.data.getVar("BUILDNAME", self.configuration.data) - bb.event.fire(bb.event.BuildStarted(buildname, targets, self.configuration.event_data)) + bb.event.fire(bb.event.BuildStarted(buildname, targets), self.configuration.event_data) localdata = data.createCopy(self.configuration.data) bb.data.update_data(localdata) @@ -786,7 +786,7 @@ class BBCooker: self.cookerState = cookerParsed return None - return 0.00001 + return True def checkPackages(self, pkgs_to_build): @@ -904,15 +904,15 @@ class BBCooker: else: self.server.serve_forever() - bb.event.fire(CookerExit(self.configuration.event_data)) + bb.event.fire(CookerExit(), self.configuration.event_data) class CookerExit(bb.event.Event): """ Notify clients of the Cooker shutdown """ - def __init__(self, d): - bb.event.Event.__init__(self, d) + def __init__(self): + bb.event.Event.__init__(self) class CookerParser: def __init__(self, cooker, filelist, masked): @@ -932,8 +932,6 @@ class CookerParser: self.pointer = 0 def parse_next(self): - print "Pointer %d" % self.pointer - if self.pointer < len(self.filelist): f = self.filelist[self.pointer] cooker = self.cooker @@ -964,7 +962,7 @@ class CookerParser: cooker.bb_cache.remove(f) raise finally: - bb.event.fire(bb.event.ParseProgress(cooker.configuration.event_data, self.cached, self.parsed, self.skipped, self.masked, self.error, self.total)) + bb.event.fire(bb.event.ParseProgress(self.cached, self.parsed, self.skipped, self.masked, self.error, self.total), cooker.configuration.event_data) self.pointer += 1 diff --git a/bitbake-dev/lib/bb/event.py b/bitbake-dev/lib/bb/event.py index 86b566febf..3062dc51be 100644 --- a/bitbake-dev/lib/bb/event.py +++ b/bitbake-dev/lib/bb/event.py @@ -24,27 +24,19 @@ BitBake build tools. import os, re import bb.utils +import pickle # This is the pid for which we should generate the event. This is set when # the runqueue forks off. worker_pid = 0 +worker_pipe = None class Event: """Base class for events""" - type = "Event" - def __init__(self, d): - self._data = d + def __init__(self): self.pid = worker_pid - def getData(self): - return self._data - - def setData(self, data): - self._data = data - - data = property(getData, setData, None, "data property") - NotHandled = 0 Handled = 1 @@ -56,33 +48,48 @@ _handlers = {} _ui_handlers = {} _ui_handler_seq = 0 -def fire(event): +def fire(event, d): """Fire off an Event""" + if worker_pid != 0: + worker_fire(event, d) + return + for handler in _handlers: h = _handlers[handler] + event.data = d if type(h).__name__ == "code": exec(h) tmpHandler(event) else: h(event) - - # Remove the event data elements for UI handlers - too much data otherwise - # They can request data if they need it - event.data = None - event._data = None + del event.data errors = [] for h in _ui_handlers: #print "Sending event %s" % event - classid = "%s.%s" % (event.__class__.__module__, event.__class__.__name__) try: - _ui_handlers[h].event.send((classid, event)) + # We use pickle here since it better handles object instances + # which xmlrpc's marshaller does not. Events *must* be serializable + # by pickle. + _ui_handlers[h].event.send((pickle.dumps(event))) except: errors.append(h) for h in errors: del _ui_handlers[h] +def worker_fire(event, d): + data = "<event>" + pickle.dumps(event) + "</event>" + if os.write(worker_pipe, data) != len (data): + print "Error sending event to server (short write)" + +def fire_from_worker(event, d): + if not event.startswith("<event>") or not event.endswith("</event>"): + print "Error, not an event" + return + event = pickle.loads(event[7:-8]) + bb.event.fire(event, d) + def register(name, handler): """Register an Event handler""" @@ -128,17 +135,17 @@ class ConfigParsed(Event): class RecipeParsed(Event): """ Recipe Parsing Complete """ - def __init__(self, fn, d): + def __init__(self, fn): self.fn = fn - Event.__init__(self, d) + Event.__init__(self) class StampUpdate(Event): """Trigger for any adjustment of the stamp files to happen""" - def __init__(self, targets, stampfns, d): + def __init__(self, targets, stampfns): self._targets = targets self._stampfns = stampfns - Event.__init__(self, d) + Event.__init__(self) def getStampPrefix(self): return self._stampfns @@ -149,30 +156,13 @@ class StampUpdate(Event): stampPrefix = property(getStampPrefix) targets = property(getTargets) -class PkgBase(Event): - """Base class for package events""" - - def __init__(self, t, d): - self._pkg = t - Event.__init__(self, d) - self._message = "package %s: %s" % (bb.data.getVar("P", d, 1), getName(self)[3:]) - - def getPkg(self): - return self._pkg - - def setPkg(self, pkg): - self._pkg = pkg - - pkg = property(getPkg, setPkg, None, "pkg property") - - class BuildBase(Event): """Base class for bbmake run events""" - def __init__(self, n, p, c, failures = 0): + def __init__(self, n, p, failures = 0): self._name = n self._pkgs = p - Event.__init__(self, c) + Event.__init__(self) self._failures = failures def getPkgs(self): @@ -204,20 +194,7 @@ class BuildBase(Event): cfg = property(getCfg, setCfg, None, "cfg property") -class DepBase(PkgBase): - """Base class for dependency events""" - def __init__(self, t, data, d): - self._dep = d - PkgBase.__init__(self, t, data) - - def getDep(self): - return self._dep - - def setDep(self, dep): - self._dep = dep - - dep = property(getDep, setDep, None, "dep property") class BuildStarted(BuildBase): @@ -228,18 +205,13 @@ class BuildCompleted(BuildBase): """bbmake build run completed""" -class UnsatisfiedDep(DepBase): - """Unsatisfied Dependency""" - -class RecursiveDep(DepBase): - """Recursive Dependency""" class NoProvider(Event): """No Provider for an Event""" - def __init__(self, item, data, runtime=False): - Event.__init__(self, data) + def __init__(self, item, runtime=False): + Event.__init__(self) self._item = item self._runtime = runtime @@ -252,8 +224,8 @@ class NoProvider(Event): class MultipleProviders(Event): """Multiple Providers""" - def __init__(self, item, candidates, data, runtime = False): - Event.__init__(self, data) + def __init__(self, item, candidates, runtime = False): + Event.__init__(self) self._item = item self._candidates = candidates self._is_runtime = runtime @@ -281,8 +253,8 @@ class ParseProgress(Event): Parsing Progress Event """ - def __init__(self, d, cached, parsed, skipped, masked, errors, total): - Event.__init__(self, d) + def __init__(self, cached, parsed, skipped, masked, errors, total): + Event.__init__(self) self.cached = cached self.parsed = parsed self.skipped = skipped @@ -296,7 +268,7 @@ class DepTreeGenerated(Event): Event when a dependency tree has been generated """ - def __init__(self, d, depgraph): - Event.__init__(self, d) + def __init__(self, depgraph): + Event.__init__(self) self._depgraph = depgraph diff --git a/bitbake-dev/lib/bb/fetch/cvs.py b/bitbake-dev/lib/bb/fetch/cvs.py index d8bd4eaf75..90a006500e 100644 --- a/bitbake-dev/lib/bb/fetch/cvs.py +++ b/bitbake-dev/lib/bb/fetch/cvs.py @@ -41,7 +41,7 @@ class Cvs(Fetch): """ Check to see if a given url can be fetched with cvs. """ - return ud.type in ['cvs', 'pserver'] + return ud.type in ['cvs'] def localpath(self, url, ud, d): if not "module" in ud.parm: diff --git a/bitbake-dev/lib/bb/fetch/git.py b/bitbake-dev/lib/bb/fetch/git.py index 43053d6c46..0e68325db9 100644 --- a/bitbake-dev/lib/bb/fetch/git.py +++ b/bitbake-dev/lib/bb/fetch/git.py @@ -51,6 +51,10 @@ class Git(Fetch): ud.branch = ud.parm.get("branch", "master") + gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.')) + ud.mirrortarball = 'git_%s.tar.gz' % (gitsrcname) + ud.clonedir = os.path.join(data.expand('${GITDIR}', d), gitsrcname) + tag = Fetch.srcrev_internal_helper(ud, d) if tag is True: ud.tag = self.latest_revision(url, ud, d) @@ -60,7 +64,18 @@ class Git(Fetch): if not ud.tag or ud.tag == "master": ud.tag = self.latest_revision(url, ud, d) - ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, ud.path.replace('/', '.'), ud.tag), d) + subdir = ud.parm.get("subpath", "") + if subdir != "": + if subdir.endswith("/"): + subdir = subdir[:-1] + subdirpath = os.path.join(ud.path, subdir); + else: + subdirpath = ud.path; + + if 'fullclone' in ud.parm: + ud.localfile = ud.mirrortarball + else: + ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, subdirpath.replace('/', '.'), ud.tag), d) return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile) @@ -76,24 +91,20 @@ class Git(Fetch): else: username = "" - gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.')) - - repofilename = 'git_%s.tar.gz' % (gitsrcname) - repofile = os.path.join(data.getVar("DL_DIR", d, 1), repofilename) - repodir = os.path.join(data.expand('${GITDIR}', d), gitsrcname) + repofile = os.path.join(data.getVar("DL_DIR", d, 1), ud.mirrortarball) coname = '%s' % (ud.tag) - codir = os.path.join(repodir, coname) + codir = os.path.join(ud.clonedir, coname) - if not os.path.exists(repodir): - if Fetch.try_mirror(d, repofilename): - bb.mkdirhier(repodir) - os.chdir(repodir) + if not os.path.exists(ud.clonedir): + if Fetch.try_mirror(d, ud.mirrortarball): + bb.mkdirhier(ud.clonedir) + os.chdir(ud.clonedir) runfetchcmd("tar -xzf %s" % (repofile), d) else: - runfetchcmd("git clone -n %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, repodir), d) + runfetchcmd("git clone -n %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, ud.clonedir), d) - os.chdir(repodir) + os.chdir(ud.clonedir) # Remove all but the .git directory if not self._contains_ref(ud.tag, d): runfetchcmd("rm * -Rf", d) @@ -102,25 +113,45 @@ class Git(Fetch): runfetchcmd("git prune-packed", d) runfetchcmd("git pack-redundant --all | xargs -r rm", d) - os.chdir(repodir) + os.chdir(ud.clonedir) mirror_tarballs = data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True) - if mirror_tarballs != "0": + if mirror_tarballs != "0" or 'fullclone' in ud.parm: bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git repository") runfetchcmd("tar -czf %s %s" % (repofile, os.path.join(".", ".git", "*") ), d) + if 'fullclone' in ud.parm: + return + if os.path.exists(codir): bb.utils.prunedir(codir) + subdir = ud.parm.get("subpath", "") + if subdir != "": + if subdir.endswith("/"): + subdirbase = os.path.basename(subdir[:-1]) + else: + subdirbase = os.path.basename(subdir) + else: + subdirbase = "" + + if subdir != "": + readpathspec = ":%s" % (subdir) + codir = os.path.join(codir, "git") + coprefix = os.path.join(codir, subdirbase, "") + else: + readpathspec = "" + coprefix = os.path.join(codir, "git", "") + bb.mkdirhier(codir) - os.chdir(repodir) - runfetchcmd("git read-tree %s" % (ud.tag), d) - runfetchcmd("git checkout-index -q -f --prefix=%s -a" % (os.path.join(codir, "git", "")), d) + os.chdir(ud.clonedir) + runfetchcmd("git read-tree %s%s" % (ud.tag, readpathspec), d) + runfetchcmd("git checkout-index -q -f --prefix=%s -a" % (coprefix), d) os.chdir(codir) bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git checkout") runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.join(".", "*") ), d) - os.chdir(repodir) + os.chdir(ud.clonedir) bb.utils.prunedir(codir) def suppports_srcrev(self): @@ -145,7 +176,10 @@ class Git(Fetch): else: username = "" - output = runfetchcmd("git ls-remote %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, ud.branch), d, True) + cmd = "git ls-remote %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, ud.branch) + output = runfetchcmd(cmd, d, True) + if not output: + raise bb.fetch.FetchError("Fetch command %s gave empty output\n" % (cmd)) return output.split()[0] def _build_revision(self, url, ud, d): @@ -156,20 +190,20 @@ class Git(Fetch): Return a suitable buildindex for the revision specified. This is done by counting revisions using "git rev-list" which may or may not work in different circumstances. """ - gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.')) - repodir = os.path.join(data.expand('${GITDIR}', d), gitsrcname) cwd = os.getcwd() # Check if we have the rev already - if not os.path.exists(repodir): + + if not os.path.exists(ud.clonedir): + print "no repo" self.go(None, ud, d) - if not os.path.exists(repodir): - bb.msg.error(bb.msg.domain.Fetcher, "GIT repository for %s doesn't exist in %s, cannot get sortable buildnumber, using old value" % (url, repodir)) + if not os.path.exists(ud.clonedir): + bb.msg.error(bb.msg.domain.Fetcher, "GIT repository for %s doesn't exist in %s, cannot get sortable buildnumber, using old value" % (url, ud.clonedir)) return None - os.chdir(repodir) + os.chdir(ud.clonedir) if not self._contains_ref(rev, d): self.go(None, ud, d) diff --git a/bitbake-dev/lib/bb/fetch/local.py b/bitbake-dev/lib/bb/fetch/local.py index 577774e597..f9bdf589cb 100644 --- a/bitbake-dev/lib/bb/fetch/local.py +++ b/bitbake-dev/lib/bb/fetch/local.py @@ -33,9 +33,9 @@ from bb.fetch import Fetch class Local(Fetch): def supports(self, url, urldata, d): """ - Check to see if a given url can be fetched with cvs. + Check to see if a given url represents a local fetch. """ - return urldata.type in ['file','patch'] + return urldata.type in ['file'] def localpath(self, url, urldata, d): """ diff --git a/bitbake-dev/lib/bb/fetch/svk.py b/bitbake-dev/lib/bb/fetch/svk.py index 442f85804f..120dad9d4e 100644 --- a/bitbake-dev/lib/bb/fetch/svk.py +++ b/bitbake-dev/lib/bb/fetch/svk.py @@ -36,7 +36,7 @@ class Svk(Fetch): """Class to fetch a module or modules from svk repositories""" def supports(self, url, ud, d): """ - Check to see if a given url can be fetched with cvs. + Check to see if a given url can be fetched with svk. """ return ud.type in ['svk'] diff --git a/bitbake-dev/lib/bb/fetch/wget.py b/bitbake-dev/lib/bb/fetch/wget.py index a0dca94040..fd93c7ec46 100644 --- a/bitbake-dev/lib/bb/fetch/wget.py +++ b/bitbake-dev/lib/bb/fetch/wget.py @@ -36,7 +36,7 @@ class Wget(Fetch): """Class to fetch urls via 'wget'""" def supports(self, url, ud, d): """ - Check to see if a given url can be fetched with cvs. + Check to see if a given url can be fetched with wget. """ return ud.type in ['http','https','ftp'] diff --git a/bitbake-dev/lib/bb/msg.py b/bitbake-dev/lib/bb/msg.py index 7990833c2e..3fcf7091be 100644 --- a/bitbake-dev/lib/bb/msg.py +++ b/bitbake-dev/lib/bb/msg.py @@ -47,9 +47,9 @@ domain = bb.utils.Enum( class MsgBase(bb.event.Event): """Base class for messages""" - def __init__(self, msg, d ): + def __init__(self, msg): self._message = msg - event.Event.__init__(self, d) + event.Event.__init__(self) class MsgDebug(MsgBase): """Debug Message""" @@ -100,26 +100,26 @@ def debug(level, domain, msg, fn = None): if not domain: domain = 'default' if debug_level[domain] >= level: - bb.event.fire(MsgDebug(msg, None)) + bb.event.fire(MsgDebug(msg), None) def note(level, domain, msg, fn = None): if not domain: domain = 'default' if level == 1 or verbose or debug_level[domain] >= 1: - bb.event.fire(MsgNote(msg, None)) + bb.event.fire(MsgNote(msg), None) def warn(domain, msg, fn = None): - bb.event.fire(MsgWarn(msg, None)) + bb.event.fire(MsgWarn(msg), None) def error(domain, msg, fn = None): - bb.event.fire(MsgError(msg, None)) + bb.event.fire(MsgError(msg), None) print 'ERROR: ' + msg def fatal(domain, msg, fn = None): - bb.event.fire(MsgFatal(msg, None)) + bb.event.fire(MsgFatal(msg), None) print 'FATAL: ' + msg sys.exit(1) def plain(msg, fn = None): - bb.event.fire(MsgPlain(msg, None)) + bb.event.fire(MsgPlain(msg), None) diff --git a/bitbake-dev/lib/bb/parse/parse_py/BBHandler.py b/bitbake-dev/lib/bb/parse/parse_py/BBHandler.py index f0c3409568..f34599136c 100644 --- a/bitbake-dev/lib/bb/parse/parse_py/BBHandler.py +++ b/bitbake-dev/lib/bb/parse/parse_py/BBHandler.py @@ -114,7 +114,7 @@ def finalise(fn, d): tasklist = data.getVar('__BBTASKS', d) or [] bb.build.add_tasks(tasklist, d) - bb.event.fire(bb.event.RecipeParsed(fn, d)) + bb.event.fire(bb.event.RecipeParsed(fn), d) def handle(fn, d, include = 0): diff --git a/bitbake-dev/lib/bb/parse/parse_py/ConfHandler.py b/bitbake-dev/lib/bb/parse/parse_py/ConfHandler.py index c9f1ea13fb..23316ada58 100644 --- a/bitbake-dev/lib/bb/parse/parse_py/ConfHandler.py +++ b/bitbake-dev/lib/bb/parse/parse_py/ConfHandler.py @@ -34,10 +34,17 @@ __require_regexp__ = re.compile( r"require\s+(.+)" ) __export_regexp__ = re.compile( r"export\s+(.+)" ) def init(data): - if not bb.data.getVar('TOPDIR', data): - bb.data.setVar('TOPDIR', os.getcwd(), data) + topdir = bb.data.getVar('TOPDIR', data) + if not topdir: + topdir = os.getcwd() + bb.data.setVar('TOPDIR', topdir, data) if not bb.data.getVar('BBPATH', data): - bb.data.setVar('BBPATH', os.path.join(sys.prefix, 'share', 'bitbake'), data) + from pkg_resources import Requirement, resource_filename + bitbake = Requirement.parse("bitbake") + datadir = resource_filename(bitbake, "../share/bitbake") + basedir = resource_filename(bitbake, "..") + bb.data.setVar('BBPATH', '%s:%s:%s' % (topdir, datadir, basedir), data) + def supports(fn, d): return localpath(fn, d)[-5:] == ".conf" diff --git a/bitbake-dev/lib/bb/runqueue.py b/bitbake-dev/lib/bb/runqueue.py index 8b6e12d185..c3ad442e47 100644 --- a/bitbake-dev/lib/bb/runqueue.py +++ b/bitbake-dev/lib/bb/runqueue.py @@ -857,6 +857,7 @@ class RunQueue: self.runq_running = [] self.runq_complete = [] self.build_pids = {} + self.build_pipes = {} self.failed_fnids = [] # Mark initial buildable tasks @@ -870,7 +871,7 @@ class RunQueue: self.state = runQueueRunning - event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp, self.cfgData)) + event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp), self.cfgData) def task_complete(self, task): """ @@ -903,7 +904,7 @@ class RunQueue: self.stats.taskFailed() fnid = self.runq_fnid[task] self.failed_fnids.append(fnid) - bb.event.fire(runQueueTaskFailed(task, self.stats, self, self.cfgData)) + bb.event.fire(runQueueTaskFailed(task, self.stats, self), self.cfgData) if self.taskData.abort: self.state = runQueueCleanup @@ -935,53 +936,67 @@ class RunQueue: sys.stdout.flush() sys.stderr.flush() - try: + try: + pipein, pipeout = os.pipe() pid = os.fork() except OSError, e: bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) if pid == 0: + os.close(pipein) # Save out the PID so that the event can include it the # events bb.event.worker_pid = os.getpid() + bb.event.worker_pipe = pipeout - bb.event.fire(runQueueTaskStarted(task, self.stats, self, self.cfgData)) - bb.msg.note(1, bb.msg.domain.RunQueue, - "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.stats.active + 1, - self.stats.total, - task, - self.get_user_idstring(task))) self.state = runQueueChildProcess # Make the child the process group leader os.setpgid(0, 0) + # No stdin newsi = os.open('/dev/null', os.O_RDWR) os.dup2(newsi, sys.stdin.fileno()) + + bb.event.fire(runQueueTaskStarted(task, self.stats, self), self.cfgData) + bb.msg.note(1, bb.msg.domain.RunQueue, + "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.stats.active + 1, + self.stats.total, + task, + self.get_user_idstring(task))) + bb.data.setVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", self, self.cooker.configuration.data) try: self.cooker.tryBuild(fn, taskname[3:]) except bb.build.EventException: bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") - sys.exit(1) + os._exit(1) except: bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") - raise - sys.exit(0) + os._exit(1) + os._exit(0) + self.build_pids[pid] = task + self.build_pipes[pid] = runQueuePipe(pipein, pipeout, self.cfgData) self.runq_running[task] = 1 self.stats.taskActive() if self.stats.active < self.number_tasks: continue + + for pipe in self.build_pipes: + self.build_pipes[pipe].read() + if self.stats.active > 0: result = os.waitpid(-1, os.WNOHANG) if result[0] is 0 and result[1] is 0: return task = self.build_pids[result[0]] del self.build_pids[result[0]] + self.build_pipes[result[0]].close() + del self.build_pipes[result[0]] if result[1] != 0: self.task_fail(task, result[1]) return self.task_complete(task) self.stats.taskCompleted() - bb.event.fire(runQueueTaskCompleted(task, self.stats, self, self.cfgData)) + bb.event.fire(runQueueTaskCompleted(task, self.stats, self), self.cfgData) continue if len(self.failed_fnids) != 0: @@ -1006,6 +1021,8 @@ class RunQueue: os.kill(-k, signal.SIGINT) except: pass + for pipe in self.build_pipes: + self.build_pipes[pipe].read() def finish_runqueue(self, now = False): self.state = runQueueCleanUp @@ -1013,7 +1030,7 @@ class RunQueue: self.finish_runqueue_now() try: while self.stats.active > 0: - bb.event.fire(runQueueExitWait(self.stats.active, self.cfgData)) + bb.event.fire(runQueueExitWait(self.stats.active), self.cfgData) bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % self.stats.active) tasknum = 1 for k, v in self.build_pids.iteritems(): @@ -1024,11 +1041,13 @@ class RunQueue: return task = self.build_pids[result[0]] del self.build_pids[result[0]] + self.build_pipes[result[0]].close() + del self.build_pipes[result[0]] if result[1] != 0: self.task_fail(task, result[1]) else: self.stats.taskCompleted() - bb.event.fire(runQueueTaskCompleted(task, self.stats, self, self.cfgData)) + bb.event.fire(runQueueTaskCompleted(task, self.stats, self), self.cfgData) except: self.finish_runqueue_now() raise @@ -1078,43 +1097,43 @@ class runQueueExitWait(bb.event.Event): Event when waiting for task processes to exit """ - def __init__(self, remain, d): + def __init__(self, remain): self.remain = remain self.message = "Waiting for %s active tasks to finish" % remain - bb.event.Event.__init__(self, d) + bb.event.Event.__init__(self) class runQueueEvent(bb.event.Event): """ Base runQueue event class """ - def __init__(self, task, stats, rq, d): + def __init__(self, task, stats, rq): self.taskid = task self.taskstring = rq.get_user_idstring(task) self.stats = stats - bb.event.Event.__init__(self, d) + bb.event.Event.__init__(self) class runQueueTaskStarted(runQueueEvent): """ Event notifing a task was started """ - def __init__(self, task, stats, rq, d): - runQueueEvent.__init__(self, task, stats, rq, d) + def __init__(self, task, stats, rq): + runQueueEvent.__init__(self, task, stats, rq) self.message = "Running task %s (%d of %d) (%s)" % (task, stats.completed + stats.active + 1, self.stats.total, self.taskstring) class runQueueTaskFailed(runQueueEvent): """ Event notifing a task failed """ - def __init__(self, task, stats, rq, d): - runQueueEvent.__init__(self, task, stats, rq, d) + def __init__(self, task, stats, rq): + runQueueEvent.__init__(self, task, stats, rq) self.message = "Task %s failed (%s)" % (task, self.taskstring) class runQueueTaskCompleted(runQueueEvent): """ Event notifing a task completed """ - def __init__(self, task, stats, rq, d): - runQueueEvent.__init__(self, task, stats, rq, d) + def __init__(self, task, stats, rq): + runQueueEvent.__init__(self, task, stats, rq) self.message = "Task %s completed (%s)" % (task, self.taskstring) def check_stamp_fn(fn, taskname, d): @@ -1124,3 +1143,32 @@ def check_stamp_fn(fn, taskname, d): if taskid is not None: return rq.check_stamp_task(taskid) return None + +class runQueuePipe(): + """ + Abstraction for a pipe between a worker thread and the server + """ + def __init__(self, pipein, pipeout, d): + self.fd = pipein + os.close(pipeout) + self.queue = "" + self.d = d + + def read(self): + start = len(self.queue) + self.queue = self.queue + os.read(self.fd, 1024) + end = len(self.queue) + index = self.queue.find("</event>") + while index != -1: + bb.event.fire_from_worker(self.queue[:index+8], self.d) + self.queue = self.queue[index+8:] + index = self.queue.find("</event>") + return (end > start) + + def close(self): + while self.read(): + continue + if len(self.queue) > 0: + print "Warning, worker left partial message" + os.close(self.fd) + diff --git a/bitbake-dev/lib/bb/server/__init__.py b/bitbake-dev/lib/bb/server/__init__.py index 0dd04cf724..1a732236e2 100644 --- a/bitbake-dev/lib/bb/server/__init__.py +++ b/bitbake-dev/lib/bb/server/__init__.py @@ -1 +1,2 @@ import xmlrpc +import none diff --git a/bitbake-dev/lib/bb/server/none.py b/bitbake-dev/lib/bb/server/none.py index ef061bc5dd..ebda111582 100644 --- a/bitbake-dev/lib/bb/server/none.py +++ b/bitbake-dev/lib/bb/server/none.py @@ -1,5 +1,5 @@ # -# BitBake XMLRPC Server +# BitBake 'dummy' Passthrough Server # # Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer # Copyright (C) 2006 - 2008 Richard Purdie @@ -31,8 +31,11 @@ in the server's main loop. """ +import time import bb +from bb.ui import uievent import xmlrpclib +import pickle DEBUG = False @@ -44,31 +47,19 @@ class BitBakeServerCommands(): self.cooker = cooker self.server = server - def registerEventHandler(self, host, port): - """ - Register a remote UI Event Handler - """ - s = xmlrpclib.Server("http://%s:%d" % (host, port), allow_none=True) - return bb.event.register_UIHhandler(s) - - def unregisterEventHandler(self, handlerNum): - """ - Unregister a remote UI Event Handler - """ - return bb.event.unregister_UIHhandler(handlerNum) - def runCommand(self, command): """ Run a cooker command on the server """ + #print "Running Command %s" % command return self.cooker.command.runCommand(command) def terminateServer(self): """ Trigger the server to quit """ - self.server.quit = True - print "Server (cooker) exitting" + self.server.server_exit() + #print "Server (cooker) exitting" return def ping(self): @@ -77,63 +68,84 @@ class BitBakeServerCommands(): """ return True -class BitBakeXMLRPCServer(SimpleXMLRPCServer): +eventQueue = [] + +class BBUIEventQueue: + class event: + def __init__(self, parent): + self.parent = parent + @staticmethod + def send(event): + bb.server.none.eventQueue.append(pickle.loads(event)) + @staticmethod + def quit(): + return + + def __init__(self, BBServer): + self.eventQueue = bb.server.none.eventQueue + self.BBServer = BBServer + self.EventHandle = bb.event.register_UIHhandler(self) + + def getEvent(self): + if len(self.eventQueue) == 0: + return None + + return self.eventQueue.pop(0) + + def waitEvent(self, delay): + event = self.getEvent() + if event: + return event + self.BBServer.idle_commands(delay) + return self.getEvent() + + def queue_event(self, event): + self.eventQueue.append(event) + + def system_quit( self ):
+ bb.event.unregister_UIHhandler(self.EventHandle) + +class BitBakeServer(): # remove this when you're done with debugging # allow_reuse_address = True - def __init__(self, cooker, interface = ("localhost", 0)): - """ - Constructor - """ - SimpleXMLRPCServer.__init__(self, interface, - requestHandler=SimpleXMLRPCRequestHandler, - logRequests=False, allow_none=True) + def __init__(self, cooker): self._idlefuns = {} - self.host, self.port = self.socket.getsockname() - #self.register_introspection_functions() - commands = BitBakeServerCommands(self, cooker) - self.autoregister_all_functions(commands, "") - - def autoregister_all_functions(self, context, prefix): - """ - Convenience method for registering all functions in the scope - of this class that start with a common prefix - """ - methodlist = inspect.getmembers(context, inspect.ismethod) - for name, method in methodlist: - if name.startswith(prefix): - self.register_function(method, name[len(prefix):]) + self.commands = BitBakeServerCommands(self, cooker) def register_idle_function(self, function, data): """Register a function to be called while the server is idle""" assert callable(function) self._idlefuns[function] = data - def serve_forever(self): - """ - Serve Requests. Overloaded to honor a quit command - """ - self.quit = False - while not self.quit: - #print "Idle queue length %s" % len(self._idlefuns) - if len(self._idlefuns) == 0: - self.timeout = None - else: - self.timeout = 0 - self.handle_request() - #print "Idle timeout, running idle functions" - for function, data in self._idlefuns.items(): - try: - retval = function(self, data, False) - if not retval: - del self._idlefuns[function] - except SystemExit: - raise - except: - import traceback - traceback.print_exc() - pass + def idle_commands(self, delay): + #print "Idle queue length %s" % len(self._idlefuns) + #print "Idle timeout, running idle functions" + #if len(self._idlefuns) == 0: + nextsleep = delay + for function, data in self._idlefuns.items(): + try: + retval = function(self, data, False) + #print "Idle function returned %s" % (retval) + if retval is False: + del self._idlefuns[function] + elif retval is True: + nextsleep = None + elif nextsleep is None: + continue + elif retval < nextsleep: + nextsleep = retval + except SystemExit: + raise + except: + import traceback + traceback.print_exc() + pass + if nextsleep is not None: + #print "Sleeping for %s (%s)" % (nextsleep, delay) + time.sleep(nextsleep) + def server_exit(self): # Tell idle functions we're exiting for function, data in self._idlefuns.items(): try: @@ -141,5 +153,29 @@ class BitBakeXMLRPCServer(SimpleXMLRPCServer): except: pass - self.server_close() - return +class BitbakeServerInfo(): + def __init__(self, server): + self.server = server + self.commands = server.commands + +class BitBakeServerFork(): + def __init__(self, serverinfo, command, logfile): + serverinfo.forkCommand = command + serverinfo.logfile = logfile + +class BitBakeServerConnection(): + def __init__(self, serverinfo): + self.server = serverinfo.server + self.connection = serverinfo.commands + self.events = bb.server.none.BBUIEventQueue(self.server) + + def terminate(self): + try: + self.events.system_quit() + except: + pass + try: + self.connection.terminateServer() + except: + pass + diff --git a/bitbake-dev/lib/bb/server/xmlrpc.py b/bitbake-dev/lib/bb/server/xmlrpc.py index c5937abd66..b4d69f7be3 100644 --- a/bitbake-dev/lib/bb/server/xmlrpc.py +++ b/bitbake-dev/lib/bb/server/xmlrpc.py @@ -33,6 +33,8 @@ import bb import xmlrpclib +from bb import daemonize +from bb.ui import uievent DEBUG = False @@ -114,26 +116,34 @@ class BitBakeServer(SimpleXMLRPCServer): Serve Requests. Overloaded to honor a quit command """ self.quit = False + self.timeout = 0 # Run Idle calls for our first callback while not self.quit: #print "Idle queue length %s" % len(self._idlefuns) - if len(self._idlefuns) == 0: - self.timeout = None - else: - self.timeout = 0 self.handle_request() #print "Idle timeout, running idle functions" + nextsleep = None for function, data in self._idlefuns.items(): try: retval = function(self, data, False) - if not retval: + if retval is False: del self._idlefuns[function] + elif retval is True: + nextsleep = 0 + elif nextsleep is 0: + continue + elif nextsleep is None: + nextsleep = retval + elif retval < nextsleep: + nextsleep = retval except SystemExit: raise except: import traceback traceback.print_exc() pass - + if nextsleep is None and len(self._idlefuns) > 0: + nextsleep = 0 + self.timeout = nextsleep # Tell idle functions we're exiting for function, data in self._idlefuns.items(): try: @@ -143,3 +153,31 @@ class BitBakeServer(SimpleXMLRPCServer): self.server_close() return + +class BitbakeServerInfo(): + def __init__(self, server): + self.host = server.host + self.port = server.port + +class BitBakeServerFork(): + def __init__(self, serverinfo, command, logfile): + daemonize.createDaemon(command, logfile) + +class BitBakeServerConnection(): + def __init__(self, serverinfo): + self.connection = xmlrpclib.Server("http://%s:%s" % (serverinfo.host, serverinfo.port), allow_none=True) + self.events = uievent.BBUIEventQueue(self.connection) + + def terminate(self): + # Don't wait for server indefinitely + import socket + socket.setdefaulttimeout(2) + try: + self.events.system_quit() + except: + pass + try: + self.connection.terminateServer() + except: + pass + diff --git a/bitbake-dev/lib/bb/taskdata.py b/bitbake-dev/lib/bb/taskdata.py index 73ec2aa750..e3a60b9884 100644 --- a/bitbake-dev/lib/bb/taskdata.py +++ b/bitbake-dev/lib/bb/taskdata.py @@ -25,6 +25,19 @@ Task data collection and handling import bb +def re_match_strings(target, strings): + """ + Whether or not the string 'target' matches + any one string of the strings which can be regular expression string + """ + import re + + for name in strings: + if (name==target or + re.search(name,target)!=None): + return True + return False + class TaskData: """ BitBake Task Data implementation @@ -261,7 +274,7 @@ class TaskData: """ unresolved = [] for target in self.build_names_index: - if target in dataCache.ignored_dependencies: + if re_match_strings(target, dataCache.ignored_dependencies): continue if self.build_names_index.index(target) in self.failed_deps: continue @@ -276,7 +289,7 @@ class TaskData: """ unresolved = [] for target in self.run_names_index: - if target in dataCache.ignored_dependencies: + if re_match_strings(target, dataCache.ignored_dependencies): continue if self.run_names_index.index(target) in self.failed_rdeps: continue @@ -356,7 +369,7 @@ class TaskData: added internally during dependency resolution """ - if item in dataCache.ignored_dependencies: + if re_match_strings(item, dataCache.ignored_dependencies): return if not item in dataCache.providers: @@ -364,7 +377,7 @@ class TaskData: bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s' (but '%s' DEPENDS on or otherwise requires it)" % (item, self.get_dependees_str(item))) else: bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s'" % (item)) - bb.event.fire(bb.event.NoProvider(item, cfgData)) + bb.event.fire(bb.event.NoProvider(item), cfgData) raise bb.providers.NoProvider(item) if self.have_build_target(item): @@ -377,7 +390,7 @@ class TaskData: if not eligible: bb.msg.note(2, bb.msg.domain.Provider, "No buildable provider PROVIDES '%s' but '%s' DEPENDS on or otherwise requires it. Enable debugging and see earlier logs to find unbuildable providers." % (item, self.get_dependees_str(item))) - bb.event.fire(bb.event.NoProvider(item, cfgData)) + bb.event.fire(bb.event.NoProvider(item), cfgData) raise bb.providers.NoProvider(item) if len(eligible) > 1 and foundUnique == False: @@ -387,7 +400,7 @@ class TaskData: providers_list.append(dataCache.pkg_fn[fn]) bb.msg.note(1, bb.msg.domain.Provider, "multiple providers are available for %s (%s);" % (item, ", ".join(providers_list))) bb.msg.note(1, bb.msg.domain.Provider, "consider defining PREFERRED_PROVIDER_%s" % item) - bb.event.fire(bb.event.MultipleProviders(item, providers_list, cfgData)) + bb.event.fire(bb.event.MultipleProviders(item, providers_list), cfgData) self.consider_msgs_cache.append(item) for fn in eligible: @@ -407,7 +420,7 @@ class TaskData: (takes item names from RDEPENDS/PACKAGES namespace) """ - if item in dataCache.ignored_dependencies: + if re_match_strings(item, dataCache.ignored_dependencies): return if self.have_runtime_target(item): @@ -417,7 +430,7 @@ class TaskData: if not all_p: bb.msg.error(bb.msg.domain.Provider, "'%s' RDEPENDS/RRECOMMENDS or otherwise requires the runtime entity '%s' but it wasn't found in any PACKAGE or RPROVIDES variables" % (self.get_rdependees_str(item), item)) - bb.event.fire(bb.event.NoProvider(item, cfgData, runtime=True)) + bb.event.fire(bb.event.NoProvider(item, runtime=True), cfgData) raise bb.providers.NoRProvider(item) eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache) @@ -425,7 +438,7 @@ class TaskData: if not eligible: bb.msg.error(bb.msg.domain.Provider, "'%s' RDEPENDS/RRECOMMENDS or otherwise requires the runtime entity '%s' but it wasn't found in any PACKAGE or RPROVIDES variables of any buildable targets.\nEnable debugging and see earlier logs to find unbuildable targets." % (self.get_rdependees_str(item), item)) - bb.event.fire(bb.event.NoProvider(item, cfgData, runtime=True)) + bb.event.fire(bb.event.NoProvider(item, runtime=True), cfgData) raise bb.providers.NoRProvider(item) if len(eligible) > 1 and numberPreferred == 0: @@ -435,7 +448,7 @@ class TaskData: providers_list.append(dataCache.pkg_fn[fn]) bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (%s);" % (item, ", ".join(providers_list))) bb.msg.note(2, bb.msg.domain.Provider, "consider defining a PREFERRED_PROVIDER entry to match runtime %s" % item) - bb.event.fire(bb.event.MultipleProviders(item,providers_list, cfgData, runtime=True)) + bb.event.fire(bb.event.MultipleProviders(item,providers_list, runtime=True), cfgData) self.consider_msgs_cache.append(item) if numberPreferred > 1: @@ -445,7 +458,7 @@ class TaskData: providers_list.append(dataCache.pkg_fn[fn]) bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (top %s entries preferred) (%s);" % (item, numberPreferred, ", ".join(providers_list))) bb.msg.note(2, bb.msg.domain.Provider, "consider defining only one PREFERRED_PROVIDER entry to match runtime %s" % item) - bb.event.fire(bb.event.MultipleProviders(item,providers_list, cfgData, runtime=True)) + bb.event.fire(bb.event.MultipleProviders(item,providers_list, runtime=True), cfgData) self.consider_msgs_cache.append(item) # run through the list until we find one that we can build diff --git a/bitbake-dev/lib/bb/ui/crumbs/runningbuild.py b/bitbake-dev/lib/bb/ui/crumbs/runningbuild.py index 34f65d2396..401559255b 100644 --- a/bitbake-dev/lib/bb/ui/crumbs/runningbuild.py +++ b/bitbake-dev/lib/bb/ui/crumbs/runningbuild.py @@ -61,36 +61,36 @@ class RunningBuild (gobject.GObject): # If we have a pid attached to this message/event try and get the # (package, task) pair for it. If we get that then get the parent iter # for the message. - if event[1].has_key ('pid'): - pid = event[1]['pid'] + if hassattr(event, 'pid'): + pid = event.pid if self.pids_to_task.has_key(pid): (package, task) = self.pids_to_task[pid] parent = self.tasks_to_iter[(package, task)] - if event[0].startswith('bb.msg.Msg'): + if isinstance(event, bb.msg.Msg): # Set a pretty icon for the message based on it's type. - if (event[0].startswith ('bb.msg.MsgWarn')): + if isinstance(event, bb.msg.MsgWarn): icon = "dialog-warning" - elif (event[0].startswith ('bb.msg.MsgErr')): + elif isinstance(event, bb.msg.MsgErr): icon = "dialog-error" else: icon = None # Ignore the "Running task i of n .." messages - if (event[1]['_message'].startswith ("Running task")): + if (event._message.startswith ("Running task")): return # Add the message to the tree either at the top level if parent is # None otherwise as a descendent of a task. self.model.append (parent, - (event[0].split()[-1], # e.g. MsgWarn, MsgError + (event.__name__.split()[-1], # e.g. MsgWarn, MsgError package, task, - event[1]['_message'], + event._message, icon, False)) - elif event[0].startswith('bb.build.TaskStarted'): - (package, task) = (event[1]['_package'], event[1]['_task']) + elif isinstance(event, bb.build.TaskStarted): + (package, task) = (event._package, event._task) # Save out this PID. self.pids_to_task[pid] = (package,task) @@ -128,9 +128,9 @@ class RunningBuild (gobject.GObject): # Mark this task as active. self.model.set(i, self.model.COL_ICON, "gtk-execute") - elif event[0].startswith('bb.build.Task'): + elif isinstance(event, bb.build.Task): - if event[0].startswith('bb.build.TaskFailed'): + if isinstance(event, bb.build.TaskFailed): # Mark the task as failed i = self.tasks_to_iter[(package, task)] self.model.set(i, self.model.COL_ICON, "dialog-error") @@ -153,8 +153,8 @@ class RunningBuild (gobject.GObject): del self.tasks_to_iter[(package, task)] del self.pids_to_task[pid] - elif event[0].startswith('bb.event.BuildCompleted'): - failures = int (event[1]['_failures']) + elif isinstance(event, bb.event.BuildCompleted): + failures = int (event._failures) # Emit the appropriate signal depending on the number of failures if (failures > 1): diff --git a/bitbake-dev/lib/bb/ui/depexp.py b/bitbake-dev/lib/bb/ui/depexp.py index 0c559c7976..cfa5b6564e 100644 --- a/bitbake-dev/lib/bb/ui/depexp.py +++ b/bitbake-dev/lib/bb/ui/depexp.py @@ -229,12 +229,12 @@ def init(server, eventHandler): if event is None: continue - if event[0].startswith('bb.event.ParseProgress'): - x = event[1]['sofar'] - y = event[1]['total'] + if isinstance(event, bb.event.ParseProgress): + x = event.sofar + y = event.total if x == y: print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors." - % ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'], event[1]['errors'])) + % ( event.cached, event.parsed, event.skipped, event.masked, event.errors)) pbar.hide() gtk.gdk.threads_enter() pbar.progress.set_fraction(float(x)/float(y)) @@ -242,17 +242,17 @@ def init(server, eventHandler): gtk.gdk.threads_leave() continue - if event[0] == "bb.event.DepTreeGenerated": + if isinstance(event, bb.event.DepTreeGenerated): gtk.gdk.threads_enter() - parse(event[1]['_depgraph'], dep.pkg_model, dep.depends_model) + parse(event._depgraph, dep.pkg_model, dep.depends_model) gtk.gdk.threads_leave() - if event[0] == 'bb.command.CookerCommandCompleted': + if isinstance(event, bb.command.CookerCommandCompleted): continue - if event[0] == 'bb.command.CookerCommandFailed': - print "Command execution failed: %s" % event[1]['error'] + if isinstance(event, bb.command.CookerCommandFailed): + print "Command execution failed: %s" % event.error break - if event[0] == 'bb.cooker.CookerExit': + if isinstance(event, bb.cooker.CookerExit): break continue diff --git a/bitbake-dev/lib/bb/ui/knotty.py b/bitbake-dev/lib/bb/ui/knotty.py index 8a2afeeb6d..6baed836a1 100644 --- a/bitbake-dev/lib/bb/ui/knotty.py +++ b/bitbake-dev/lib/bb/ui/knotty.py @@ -53,29 +53,29 @@ def init(server, eventHandler): if event is None: continue #print event - if event[0].startswith('bb.msg.MsgPlain'): - print event[1]['_message'] + if isinstance(event, bb.msg.MsgPlain): + print event._message continue - if event[0].startswith('bb.msg.MsgDebug'): - print 'DEBUG: ' + event[1]['_message'] + if isinstance(event, bb.msg.MsgDebug): + print 'DEBUG: ' + event._message continue - if event[0].startswith('bb.msg.MsgNote'): - print 'NOTE: ' + event[1]['_message'] + if isinstance(event, bb.msg.MsgNote): + print 'NOTE: ' + event._message continue - if event[0].startswith('bb.msg.MsgWarn'): - print 'WARNING: ' + event[1]['_message'] + if isinstance(event, bb.msg.MsgWarn): + print 'WARNING: ' + event._message continue - if event[0].startswith('bb.msg.MsgError'): + if isinstance(event, bb.msg.MsgError): return_value = 1 - print 'ERROR: ' + event[1]['_message'] + print 'ERROR: ' + event._message continue - if event[0].startswith('bb.msg.MsgFatal'): + if isinstance(event, bb.msg.MsgFatal): return_value = 1 - print 'FATAL: ' + event[1]['_message'] + print 'FATAL: ' + event._message break - if event[0].startswith('bb.build.TaskFailed'): + if isinstance(event, bb.build.TaskFailed): return_value = 1 - logfile = event[1]['logfile'] + logfile = event.logfile if logfile: print "ERROR: Logfile of failure stored in %s." % logfile if 1 or includelogs: @@ -97,12 +97,12 @@ def init(server, eventHandler): if lines: for line in lines: print line - if event[0].startswith('bb.build.Task'): - print "NOTE: %s" % event[1]['_message'] + if isinstance(event, bb.build.TaskBase): + print "NOTE: %s" % event._message continue - if event[0].startswith('bb.event.ParseProgress'): - x = event[1]['sofar'] - y = event[1]['total'] + if isinstance(event, bb.event.ParseProgress): + x = event.sofar + y = event.total if os.isatty(sys.stdout.fileno()): sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) ) sys.stdout.flush() @@ -115,35 +115,35 @@ def init(server, eventHandler): sys.stdout.flush() if x == y: print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors." - % ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'], event[1]['errors'])) + % ( event.cached, event.parsed, event.skipped, event.masked, event.errors)) continue - if event[0] == 'bb.command.CookerCommandCompleted': + if isinstance(event, bb.command.CookerCommandCompleted): break - if event[0] == 'bb.command.CookerCommandSetExitCode': - return_value = event[1]['exitcode'] + if isinstance(event, bb.command.CookerCommandSetExitCode): + return_value = event.exitcode continue - if event[0] == 'bb.command.CookerCommandFailed': + if isinstance(event, bb.command.CookerCommandFailed): return_value = 1 - print "Command execution failed: %s" % event[1]['error'] + print "Command execution failed: %s" % event.error break - if event[0] == 'bb.cooker.CookerExit': + if isinstance(event, bb.cooker.CookerExit): break # ignore - if event[0].startswith('bb.event.BuildStarted'): + if isinstance(event, bb.event.BuildStarted): continue - if event[0].startswith('bb.event.BuildCompleted'): + if isinstance(event, bb.event.BuildCompleted): continue - if event[0].startswith('bb.event.MultipleProviders'): + if isinstance(event, bb.event.MultipleProviders): continue - if event[0].startswith('bb.runqueue.runQueue'): + if isinstance(event, bb.runqueue.runQueueEvent): continue - if event[0].startswith('bb.event.StampUpdate'): + if isinstance(event, bb.event.StampUpdate): continue - if event[0].startswith('bb.event.ConfigParsed'): + if isinstance(event, bb.event.ConfigParsed): continue - if event[0].startswith('bb.event.RecipeParsed'): + if isinstance(event, bb.event.RecipeParsed): continue print "Unknown Event: %s" % event diff --git a/bitbake-dev/lib/bb/ui/ncurses.py b/bitbake-dev/lib/bb/ui/ncurses.py index 2cd7e8e6e7..14310dc124 100644 --- a/bitbake-dev/lib/bb/ui/ncurses.py +++ b/bitbake-dev/lib/bb/ui/ncurses.py @@ -246,29 +246,29 @@ class NCursesUI: continue helper.eventHandler(event) #mw.appendText("%s\n" % event[0]) - if event[0].startswith('bb.build.Task'): - mw.appendText("NOTE: %s\n" % event[1]['_message']) - if event[0].startswith('bb.msg.MsgDebug'): - mw.appendText('DEBUG: ' + event[1]['_message'] + '\n') - if event[0].startswith('bb.msg.MsgNote'): - mw.appendText('NOTE: ' + event[1]['_message'] + '\n') - if event[0].startswith('bb.msg.MsgWarn'): - mw.appendText('WARNING: ' + event[1]['_message'] + '\n') - if event[0].startswith('bb.msg.MsgError'): - mw.appendText('ERROR: ' + event[1]['_message'] + '\n') - if event[0].startswith('bb.msg.MsgFatal'): - mw.appendText('FATAL: ' + event[1]['_message'] + '\n') - if event[0].startswith('bb.event.ParseProgress'): - x = event[1]['sofar'] - y = event[1]['total'] + if isinstance(event, bb.build.Task): + mw.appendText("NOTE: %s\n" % event._message) + if isinstance(event, bb.msg.MsgDebug): + mw.appendText('DEBUG: ' + event._message + '\n') + if isinstance(event, bb.msg.MsgNote): + mw.appendText('NOTE: ' + event._message + '\n') + if isinstance(event, bb.msg.MsgWarn): + mw.appendText('WARNING: ' + event._message + '\n') + if isinstance(event, bb.msg.MsgError): + mw.appendText('ERROR: ' + event._message + '\n') + if isinstance(event, bb.msg.MsgFatal): + mw.appendText('FATAL: ' + event._message + '\n') + if isinstance(event, bb.event.ParseProgress): + x = event.sofar + y = event.total if x == y: mw.setStatus("Idle") mw.appendText("Parsing finished. %d cached, %d parsed, %d skipped, %d masked." - % ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'] )) + % ( event.cached, event.parsed, event.skipped, event.masked )) else: mw.setStatus("Parsing: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) ) -# if event[0].startswith('bb.build.TaskFailed'): -# if event[1]['logfile']: +# if isinstance(event, bb.build.TaskFailed): +# if event.logfile: # if data.getVar("BBINCLUDELOGS", d): # bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile) # number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d) @@ -286,13 +286,13 @@ class NCursesUI: # else: # bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile) - if event[0] == 'bb.command.CookerCommandCompleted': + if isinstance(event, bb.command.CookerCommandCompleted): exitflag = True - if event[0] == 'bb.command.CookerCommandFailed': - mw.appendText("Command execution failed: %s" % event[1]['error']) + if isinstance(event, bb.command.CookerCommandFailed): + mw.appendText("Command execution failed: %s" % event.error) time.sleep(2) exitflag = True - if event[0] == 'bb.cooker.CookerExit': + if isinstance(event, bb.cooker.CookerExit): exitflag = True if helper.needUpdate: diff --git a/bitbake-dev/lib/bb/ui/uievent.py b/bitbake-dev/lib/bb/ui/uievent.py index 23fdd0f961..36302f4da7 100644 --- a/bitbake-dev/lib/bb/ui/uievent.py +++ b/bitbake-dev/lib/bb/ui/uievent.py @@ -24,7 +24,7 @@ server and queue them for the UI to process. This process must be used to avoid client/server deadlocks. """ -import socket, threading +import socket, threading, pickle from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler class BBUIEventQueue: @@ -37,8 +37,8 @@ class BBUIEventQueue: self.BBServer = BBServer self.t = threading.Thread() - self.t.setDaemon(True) - self.t.run = self.startCallbackHandler + self.t.setDaemon(True)
+ self.t.run = self.startCallbackHandler
self.t.start() def getEvent(self): @@ -55,7 +55,6 @@ class BBUIEventQueue: self.eventQueueNotify.clear() self.eventQueueLock.release() - return item def waitEvent(self, delay): @@ -63,16 +62,15 @@ class BBUIEventQueue: return self.getEvent() def queue_event(self, event): - self.eventQueueLock.acquire() - self.eventQueue.append(event) + self.eventQueue.append(pickle.loads(event)) self.eventQueueNotify.set() self.eventQueueLock.release() def startCallbackHandler(self): server = UIXMLRPCServer() - self.host, self.port = server.socket.getsockname() + self.host, self.port = server.socket.getsockname()
server.register_function( self.system_quit, "event.quit" ) server.register_function( self.queue_event, "event.send" ) @@ -85,7 +83,7 @@ class BBUIEventQueue: server.handle_request() server.server_close() - def system_quit( self ): + def system_quit( self ):
""" Shut down the callback thread """ @@ -97,11 +95,11 @@ class BBUIEventQueue: class UIXMLRPCServer (SimpleXMLRPCServer): - def __init__( self, interface = ("localhost", 0) ): + def __init__( self, interface = ("localhost", 0) ):
self.quit = False - SimpleXMLRPCServer.__init__( self, - interface, - requestHandler=SimpleXMLRPCRequestHandler, + SimpleXMLRPCServer.__init__( self,
+ interface,
+ requestHandler=SimpleXMLRPCRequestHandler,
logRequests=False, allow_none=True) def get_request(self): @@ -123,5 +121,5 @@ class UIXMLRPCServer (SimpleXMLRPCServer): if request is None: return SimpleXMLRPCServer.process_request(self, request, client_address) - +
diff --git a/bitbake-dev/lib/bb/ui/uihelper.py b/bitbake-dev/lib/bb/ui/uihelper.py index 246844c9d2..151ffc5854 100644 --- a/bitbake-dev/lib/bb/ui/uihelper.py +++ b/bitbake-dev/lib/bb/ui/uihelper.py @@ -24,25 +24,25 @@ class BBUIHelper: self.failed_tasks = {} def eventHandler(self, event): - if event[0].startswith('bb.build.TaskStarted'): - self.running_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] = "" + if isinstance(event, bb.build.TaskStarted): + self.running_tasks["%s %s\n" % (event._package, event._task)] = "" self.needUpdate = True - if event[0].startswith('bb.build.TaskSucceeded'): - del self.running_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] + if isinstance(event, bb.build.TaskSucceeded): + del self.running_tasks["%s %s\n" % (event._package, event._task)] self.needUpdate = True - if event[0].startswith('bb.build.TaskFailed'): - del self.running_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] - self.failed_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] = "" + if isinstance(event, bb.build.TaskFailed): + del self.running_tasks["%s %s\n" % (event._package, event._task)] + self.failed_tasks["%s %s\n" % (event._package, event._task)] = "" self.needUpdate = True # Add runqueue event handling - #if event[0].startswith('bb.runqueue.runQueueTaskCompleted'): + #if isinstance(event, bb.runqueue.runQueueTaskCompleted): # a = 1 - #if event[0].startswith('bb.runqueue.runQueueTaskStarted'): + #if isinstance(event, bb.runqueue.runQueueTaskStarted): # a = 1 - #if event[0].startswith('bb.runqueue.runQueueTaskFailed'): + #if isinstance(event, bb.runqueue.runQueueTaskFailed): # a = 1 - #if event[0].startswith('bb.runqueue.runQueueExitWait'): + #if isinstance(event, bb.runqueue.runQueueExitWait): # a = 1 def getTasks(self): |