[Toaster] [review-request][PATCH 3/3] toaster: create Build object earlier in bitbake processing
Elliot Smith
elliot.smith at intel.com
Mon Feb 1 06:30:42 PST 2016
If a build fails because of a bitbake error occurring before the
BuildStarted event fires, we do not generate a Build object
for command-line builds. This means that failed command-line builds
don't appear in Toaster at all.
Listen for the CommandExecution event for the buildTargets() command
as it is passed to the cooker. At this point, all the information
needed for a skeletal build (including targets) is available in the
event or on the bitbake server, regardless of whether the build
succeeds or not.
Note that although this occurs after ParseStarted, which is when we
previously created our build object, the CommandExecution event
for buildTargets() is the first time when build targets can be
accessed. A build object could be created earlier (on ParseStarted),
but we would not be able to associate any targets with it.
[YOCTO #8440]
Signed-off-by: Elliot Smith <elliot.smith at intel.com>
---
bitbake/lib/bb/ui/buildinfohelper.py | 49 +++++++++++++++++++++++++-----------
bitbake/lib/bb/ui/toasterui.py | 25 +++++++++---------
2 files changed, 47 insertions(+), 27 deletions(-)
diff --git a/bitbake/lib/bb/ui/buildinfohelper.py b/bitbake/lib/bb/ui/buildinfohelper.py
index 1533f17..6307861 100644
--- a/bitbake/lib/bb/ui/buildinfohelper.py
+++ b/bitbake/lib/bb/ui/buildinfohelper.py
@@ -127,7 +127,7 @@ class ORMWrapper(object):
# pylint: disable=bad-continuation
# we do not follow the python conventions for continuation indentation due to long lines here
- def create_build_object(self, build_info, brbe, project_id):
+ def create_build_object(self, build_info, brbe, project_id = None):
assert 'machine' in build_info
assert 'distro' in build_info
assert 'distro_version' in build_info
@@ -883,18 +883,44 @@ class BuildInfoHelper(object):
except NotExisting as nee:
logger.warn("buildinfohelper: cannot identify layer exception:%s ", nee)
+ def store_new_build(self, event, build_log_path):
+ """
+ create a skeletal build object (or retrieve an existing one) as soon as
+ bitbake starts trying to do the build; this uses the earliest event
+ which occurs for all failed/successful builds and which only occurs once
+ during a build
- def store_started_build(self, event, build_log_path):
- assert '_pkgs' in vars(event)
- build_information = self._get_build_information(build_log_path)
+ event: a CommandPrepared event; the first element in the commandline
+ list is a list of targets for the build
+ """
+ if event.command != 'buildTargets':
+ return
- # Update brbe and project as they can be changed for every build
+ # create the build
+ build_information = self._get_build_information(build_log_path)
self.brbe = build_information['brbe']
- self.project = build_information['project']
+ self.internal_state['build'] = self.orm_wrapper.create_build_object(build_information, self.brbe)
- build_obj = self.orm_wrapper.create_build_object(build_information, self.brbe, self.project)
+ # get the targets passed to the buildTargets command
+ action = event.commandline[1]
+ targets = map(lambda target: target + ':do_' + action, event.commandline[0])
- self.internal_state['build'] = build_obj
+ # create target information
+ target_information = {}
+ target_information['targets'] = targets
+ target_information['build'] = self.internal_state['build']
+
+ self.internal_state['targets'] = self.orm_wrapper.get_or_create_targets(target_information)
+
+ def update_build(self, event):
+ """
+ update the current build with layer and config data once it
+ actually starts
+
+ event: a BuildStarted event
+ """
+
+ build_obj = self.internal_state['build']
# save layer version information for this build
if not 'lvs' in self.internal_state:
@@ -905,13 +931,6 @@ class BuildInfoHelper(object):
del self.internal_state['lvs']
- # create target information
- target_information = {}
- target_information['targets'] = event._pkgs
- target_information['build'] = build_obj
-
- self.internal_state['targets'] = self.orm_wrapper.get_or_create_targets(target_information)
-
# Save build configuration
data = self.server.runCommand(["getAllKeysWithFlags", ["doc", "func"]])[0]
diff --git a/bitbake/lib/bb/ui/toasterui.py b/bitbake/lib/bb/ui/toasterui.py
index 32b1889..cef2e30 100644
--- a/bitbake/lib/bb/ui/toasterui.py
+++ b/bitbake/lib/bb/ui/toasterui.py
@@ -93,14 +93,14 @@ def _close_build_log(build_log):
logger.removeHandler(build_log)
_evt_list = [ "bb.runqueue.runQueueExitWait", "bb.event.LogExecTTY", "logging.LogRecord",
- "bb.build.TaskFailed", "bb.build.TaskBase", "bb.event.ParseStarted",
+ "bb.build.TaskFailed", "bb.build.TaskBase",
"bb.event.ParseProgress", "bb.event.ParseCompleted", "bb.event.CacheLoadStarted",
"bb.event.CacheLoadProgress", "bb.event.CacheLoadCompleted", "bb.command.CommandFailed",
"bb.command.CommandExit", "bb.command.CommandCompleted", "bb.cooker.CookerExit",
"bb.event.MultipleProviders", "bb.event.NoProvider", "bb.runqueue.sceneQueueTaskStarted",
"bb.runqueue.runQueueTaskStarted", "bb.runqueue.runQueueTaskFailed", "bb.runqueue.sceneQueueTaskFailed",
"bb.event.BuildBase", "bb.build.TaskStarted", "bb.build.TaskSucceeded", "bb.build.TaskFailedSilent",
- "bb.event.MetadataEvent"]
+ "bb.event.MetadataEvent", "bb.command.CommandExecution"]
def main(server, eventHandler, params):
# set to a logging.FileHandler instance when a build starts;
@@ -186,19 +186,20 @@ def main(server, eventHandler, params):
# pylint: disable=protected-access
# the code will look into the protected variables of the event; no easy way around this
- # we treat ParseStarted as the first event of toaster-triggered
- # builds; that way we get the Build Configuration included in the log
- # and any errors that occur before BuildStarted is fired
- if isinstance(event, bb.event.ParseStarted):
- if not (build_log and build_log_file_path):
- build_log, build_log_file_path = _open_build_log(log_dir)
+ # we treat the buildTargets command to cooker as the first "event"
+ # of the build; any earlier than this, and we have no way of
+ # knowing which targets are being built
+ if isinstance(event, bb.command.CommandExecution):
+ if event.command == 'buildTargets':
+ if not (build_log and build_log_file_path):
+ build_log, build_log_file_path = _open_build_log(log_dir)
+ buildinfohelper.store_new_build(event, build_log_file_path)
continue
+ # when the build proper starts, we extract information about
+ # any layers and config data
if isinstance(event, bb.event.BuildStarted):
- if not (build_log and build_log_file_path):
- build_log, build_log_file_path = _open_build_log(log_dir)
-
- buildinfohelper.store_started_build(event, build_log_file_path)
+ buildinfohelper.update_build(event)
if isinstance(event, (bb.build.TaskStarted, bb.build.TaskSucceeded, bb.build.TaskFailedSilent)):
buildinfohelper.update_and_store_task(event)
--
Elliot Smith
Software Engineer
Intel OTC
---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
More information about the toaster
mailing list