mirror of
https://git.yoctoproject.org/poky
synced 2026-06-03 21:52:38 +02:00
We need to use the buildTargets command to ensure dependencies, such as native tools to build the rootfs, are correctly included. This patch achieves this by modifying BBPATH and BBFILES to include matches for the location of the generated recipe file and reparsing the metadata before calling buildTargets. Fixes [YOCTO #1228] (Bitbake rev: 5840d59098141e773c12bea8ed8d9f4f1a706132) Signed-off-by: Joshua Lock <josh@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
324 lines
13 KiB
Python
324 lines
13 KiB
Python
#
|
|
# BitBake Graphical GTK User Interface
|
|
#
|
|
# Copyright (C) 2011 Intel Corporation
|
|
#
|
|
# Authored by Joshua Lock <josh@linux.intel.com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License version 2 as
|
|
# published by the Free Software Foundation.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along
|
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
import gobject
|
|
|
|
progress_total = 0
|
|
|
|
class HobHandler(gobject.GObject):
|
|
|
|
"""
|
|
This object does BitBake event handling for the hob gui.
|
|
"""
|
|
__gsignals__ = {
|
|
"machines-updated" : (gobject.SIGNAL_RUN_LAST,
|
|
gobject.TYPE_NONE,
|
|
(gobject.TYPE_PYOBJECT,)),
|
|
"sdk-machines-updated": (gobject.SIGNAL_RUN_LAST,
|
|
gobject.TYPE_NONE,
|
|
(gobject.TYPE_PYOBJECT,)),
|
|
"distros-updated" : (gobject.SIGNAL_RUN_LAST,
|
|
gobject.TYPE_NONE,
|
|
(gobject.TYPE_PYOBJECT,)),
|
|
"package-formats-found" : (gobject.SIGNAL_RUN_LAST,
|
|
gobject.TYPE_NONE,
|
|
(gobject.TYPE_PYOBJECT,)),
|
|
"config-found" : (gobject.SIGNAL_RUN_LAST,
|
|
gobject.TYPE_NONE,
|
|
(gobject.TYPE_STRING,)),
|
|
"generating-data" : (gobject.SIGNAL_RUN_LAST,
|
|
gobject.TYPE_NONE,
|
|
()),
|
|
"data-generated" : (gobject.SIGNAL_RUN_LAST,
|
|
gobject.TYPE_NONE,
|
|
()),
|
|
"error" : (gobject.SIGNAL_RUN_LAST,
|
|
gobject.TYPE_NONE,
|
|
(gobject.TYPE_STRING,)),
|
|
"reload-triggered" : (gobject.SIGNAL_RUN_LAST,
|
|
gobject.TYPE_NONE,
|
|
(gobject.TYPE_STRING,
|
|
gobject.TYPE_STRING)),
|
|
}
|
|
|
|
(CFG_PATH_LOCAL, CFG_PATH_HOB, CFG_PATH_LAYERS, CFG_FILES_DISTRO, CFG_FILES_MACH, CFG_FILES_SDK, FILES_MATCH_CLASS, GENERATE_TGTS, REPARSE_FILES, BUILD_IMAGE) = range(10)
|
|
|
|
def __init__(self, taskmodel, server):
|
|
gobject.GObject.__init__(self)
|
|
|
|
self.current_command = None
|
|
self.building = None
|
|
self.gplv3_excluded = False
|
|
self.build_toolchain = False
|
|
self.build_toolchain_headers = False
|
|
self.generating = False
|
|
self.build_queue = []
|
|
|
|
self.model = taskmodel
|
|
self.server = server
|
|
|
|
self.image_output_types = self.server.runCommand(["getVariable", "IMAGE_FSTYPES"]).split(" ")
|
|
|
|
def run_next_command(self):
|
|
if self.current_command and not self.generating:
|
|
self.emit("generating-data")
|
|
self.generating = True
|
|
|
|
if self.current_command == self.CFG_PATH_LOCAL:
|
|
self.current_command = self.CFG_PATH_HOB
|
|
self.server.runCommand(["findConfigFilePath", "hob.local.conf"])
|
|
elif self.current_command == self.CFG_PATH_HOB:
|
|
self.current_command = self.CFG_PATH_LAYERS
|
|
self.server.runCommand(["findConfigFilePath", "bblayers.conf"])
|
|
elif self.current_command == self.CFG_PATH_LAYERS:
|
|
self.current_command = self.CFG_FILES_DISTRO
|
|
self.server.runCommand(["findConfigFiles", "DISTRO"])
|
|
elif self.current_command == self.CFG_FILES_DISTRO:
|
|
self.current_command = self.CFG_FILES_MACH
|
|
self.server.runCommand(["findConfigFiles", "MACHINE"])
|
|
elif self.current_command == self.CFG_FILES_MACH:
|
|
self.current_command = self.CFG_FILES_SDK
|
|
self.server.runCommand(["findConfigFiles", "MACHINE-SDK"])
|
|
elif self.current_command == self.CFG_FILES_SDK:
|
|
self.current_command = self.FILES_MATCH_CLASS
|
|
self.server.runCommand(["findFilesMatchingInDir", "rootfs_", "classes"])
|
|
elif self.current_command == self.FILES_MATCH_CLASS:
|
|
self.current_command = self.GENERATE_TGTS
|
|
self.server.runCommand(["generateTargetsTree", "classes/image.bbclass"])
|
|
elif self.current_command == self.GENERATE_TGTS:
|
|
if self.generating:
|
|
self.emit("data-generated")
|
|
self.generating = False
|
|
self.current_command = None
|
|
elif self.current_command == self.REPARSE_FILES:
|
|
if self.build_queue:
|
|
self.current_command = self.BUILD_IMAGE
|
|
else:
|
|
self.current_command = self.CFG_PATH_LAYERS
|
|
self.server.runCommand(["reparseFiles"])
|
|
elif self.current_command == self.BUILD_IMAGE:
|
|
self.building = "image"
|
|
if self.generating:
|
|
self.emit("data-generated")
|
|
self.generating = False
|
|
bbpath = self.server.runCommand(["getVariable", "BBPATH"])
|
|
bbfiles = self.server.runCommand(["getVariable", "BBFILES"])
|
|
self.server.runCommand(["buildTargets", self.build_queue, "build"])
|
|
self.build_queue = []
|
|
self.current_command = None
|
|
|
|
def handle_event(self, event, running_build, pbar):
|
|
if not event:
|
|
return
|
|
|
|
# If we're running a build, use the RunningBuild event handler
|
|
if self.building:
|
|
running_build.handle_event(event)
|
|
elif isinstance(event, bb.event.TargetsTreeGenerated):
|
|
if event._model:
|
|
self.model.populate(event._model)
|
|
elif isinstance(event, bb.event.ConfigFilesFound):
|
|
var = event._variable
|
|
if var == "distro":
|
|
distros = event._values
|
|
distros.sort()
|
|
self.emit("distros-updated", distros)
|
|
elif var == "machine":
|
|
machines = event._values
|
|
machines.sort()
|
|
self.emit("machines-updated", machines)
|
|
elif var == "machine-sdk":
|
|
sdk_machines = event._values
|
|
sdk_machines.sort()
|
|
self.emit("sdk-machines-updated", sdk_machines)
|
|
elif isinstance(event, bb.event.ConfigFilePathFound):
|
|
path = event._path
|
|
self.emit("config-found", path)
|
|
elif isinstance(event, bb.event.FilesMatchingFound):
|
|
# FIXME: hard coding, should at least be a variable shared between
|
|
# here and the caller
|
|
if event._pattern == "rootfs_":
|
|
formats = []
|
|
for match in event._matches:
|
|
classname, sep, cls = match.rpartition(".")
|
|
fs, sep, format = classname.rpartition("_")
|
|
formats.append(format)
|
|
formats.sort()
|
|
self.emit("package-formats-found", formats)
|
|
elif isinstance(event, bb.command.CommandCompleted):
|
|
self.run_next_command()
|
|
elif isinstance(event, bb.command.CommandFailed):
|
|
self.emit("error", event.error)
|
|
elif isinstance(event, bb.event.CacheLoadStarted):
|
|
bb.ui.crumbs.hobeventhandler.progress_total = event.total
|
|
pbar.set_text("Loading cache: %s/%s" % (0, bb.ui.crumbs.hobeventhandler.progress_total))
|
|
elif isinstance(event, bb.event.CacheLoadProgress):
|
|
pbar.set_text("Loading cache: %s/%s" % (event.current, bb.ui.crumbs.hobeventhandler.progress_total))
|
|
elif isinstance(event, bb.event.CacheLoadCompleted):
|
|
pbar.set_text("Loading cache: %s/%s" % (bb.ui.crumbs.hobeventhandler.progress_total, bb.ui.crumbs.hobeventhandler.progress_total))
|
|
elif isinstance(event, bb.event.ParseStarted):
|
|
if event.total == 0:
|
|
return
|
|
bb.ui.crumbs.hobeventhandler.progress_total = event.total
|
|
pbar.set_text("Processing recipes: %s/%s" % (0, bb.ui.crumbs.hobeventhandler.progress_total))
|
|
elif isinstance(event, bb.event.ParseProgress):
|
|
pbar.set_text("Processing recipes: %s/%s" % (event.current, bb.ui.crumbs.hobeventhandler.progress_total))
|
|
elif isinstance(event, bb.event.ParseCompleted):
|
|
pbar.set_fraction(1.0)
|
|
return
|
|
|
|
def event_handle_idle_func (self, eventHandler, running_build, pbar):
|
|
# Consume as many messages as we can in the time available to us
|
|
event = eventHandler.getEvent()
|
|
while event:
|
|
self.handle_event(event, running_build, pbar)
|
|
event = eventHandler.getEvent()
|
|
return True
|
|
|
|
def set_machine(self, machine):
|
|
self.server.runCommand(["setVariable", "MACHINE", machine])
|
|
|
|
def set_sdk_machine(self, sdk_machine):
|
|
self.server.runCommand(["setVariable", "SDKMACHINE", sdk_machine])
|
|
|
|
def set_distro(self, distro):
|
|
self.server.runCommand(["setVariable", "DISTRO", distro])
|
|
|
|
def set_package_format(self, format):
|
|
self.server.runCommand(["setVariable", "PACKAGE_CLASSES", "package_%s" % format])
|
|
|
|
def reload_data(self, config=None):
|
|
img = self.model.selected_image
|
|
selected_packages, _ = self.model.get_selected_packages()
|
|
self.emit("reload-triggered", img, " ".join(selected_packages))
|
|
self.current_command = self.REPARSE_FILES
|
|
self.run_next_command()
|
|
|
|
def set_bbthreads(self, threads):
|
|
self.server.runCommand(["setVariable", "BB_NUMBER_THREADS", threads])
|
|
|
|
def set_pmake(self, threads):
|
|
pmake = "-j %s" % threads
|
|
self.server.runCommand(["setVariable", "BB_NUMBER_THREADS", pmake])
|
|
|
|
def build_image(self, image, image_path, configurator):
|
|
targets = []
|
|
targets.append(image)
|
|
if self.build_toolchain and self.build_toolchain_headers:
|
|
targets.append("meta-toolchain-sdk")
|
|
elif self.build_toolchain:
|
|
targets.append("meta-toolchain")
|
|
self.build_queue = targets
|
|
|
|
bbpath_ok = False
|
|
bbpath = self.server.runCommand(["getVariable", "BBPATH"])
|
|
if image_path in bbpath.split(":"):
|
|
bbpath_ok = True
|
|
|
|
bbfiles_ok = False
|
|
bbfiles = self.server.runCommand(["getVariable", "BBFILES"]).split(" ")
|
|
for files in bbfiles:
|
|
import re
|
|
pattern = "%s/\*.bb" % image_path
|
|
if re.match(pattern, files):
|
|
bbfiles_ok = True
|
|
|
|
if not bbpath_ok:
|
|
nbbp = image_path
|
|
else:
|
|
nbbp = None
|
|
|
|
if not bbfiles_ok:
|
|
nbbf = "%s/*.bb" % image_path
|
|
else:
|
|
nbbf = None
|
|
|
|
if not bbfiles_ok or not bbpath_ok:
|
|
configurator.insertTempBBPath(nbbp, nbbf)
|
|
|
|
self.current_command = self.REPARSE_FILES
|
|
self.run_next_command()
|
|
|
|
def build_packages(self, pkgs):
|
|
self.building = "packages"
|
|
self.server.runCommand(["buildTargets", pkgs, "build"])
|
|
|
|
def cancel_build(self, force=False):
|
|
if force:
|
|
# Force the cooker to stop as quickly as possible
|
|
self.server.runCommand(["stateStop"])
|
|
else:
|
|
# Wait for tasks to complete before shutting down, this helps
|
|
# leave the workdir in a usable state
|
|
self.server.runCommand(["stateShutdown"])
|
|
|
|
def toggle_gplv3(self, excluded):
|
|
if self.gplv3_excluded != excluded:
|
|
self.gplv3_excluded = excluded
|
|
if excluded:
|
|
self.server.runCommand(["setVariable", "INCOMPATIBLE_LICENSE", "GPLv3"])
|
|
else:
|
|
self.server.runCommand(["setVariable", "INCOMPATIBLE_LICENSE", ""])
|
|
|
|
def toggle_toolchain(self, enabled):
|
|
if self.build_toolchain != enabled:
|
|
self.build_toolchain = enabled
|
|
|
|
def toggle_toolchain_headers(self, enabled):
|
|
if self.build_toolchain_headers != enabled:
|
|
self.build_toolchain_headers = enabled
|
|
|
|
def queue_image_recipe_path(self, path):
|
|
self.build_queue.append(path)
|
|
|
|
def build_complete_cb(self, running_build):
|
|
if len(self.build_queue) > 0:
|
|
next = self.build_queue.pop(0)
|
|
if next.endswith('.bb'):
|
|
self.build_file(next)
|
|
self.building = 'image'
|
|
self.build_file(next)
|
|
else:
|
|
self.build_packages(next.split(" "))
|
|
else:
|
|
self.building = None
|
|
self.emit("build-complete")
|
|
|
|
def set_fstypes(self, fstypes):
|
|
self.server.runCommand(["setVariable", "IMAGE_FSTYPES", fstypes])
|
|
|
|
def add_image_output_type(self, output_type):
|
|
if output_type not in self.image_output_types:
|
|
self.image_output_types.append(output_type)
|
|
fstypes = " ".join(self.image_output_types)
|
|
self.set_fstypes(fstypes)
|
|
return fstypes
|
|
|
|
def remove_image_output_type(self, output_type):
|
|
if output_type in self.image_output_types:
|
|
ind = self.image_output_types.index(output_type)
|
|
self.image_output_types.pop(ind)
|
|
fstypes = " ".join(self.image_output_types)
|
|
self.set_fstypes(fstypes)
|
|
return fstypes
|
|
|
|
def get_image_deploy_dir(self):
|
|
return self.server.runCommand(["getVariable", "DEPLOY_DIR_IMAGE"])
|