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 <[email protected]> --- 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. -- _______________________________________________ toaster mailing list [email protected] https://lists.yoctoproject.org/listinfo/toaster
