3 # BitBake Graphical GTK User Interface
5 # Copyright (C) 2011-2012 Intel Corporation
7 # Authored by Joshua Lock <josh@linux.intel.com>
8 # Authored by Dongxiao Xu <dongxiao.xu@intel.com>
9 # Authored by Shane Wang <shane.wang@intel.com>
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License version 2 as
13 # published by the Free Software Foundation.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License along
21 # with this program; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 from bb.ui.crumbs.template import TemplateMgr
34 from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
35 from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
36 from bb.ui.crumbs.packageselectionpage import PackageSelectionPage
37 from bb.ui.crumbs.builddetailspage import BuildDetailsPage
38 from bb.ui.crumbs.imagedetailspage import ImageDetailsPage
39 from bb.ui.crumbs.hobwidget import hwc, HobButton, HobAltButton
40 from bb.ui.crumbs.hig import CrumbsMessageDialog, ImageSelectionDialog, \
41 AdvancedSettingDialog, SimpleSettingsDialog, \
42 LayerSelectionDialog, DeployImageDialog
43 from bb.ui.crumbs.persistenttooltip import PersistentTooltip
44 import bb.ui.crumbs.utils
49 '''Represents the data structure of configuration.'''
52 def parse_proxy_string(cls, proxy):
53 pattern = "^\s*((http|https|ftp|git|cvs)://)?((\S+):(\S+)@)?(\S+):(\d+)/?"
54 match = re.search(pattern, proxy)
56 return match.group(2), match.group(4), match.group(5), match.group(6), match.group(7)
58 return None, None, None, "", ""
61 def make_host_string(cls, prot, user, passwd, host, default_prot=""):
62 if host == None or host == "":
67 if user != None and user != "":
68 if prot == None or prot == "":
70 return prot + "://" + user + ":" + passwd + "@" + host
72 if prot == None or prot == "":
75 return prot + "://" + host
78 def make_port_string(cls, port):
83 def make_proxy_string(cls, prot, user, passwd, host, port, default_prot=""):
84 if host == None or host == "" or port == None or port == "":
87 return Configuration.make_host_string(prot, user, passwd, host, default_prot) + ":" + Configuration.make_port_string(port)
93 self.dldir = self.sstatedir = self.sstatemirror = ""
94 self.pmake = self.bbthread = 0
95 self.curr_package_format = ""
96 self.image_rootfs_size = self.image_extra_size = 0
97 self.image_overhead_factor = 1
98 self.incompat_license = ""
99 self.curr_sdk_machine = ""
100 self.conf_version = self.lconf_version = ""
101 self.extra_setting = {}
102 self.toolchain_build = False
103 self.image_fstypes = ""
106 # image/recipes/packages
107 self.clear_selection()
109 self.user_selected_packages = []
111 self.default_task = "build"
114 self.enable_proxy = None
115 self.same_proxy = False
117 "http" : [None, None, None, "", ""], # protocol : [prot, user, passwd, host, port]
118 "https" : [None, None, None, "", ""],
119 "ftp" : [None, None, None, "", ""],
120 "git" : [None, None, None, "", ""],
121 "cvs" : [None, None, None, "", ""],
124 def clear_selection(self):
125 self.selected_image = None
126 self.selected_recipes = []
127 self.selected_packages = []
128 self.initial_selected_packages = []
130 def split_proxy(self, protocol, proxy):
132 prot, user, passwd, host, port = Configuration.parse_proxy_string(proxy)
138 self.proxies[protocol] = entry
140 def combine_proxy(self, protocol):
141 entry = self.proxies[protocol]
142 return Configuration.make_proxy_string(entry[0], entry[1], entry[2], entry[3], entry[4], protocol)
144 def combine_host_only(self, protocol):
145 entry = self.proxies[protocol]
146 return Configuration.make_host_string(entry[0], entry[1], entry[2], entry[3], protocol)
148 def combine_port_only(self, protocol):
149 entry = self.proxies[protocol]
150 return Configuration.make_port_string(entry[4])
152 def update(self, params):
154 self.curr_distro = params["distro"]
155 self.dldir = params["dldir"]
156 self.sstatedir = params["sstatedir"]
157 self.sstatemirror = params["sstatemirror"]
158 self.pmake = int(params["pmake"].split()[1])
159 self.bbthread = params["bbthread"]
160 self.curr_package_format = " ".join(params["pclass"].split("package_")).strip()
161 self.image_rootfs_size = params["image_rootfs_size"]
162 self.image_extra_size = params["image_extra_size"]
163 self.image_overhead_factor = params['image_overhead_factor']
164 self.incompat_license = params["incompat_license"]
165 self.curr_sdk_machine = params["sdk_machine"]
166 self.conf_version = params["conf_version"]
167 self.lconf_version = params["lconf_version"]
168 self.image_fstypes = params["image_fstypes"]
169 # self.extra_setting/self.toolchain_build
171 self.layers = params["layer"].split()
172 self.default_task = params["default_task"]
175 self.enable_proxy = params["http_proxy"] != "" or params["https_proxy"] != "" or params["ftp_proxy"] != "" \
176 or params["git_proxy_host"] != "" or params["git_proxy_port"] != "" \
177 or params["cvs_proxy_host"] != "" or params["cvs_proxy_port"] != ""
178 self.split_proxy("http", params["http_proxy"])
179 self.split_proxy("https", params["https_proxy"])
180 self.split_proxy("ftp", params["ftp_proxy"])
181 self.split_proxy("git", params["git_proxy_host"] + ":" + params["git_proxy_port"])
182 self.split_proxy("cvs", params["cvs_proxy_host"] + ":" + params["cvs_proxy_port"])
184 def load(self, template):
185 self.curr_mach = template.getVar("MACHINE")
186 self.curr_package_format = " ".join(template.getVar("PACKAGE_CLASSES").split("package_")).strip()
187 self.curr_distro = template.getVar("DISTRO")
188 self.dldir = template.getVar("DL_DIR")
189 self.sstatedir = template.getVar("SSTATE_DIR")
190 self.sstatemirror = template.getVar("SSTATE_MIRROR")
192 self.pmake = int(template.getVar("PARALLEL_MAKE").split()[1])
196 self.bbthread = int(template.getVar("BB_NUMBER_THREADS"))
200 self.image_rootfs_size = int(template.getVar("IMAGE_ROOTFS_SIZE"))
204 self.image_extra_size = int(template.getVar("IMAGE_EXTRA_SPACE"))
207 # image_overhead_factor is read-only.
208 self.incompat_license = template.getVar("INCOMPATIBLE_LICENSE")
209 self.curr_sdk_machine = template.getVar("SDKMACHINE")
210 self.conf_version = template.getVar("CONF_VERSION")
211 self.lconf_version = template.getVar("LCONF_VERSION")
212 self.extra_setting = eval(template.getVar("EXTRA_SETTING"))
213 self.toolchain_build = eval(template.getVar("TOOLCHAIN_BUILD"))
214 self.image_fstypes = template.getVar("IMAGE_FSTYPES")
216 self.layers = template.getVar("BBLAYERS").split()
217 # image/recipes/packages
218 self.selected_image = template.getVar("__SELECTED_IMAGE__")
219 self.selected_recipes = template.getVar("DEPENDS").split()
220 self.selected_packages = template.getVar("IMAGE_INSTALL").split()
222 self.enable_proxy = eval(template.getVar("enable_proxy"))
223 self.same_proxy = eval(template.getVar("use_same_proxy"))
224 self.split_proxy("http", template.getVar("http_proxy"))
225 self.split_proxy("https", template.getVar("https_proxy"))
226 self.split_proxy("ftp", template.getVar("ftp_proxy"))
227 self.split_proxy("git", template.getVar("GIT_PROXY_HOST") + ":" + template.getVar("GIT_PROXY_PORT"))
228 self.split_proxy("cvs", template.getVar("CVS_PROXY_HOST") + ":" + template.getVar("CVS_PROXY_PORT"))
230 def save(self, template, defaults=False):
231 template.setVar("VERSION", "%s" % hobVer)
233 template.setVar("BBLAYERS", " ".join(self.layers))
236 template.setVar("MACHINE", self.curr_mach)
237 template.setVar("DISTRO", self.curr_distro)
238 template.setVar("DL_DIR", self.dldir)
239 template.setVar("SSTATE_DIR", self.sstatedir)
240 template.setVar("SSTATE_MIRROR", self.sstatemirror)
241 template.setVar("PARALLEL_MAKE", "-j %s" % self.pmake)
242 template.setVar("BB_NUMBER_THREADS", self.bbthread)
243 template.setVar("PACKAGE_CLASSES", " ".join(["package_" + i for i in self.curr_package_format.split()]))
244 template.setVar("IMAGE_ROOTFS_SIZE", self.image_rootfs_size)
245 template.setVar("IMAGE_EXTRA_SPACE", self.image_extra_size)
246 template.setVar("INCOMPATIBLE_LICENSE", self.incompat_license)
247 template.setVar("SDKMACHINE", self.curr_sdk_machine)
248 template.setVar("CONF_VERSION", self.conf_version)
249 template.setVar("LCONF_VERSION", self.lconf_version)
250 template.setVar("EXTRA_SETTING", self.extra_setting)
251 template.setVar("TOOLCHAIN_BUILD", self.toolchain_build)
252 template.setVar("IMAGE_FSTYPES", self.image_fstypes)
254 # image/recipes/packages
255 template.setVar("__SELECTED_IMAGE__", self.selected_image)
256 template.setVar("DEPENDS", self.selected_recipes)
257 template.setVar("IMAGE_INSTALL", self.user_selected_packages)
259 template.setVar("enable_proxy", self.enable_proxy)
260 template.setVar("use_same_proxy", self.same_proxy)
261 template.setVar("http_proxy", self.combine_proxy("http"))
262 template.setVar("https_proxy", self.combine_proxy("https"))
263 template.setVar("ftp_proxy", self.combine_proxy("ftp"))
264 template.setVar("GIT_PROXY_HOST", self.combine_host_only("git"))
265 template.setVar("GIT_PROXY_PORT", self.combine_port_only("git"))
266 template.setVar("CVS_PROXY_HOST", self.combine_host_only("cvs"))
267 template.setVar("CVS_PROXY_PORT", self.combine_port_only("cvs"))
270 '''Represents other variables like available machines, etc.'''
274 self.max_threads = 65535
277 self.image_types = []
278 self.runnable_image_types = []
279 self.runnable_machine_patterns = []
280 self.deployable_image_types = []
283 self.all_machines = []
284 self.all_package_formats = []
285 self.all_distros = []
286 self.all_sdk_machines = []
288 self.image_names = []
289 self.image_white_pattern = ""
290 self.image_black_pattern = ""
292 # for build log to show
294 self.target_arch = ""
296 self.distro_version = ""
297 self.tune_pkgarch = ""
299 def update(self, params):
300 self.max_threads = params["max_threads"]
301 self.core_base = params["core_base"]
302 self.image_addr = params["image_addr"]
303 self.image_types = params["image_types"].split()
304 self.runnable_image_types = params["runnable_image_types"].split()
305 self.runnable_machine_patterns = params["runnable_machine_patterns"].split()
306 self.deployable_image_types = params["deployable_image_types"].split()
307 self.tmpdir = params["tmpdir"]
308 self.image_white_pattern = params["image_white_pattern"]
309 self.image_black_pattern = params["image_black_pattern"]
310 self.kernel_image_type = params["kernel_image_type"]
311 # for build log to show
312 self.bb_version = params["bb_version"]
313 self.target_arch = params["target_arch"]
314 self.target_os = params["target_os"]
315 self.distro_version = params["distro_version"]
316 self.tune_pkgarch = params["tune_pkgarch"]
318 def hob_conf_filter(fn, data):
319 if fn.endswith("/local.conf"):
320 distro = data.getVar("DISTRO_HOB")
322 if distro != "defaultsetup":
323 data.setVar("DISTRO", distro)
325 data.delVar("DISTRO")
327 keys = ["MACHINE_HOB", "SDKMACHINE_HOB", "PACKAGE_CLASSES_HOB", \
328 "BB_NUMBER_THREADS_HOB", "PARALLEL_MAKE_HOB", "DL_DIR_HOB", \
329 "SSTATE_DIR_HOB", "SSTATE_MIRROR_HOB", "INCOMPATIBLE_LICENSE_HOB"]
331 var_hob = data.getVar(key)
333 data.setVar(key.split("_HOB")[0], var_hob)
336 if fn.endswith("/bblayers.conf"):
337 layers = data.getVar("BBLAYERS_HOB")
339 data.setVar("BBLAYERS", layers)
342 class Builder(gtk.Window):
345 RCPPKGINFO_POPULATING,
346 RCPPKGINFO_POPULATED,
352 FAST_IMAGE_GENERATING,
357 END_NOOP) = range(14)
359 (IMAGE_CONFIGURATION,
367 MACHINE_SELECTION : IMAGE_CONFIGURATION,
368 RCPPKGINFO_POPULATING : IMAGE_CONFIGURATION,
369 RCPPKGINFO_POPULATED : IMAGE_CONFIGURATION,
370 BASEIMG_SELECTED : IMAGE_CONFIGURATION,
371 RECIPE_SELECTION : RECIPE_DETAILS,
372 PACKAGE_GENERATING : BUILD_DETAILS,
373 PACKAGE_GENERATED : PACKAGE_DETAILS,
374 PACKAGE_SELECTION : PACKAGE_DETAILS,
375 FAST_IMAGE_GENERATING : BUILD_DETAILS,
376 IMAGE_GENERATING : BUILD_DETAILS,
377 IMAGE_GENERATED : IMAGE_DETAILS,
378 MY_IMAGE_OPENED : IMAGE_DETAILS,
382 def __init__(self, hobHandler, recipe_model, package_model):
383 super(Builder, self).__init__()
385 self.hob_image = "hob-image"
386 self.hob_toolchain = "hob-toolchain"
389 self.handler = hobHandler
394 self.logger = logging.getLogger("BitBake")
395 self.consolelog = None
396 self.current_logfile = None
398 # configuration and parameters
399 self.configuration = Configuration()
400 self.parameters = Parameters()
403 self.current_step = None
404 self.previous_step = None
406 self.stopping = False
408 # recipe model and package model
409 self.recipe_model = recipe_model
410 self.package_model = package_model
412 # Indicate whether user has customized the image
413 self.customized = False
415 # Indicate whether the UI is working
416 self.sensitive = True
418 # create visual elements
419 self.create_visual_elements()
421 # connect the signals to functions
422 self.connect("delete-event", self.destroy_window_cb)
423 self.recipe_model.connect ("recipe-selection-changed", self.recipelist_changed_cb)
424 self.package_model.connect("package-selection-changed", self.packagelist_changed_cb)
425 self.handler.connect("config-updated", self.handler_config_updated_cb)
426 self.handler.connect("package-formats-updated", self.handler_package_formats_updated_cb)
427 self.handler.connect("parsing-started", self.handler_parsing_started_cb)
428 self.handler.connect("parsing", self.handler_parsing_cb)
429 self.handler.connect("parsing-completed", self.handler_parsing_completed_cb)
430 self.handler.build.connect("build-started", self.handler_build_started_cb)
431 self.handler.build.connect("build-succeeded", self.handler_build_succeeded_cb)
432 self.handler.build.connect("build-failed", self.handler_build_failed_cb)
433 self.handler.build.connect("build-aborted", self.handler_build_aborted_cb)
434 self.handler.build.connect("task-started", self.handler_task_started_cb)
435 self.handler.build.connect("log-error", self.handler_build_failure_cb)
436 self.handler.build.connect("log", self.handler_build_log_cb)
437 self.handler.build.connect("no-provider", self.handler_no_provider_cb)
438 self.handler.connect("generating-data", self.handler_generating_data_cb)
439 self.handler.connect("data-generated", self.handler_data_generated_cb)
440 self.handler.connect("command-succeeded", self.handler_command_succeeded_cb)
441 self.handler.connect("command-failed", self.handler_command_failed_cb)
442 self.handler.connect("sanity-failed", self.handler_sanity_failed_cb)
443 self.handler.connect("recipe-populated", self.handler_recipe_populated_cb)
444 self.handler.connect("package-populated", self.handler_package_populated_cb)
446 self.handler.set_config_filter(hob_conf_filter)
448 self.initiate_new_build_async()
450 def create_visual_elements(self):
451 self.set_title("Hob")
452 self.set_icon_name("applications-development")
453 self.set_resizable(True)
456 window_width = self.get_screen().get_width()
457 window_height = self.get_screen().get_height()
458 except AttributeError:
459 print "Please set DISPLAY variable before running Hob."
462 if window_width >= hwc.MAIN_WIN_WIDTH:
463 window_width = hwc.MAIN_WIN_WIDTH
464 window_height = hwc.MAIN_WIN_HEIGHT
465 self.set_size_request(window_width, window_height)
467 self.vbox = gtk.VBox(False, 0)
468 self.vbox.set_border_width(0)
472 self.image_configuration_page = ImageConfigurationPage(self)
473 self.recipe_details_page = RecipeSelectionPage(self)
474 self.build_details_page = BuildDetailsPage(self)
475 self.package_details_page = PackageSelectionPage(self)
476 self.image_details_page = ImageDetailsPage(self)
478 self.nb = gtk.Notebook()
479 self.nb.set_show_tabs(False)
480 self.nb.insert_page(self.image_configuration_page, None, self.IMAGE_CONFIGURATION)
481 self.nb.insert_page(self.recipe_details_page, None, self.RECIPE_DETAILS)
482 self.nb.insert_page(self.build_details_page, None, self.BUILD_DETAILS)
483 self.nb.insert_page(self.package_details_page, None, self.PACKAGE_DETAILS)
484 self.nb.insert_page(self.image_details_page, None, self.IMAGE_DETAILS)
485 self.vbox.pack_start(self.nb, expand=True, fill=True)
488 self.nb.set_current_page(0)
490 def initiate_new_build_async(self):
491 self.switch_page(self.MACHINE_SELECTION)
492 if self.load_template(TemplateMgr.convert_to_template_pathfilename("default", ".hob/")) == False:
493 self.handler.init_cooker()
494 self.handler.set_extra_inherit("image_types")
495 self.handler.generate_configuration()
497 def update_config_async(self):
498 self.switch_page(self.MACHINE_SELECTION)
499 self.set_user_config()
500 self.handler.generate_configuration()
502 def sanity_check(self):
503 self.handler.trigger_sanity_check()
505 def populate_recipe_package_info_async(self):
506 self.switch_page(self.RCPPKGINFO_POPULATING)
508 self.set_user_config()
509 self.handler.generate_recipes()
511 def generate_packages_async(self, log = False):
512 self.switch_page(self.PACKAGE_GENERATING)
514 self.current_logfile = self.handler.get_logfile()
515 self.do_log(self.current_logfile)
517 _, all_recipes = self.recipe_model.get_selected_recipes()
518 self.set_user_config()
519 self.handler.reset_build()
520 self.handler.generate_packages(all_recipes, self.configuration.default_task)
522 def restore_initial_selected_packages(self):
523 self.package_model.set_selected_packages(self.configuration.initial_selected_packages)
524 for package in self.configuration.selected_packages:
525 if package not in self.configuration.initial_selected_packages:
526 self.package_model.exclude_item(self.package_model.find_path_for_item(package))
528 def fast_generate_image_async(self, log = False):
529 self.switch_page(self.FAST_IMAGE_GENERATING)
531 self.current_logfile = self.handler.get_logfile()
532 self.do_log(self.current_logfile)
534 _, all_recipes = self.recipe_model.get_selected_recipes()
535 self.set_user_config()
536 self.handler.reset_build()
537 self.handler.generate_packages(all_recipes, self.configuration.default_task)
539 def generate_image_async(self, cont = False):
540 self.switch_page(self.IMAGE_GENERATING)
541 self.handler.reset_build()
543 self.current_logfile = self.handler.get_logfile()
544 self.do_log(self.current_logfile)
546 self.set_user_config()
547 toolchain_packages = []
548 if self.configuration.toolchain_build:
549 toolchain_packages = self.package_model.get_selected_packages_toolchain()
550 if self.configuration.selected_image == self.recipe_model.__custom_image__:
551 packages = self.package_model.get_selected_packages()
552 image = self.hob_image
555 image = self.configuration.selected_image
556 self.handler.generate_image(image,
560 self.configuration.default_task)
562 def get_parameters_sync(self):
563 return self.handler.get_parameters()
565 def request_package_info_async(self):
566 self.handler.request_package_info()
568 def cancel_build_sync(self, force=False):
569 self.handler.cancel_build(force)
571 def cancel_parse_sync(self):
572 self.handler.cancel_parse()
574 def load_template(self, path):
575 if not os.path.isfile(path):
578 self.template = TemplateMgr()
579 # check compatibility
580 tempVer = self.template.getVersion(path)
581 if not tempVer or int(tempVer) < hobVer:
582 self.template.destroy()
587 self.template.load(path)
588 self.configuration.load(self.template)
589 except Exception as e:
590 self.show_error_dialog("Hob Exception - %s" % (str(e)))
593 self.template.destroy()
596 for layer in self.configuration.layers:
597 if not os.path.exists(layer+'/conf/layer.conf'):
600 self.save_defaults() # remember layers and settings
601 self.update_config_async()
604 def save_template(self, path, defaults=False):
605 if path.rfind("/") == -1:
609 filename = path[path.rfind("/") + 1:len(path)]
610 path = path[0:path.rfind("/")]
612 self.template = TemplateMgr()
614 self.template.open(filename, path)
615 self.configuration.save(self.template, defaults)
618 except Exception as e:
619 self.show_error_dialog("Hob Exception - %s" % (str(e)))
622 self.template.destroy()
625 def save_defaults(self):
626 if not os.path.exists(".hob/"):
628 self.save_template(".hob/default", True)
630 def switch_page(self, next_step):
631 # Main Workflow (Business Logic)
632 self.nb.set_current_page(self.__step2page__[next_step])
634 if next_step == self.MACHINE_SELECTION: # init step
635 self.image_configuration_page.show_machine()
637 elif next_step == self.RCPPKGINFO_POPULATING:
638 # MACHINE CHANGED action or SETTINGS CHANGED
639 # show the progress bar
640 self.image_configuration_page.show_info_populating()
642 elif next_step == self.RCPPKGINFO_POPULATED:
643 self.image_configuration_page.show_info_populated()
645 elif next_step == self.BASEIMG_SELECTED:
646 self.image_configuration_page.show_baseimg_selected()
648 elif next_step == self.RECIPE_SELECTION:
649 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
650 self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.ALL)
652 self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.INCLUDED)
654 elif next_step == self.PACKAGE_SELECTION:
655 self.configuration.initial_selected_packages = self.configuration.selected_packages
656 self.package_details_page.set_title("Edit packages")
657 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
658 self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
660 self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
661 self.package_details_page.show_page(self.current_logfile)
664 elif next_step == self.PACKAGE_GENERATING or next_step == self.FAST_IMAGE_GENERATING:
665 # both PACKAGE_GENERATING and FAST_IMAGE_GENERATING share the same page
666 self.build_details_page.show_page(next_step)
668 elif next_step == self.PACKAGE_GENERATED:
669 self.package_details_page.set_title("Step 2 of 2: Edit packages")
670 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
671 self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
673 self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
674 self.package_details_page.show_page(self.current_logfile)
676 elif next_step == self.IMAGE_GENERATING:
677 # after packages are generated, selected_packages need to
678 # be updated in package_model per selected_image in recipe_model
679 self.build_details_page.show_page(next_step)
681 elif next_step == self.IMAGE_GENERATED:
682 self.image_details_page.show_page(next_step)
684 elif next_step == self.MY_IMAGE_OPENED:
685 self.image_details_page.show_page(next_step)
687 self.previous_step = self.current_step
688 self.current_step = next_step
690 def set_user_config(self):
691 self.handler.init_cooker()
693 self.handler.set_bblayers(self.configuration.layers)
694 # set local configuration
695 self.handler.set_machine(self.configuration.curr_mach)
696 self.handler.set_package_format(self.configuration.curr_package_format)
697 self.handler.set_distro(self.configuration.curr_distro)
698 self.handler.set_dl_dir(self.configuration.dldir)
699 self.handler.set_sstate_dir(self.configuration.sstatedir)
700 self.handler.set_sstate_mirror(self.configuration.sstatemirror)
701 self.handler.set_pmake(self.configuration.pmake)
702 self.handler.set_bbthreads(self.configuration.bbthread)
703 self.handler.set_rootfs_size(self.configuration.image_rootfs_size)
704 self.handler.set_extra_size(self.configuration.image_extra_size)
705 self.handler.set_incompatible_license(self.configuration.incompat_license)
706 self.handler.set_sdk_machine(self.configuration.curr_sdk_machine)
707 self.handler.set_image_fstypes(self.configuration.image_fstypes)
708 self.handler.set_extra_config(self.configuration.extra_setting)
709 self.handler.set_extra_inherit("packageinfo")
710 self.handler.set_extra_inherit("image_types")
712 if self.configuration.enable_proxy == True:
713 self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
714 self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
715 self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
716 self.handler.set_git_proxy(self.configuration.combine_host_only("git"), self.configuration.combine_port_only("git"))
717 self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
718 elif self.configuration.enable_proxy == False:
719 self.handler.set_http_proxy("")
720 self.handler.set_https_proxy("")
721 self.handler.set_ftp_proxy("")
722 self.handler.set_git_proxy("", "")
723 self.handler.set_cvs_proxy("", "")
725 def update_recipe_model(self, selected_image, selected_recipes):
726 self.recipe_model.set_selected_image(selected_image)
727 self.recipe_model.set_selected_recipes(selected_recipes)
729 def update_package_model(self, selected_packages):
730 left = self.package_model.set_selected_packages(selected_packages)
731 self.configuration.selected_packages += left
733 def update_configuration_parameters(self, params):
735 self.configuration.update(params)
736 self.parameters.update(params)
739 self.configuration.curr_mach = ""
740 self.configuration.clear_selection()
741 self.image_configuration_page.switch_machine_combo()
742 self.switch_page(self.MACHINE_SELECTION)
745 def handler_config_updated_cb(self, handler, which, values):
746 if which == "distro":
747 self.parameters.all_distros = values
748 elif which == "machine":
749 self.parameters.all_machines = values
750 self.image_configuration_page.update_machine_combo()
751 elif which == "machine-sdk":
752 self.parameters.all_sdk_machines = values
754 def handler_package_formats_updated_cb(self, handler, formats):
755 self.parameters.all_package_formats = formats
757 def handler_command_succeeded_cb(self, handler, initcmd):
758 if initcmd == self.handler.GENERATE_CONFIGURATION:
759 if not self.configuration.curr_mach:
760 self.configuration.curr_mach = self.handler.runCommand(["getVariable", "HOB_MACHINE"]) or ""
761 self.update_configuration_parameters(self.get_parameters_sync())
763 elif initcmd == self.handler.SANITY_CHECK:
764 self.image_configuration_page.switch_machine_combo()
765 elif initcmd in [self.handler.GENERATE_RECIPES,
766 self.handler.GENERATE_PACKAGES,
767 self.handler.GENERATE_IMAGE]:
768 self.update_configuration_parameters(self.get_parameters_sync())
769 self.request_package_info_async()
770 elif initcmd == self.handler.POPULATE_PACKAGEINFO:
771 if self.current_step == self.RCPPKGINFO_POPULATING:
772 self.switch_page(self.RCPPKGINFO_POPULATED)
773 self.rcppkglist_populated()
776 self.rcppkglist_populated()
777 if self.current_step == self.FAST_IMAGE_GENERATING:
778 self.generate_image_async(True)
780 def show_error_dialog(self, msg):
781 lbl = "<b>Error</b>\n"
782 lbl = lbl + "%s\n\n" % glib.markup_escape_text(msg)
783 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
784 button = dialog.add_button("Close", gtk.RESPONSE_OK)
785 HobButton.style_button(button)
786 response = dialog.run()
789 def handler_command_failed_cb(self, handler, msg):
791 self.show_error_dialog(msg)
794 def handler_sanity_failed_cb(self, handler, msg):
795 msg = msg.replace("your local.conf", "Settings")
796 self.show_error_dialog(msg)
799 def window_sensitive(self, sensitive):
800 self.image_configuration_page.machine_combo.set_sensitive(sensitive)
801 self.image_configuration_page.machine_combo.child.set_sensitive(sensitive)
802 self.image_configuration_page.image_combo.set_sensitive(sensitive)
803 self.image_configuration_page.image_combo.child.set_sensitive(sensitive)
804 self.image_configuration_page.layer_button.set_sensitive(sensitive)
805 self.image_configuration_page.layer_info_icon.set_sensitive(sensitive)
806 self.image_configuration_page.toolbar.set_sensitive(sensitive)
807 self.image_configuration_page.view_adv_configuration_button.set_sensitive(sensitive)
808 self.image_configuration_page.config_build_button.set_sensitive(sensitive)
810 self.recipe_details_page.set_sensitive(sensitive)
811 self.package_details_page.set_sensitive(sensitive)
812 self.build_details_page.set_sensitive(sensitive)
813 self.image_details_page.set_sensitive(sensitive)
816 self.window.set_cursor(None)
818 self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
819 self.sensitive = sensitive
822 def handler_generating_data_cb(self, handler):
823 self.window_sensitive(False)
825 def handler_data_generated_cb(self, handler):
826 self.window_sensitive(True)
828 def rcppkglist_populated(self):
829 selected_image = self.configuration.selected_image
830 selected_recipes = self.configuration.selected_recipes[:]
831 selected_packages = self.configuration.selected_packages[:]
833 self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
834 self.image_configuration_page.update_image_desc()
835 self.update_recipe_model(selected_image, selected_recipes)
836 self.update_package_model(selected_packages)
838 def recipelist_changed_cb(self, recipe_model):
839 self.recipe_details_page.refresh_selection()
841 def packagelist_changed_cb(self, package_model):
842 self.package_details_page.refresh_selection()
844 def handler_recipe_populated_cb(self, handler):
845 self.image_configuration_page.update_progress_bar("Populated recipes", 0.99)
847 def handler_package_populated_cb(self, handler):
848 self.image_configuration_page.update_progress_bar("Populated packages", 1.0)
850 def handler_parsing_started_cb(self, handler, message):
851 if self.current_step != self.RCPPKGINFO_POPULATING:
855 if message["eventname"] == "TreeDataPreparationStarted":
856 fraction = 0.6 + fraction
857 self.image_configuration_page.stop_button.set_sensitive(False)
859 self.image_configuration_page.stop_button.set_sensitive(True)
861 self.image_configuration_page.update_progress_bar(message["title"], fraction)
863 def handler_parsing_cb(self, handler, message):
864 if self.current_step != self.RCPPKGINFO_POPULATING:
867 fraction = message["current"] * 1.0/message["total"]
868 if message["eventname"] == "TreeDataPreparationProgress":
869 fraction = 0.6 + 0.38 * fraction
871 fraction = 0.6 * fraction
872 self.image_configuration_page.update_progress_bar(message["title"], fraction)
874 def handler_parsing_completed_cb(self, handler, message):
875 if self.current_step != self.RCPPKGINFO_POPULATING:
878 if message["eventname"] == "TreeDataPreparationCompleted":
882 self.image_configuration_page.update_progress_bar(message["title"], fraction)
884 def handler_build_started_cb(self, running_build):
885 if self.current_step == self.FAST_IMAGE_GENERATING:
887 elif self.current_step == self.IMAGE_GENERATING:
888 if self.previous_step == self.FAST_IMAGE_GENERATING:
892 elif self.current_step == self.PACKAGE_GENERATING:
894 self.build_details_page.update_progress_bar("Build Started: ", fraction)
895 self.build_details_page.show_configurations(self.configuration, self.parameters)
897 def build_succeeded(self):
898 if self.current_step == self.FAST_IMAGE_GENERATING:
900 elif self.current_step == self.IMAGE_GENERATING:
902 self.parameters.image_names = []
903 selected_image = self.recipe_model.get_selected_image()
904 if selected_image == self.recipe_model.__custom_image__:
905 linkname = 'hob-image-' + self.configuration.curr_mach
907 linkname = selected_image + '-' + self.configuration.curr_mach
908 image_extension = self.get_image_extension()
909 for image_type in self.parameters.image_types:
910 if image_type in image_extension:
911 real_types = image_extension[image_type]
913 real_types = [image_type]
914 for real_image_type in real_types:
915 linkpath = self.parameters.image_addr + '/' + linkname + '.' + real_image_type
916 if os.path.exists(linkpath):
917 self.parameters.image_names.append(os.readlink(linkpath))
918 elif self.current_step == self.PACKAGE_GENERATING:
920 self.build_details_page.update_progress_bar("Build Completed: ", fraction)
921 self.handler.build_succeeded_async()
922 self.stopping = False
924 if self.current_step == self.PACKAGE_GENERATING:
925 self.switch_page(self.PACKAGE_GENERATED)
926 elif self.current_step == self.IMAGE_GENERATING:
927 self.switch_page(self.IMAGE_GENERATED)
929 def build_failed(self):
932 message = "Build stopped: "
933 fraction = self.build_details_page.progress_bar.get_fraction()
934 stop_to_next_edit = ""
935 if self.current_step == self.FAST_IMAGE_GENERATING:
936 stop_to_next_edit = "image configuration"
937 elif self.current_step == self.IMAGE_GENERATING:
938 if self.previous_step == self.FAST_IMAGE_GENERATING:
939 stop_to_next_edit = "image configuration"
941 stop_to_next_edit = "packages"
942 elif self.current_step == self.PACKAGE_GENERATING:
943 stop_to_next_edit = "recipes"
944 button = self.build_details_page.show_stop_page(stop_to_next_edit.split(' ')[0])
945 self.set_default(button)
947 fail_to_next_edit = ""
948 if self.current_step == self.FAST_IMAGE_GENERATING:
949 fail_to_next_edit = "image configuration"
951 elif self.current_step == self.IMAGE_GENERATING:
952 if self.previous_step == self.FAST_IMAGE_GENERATING:
953 fail_to_next_edit = "image configuration"
955 fail_to_next_edit = "packages"
957 elif self.current_step == self.PACKAGE_GENERATING:
958 fail_to_next_edit = "recipes"
960 self.build_details_page.show_fail_page(fail_to_next_edit.split(' ')[0])
962 message = "Build failed: "
963 self.build_details_page.update_progress_bar(message, fraction, status)
964 self.build_details_page.show_back_button()
965 self.build_details_page.hide_stop_button()
966 self.handler.build_failed_async()
967 self.stopping = False
969 def handler_build_succeeded_cb(self, running_build):
970 if not self.stopping:
971 self.build_succeeded()
976 def handler_build_failed_cb(self, running_build):
979 def handler_build_aborted_cb(self, running_build):
982 def handler_no_provider_cb(self, running_build, msg):
983 dialog = CrumbsMessageDialog(self, glib.markup_escape_text(msg), gtk.STOCK_DIALOG_INFO)
984 button = dialog.add_button("Close", gtk.RESPONSE_OK)
985 HobButton.style_button(button)
990 def handler_task_started_cb(self, running_build, message):
991 fraction = message["current"] * 1.0/message["total"]
992 title = "Build packages"
993 if self.current_step == self.FAST_IMAGE_GENERATING:
994 if message["eventname"] == "sceneQueueTaskStarted":
995 fraction = 0.27 * fraction
996 elif message["eventname"] == "runQueueTaskStarted":
997 fraction = 0.27 + 0.63 * fraction
998 elif self.current_step == self.IMAGE_GENERATING:
999 title = "Build image"
1000 if self.previous_step == self.FAST_IMAGE_GENERATING:
1001 if message["eventname"] == "sceneQueueTaskStarted":
1002 fraction = 0.27 + 0.63 + 0.03 * fraction
1003 elif message["eventname"] == "runQueueTaskStarted":
1004 fraction = 0.27 + 0.63 + 0.03 + 0.07 * fraction
1006 if message["eventname"] == "sceneQueueTaskStarted":
1007 fraction = 0.2 * fraction
1008 elif message["eventname"] == "runQueueTaskStarted":
1009 fraction = 0.2 + 0.8 * fraction
1010 elif self.current_step == self.PACKAGE_GENERATING:
1011 if message["eventname"] == "sceneQueueTaskStarted":
1012 fraction = 0.2 * fraction
1013 elif message["eventname"] == "runQueueTaskStarted":
1014 fraction = 0.2 + 0.8 * fraction
1015 self.build_details_page.update_progress_bar(title + ": ", fraction)
1016 self.build_details_page.update_build_status(message["current"], message["total"], message["task"])
1018 def handler_build_failure_cb(self, running_build):
1019 self.build_details_page.show_issues()
1021 def handler_build_log_cb(self, running_build, func, obj):
1022 if hasattr(self.logger, func):
1023 getattr(self.logger, func)(obj)
1025 def destroy_window_cb(self, widget, event):
1026 if not self.sensitive:
1028 lbl = "<b>Do you really want to exit the Hob image creator?</b>"
1029 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1030 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1031 HobAltButton.style_button(button)
1032 button = dialog.add_button("Exit Hob", gtk.RESPONSE_YES)
1033 HobButton.style_button(button)
1034 dialog.set_default_response(gtk.RESPONSE_YES)
1035 response = dialog.run()
1037 if response == gtk.RESPONSE_YES:
1043 def build_packages(self):
1044 _, all_recipes = self.recipe_model.get_selected_recipes()
1046 lbl = "<b>No selections made</b>\nYou have not made any selections"
1047 lbl = lbl + " so there isn't anything to bake at this time."
1048 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1049 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1050 HobButton.style_button(button)
1054 self.generate_packages_async(True)
1056 def build_image(self):
1057 selected_packages = self.package_model.get_selected_packages()
1058 if not selected_packages:
1059 lbl = "<b>No selections made</b>\nYou have not made any selections"
1060 lbl = lbl + " so there isn't anything to bake at this time."
1061 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1062 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1063 HobButton.style_button(button)
1067 self.generate_image_async(True)
1069 def just_bake(self):
1070 selected_image = self.recipe_model.get_selected_image()
1071 selected_packages = self.package_model.get_selected_packages() or []
1073 # If no base image and no selected packages don't build anything
1074 if not (selected_packages or selected_image != self.recipe_model.__custom_image__):
1075 lbl = "<b>No selections made</b>\nYou have not made any selections"
1076 lbl = lbl + " so there isn't anything to bake at this time."
1077 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1078 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1079 HobButton.style_button(button)
1084 self.fast_generate_image_async(True)
1086 def show_binb_dialog(self, binb):
1087 markup = "<b>Brought in by:</b>\n%s" % binb
1088 ptip = PersistentTooltip(markup, self)
1092 def show_layer_selection_dialog(self):
1093 dialog = LayerSelectionDialog(title = "Layers",
1094 layers = copy.deepcopy(self.configuration.layers),
1095 all_layers = self.parameters.all_layers,
1097 flags = gtk.DIALOG_MODAL
1098 | gtk.DIALOG_DESTROY_WITH_PARENT
1099 | gtk.DIALOG_NO_SEPARATOR)
1100 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1101 HobAltButton.style_button(button)
1102 button = dialog.add_button("OK", gtk.RESPONSE_YES)
1103 HobButton.style_button(button)
1104 response = dialog.run()
1105 if response == gtk.RESPONSE_YES:
1106 self.configuration.layers = dialog.layers
1107 self.save_defaults() # remember layers
1109 if dialog.layers_changed:
1110 self.update_config_async()
1113 def show_load_template_dialog(self):
1114 dialog = gtk.FileChooserDialog("Load Template Files", self,
1115 gtk.FILE_CHOOSER_ACTION_OPEN)
1116 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1117 HobAltButton.style_button(button)
1118 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1119 HobButton.style_button(button)
1120 filter = gtk.FileFilter()
1121 filter.set_name("Hob Files")
1122 filter.add_pattern("*.hob")
1123 dialog.add_filter(filter)
1125 response = dialog.run()
1127 if response == gtk.RESPONSE_YES:
1128 path = dialog.get_filename()
1130 return response == gtk.RESPONSE_YES, path
1132 def show_save_template_dialog(self):
1133 dialog = gtk.FileChooserDialog("Save Template Files", self,
1134 gtk.FILE_CHOOSER_ACTION_SAVE)
1135 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1136 HobAltButton.style_button(button)
1137 button = dialog.add_button("Save", gtk.RESPONSE_YES)
1138 HobButton.style_button(button)
1139 dialog.set_current_name("hob")
1140 response = dialog.run()
1141 if response == gtk.RESPONSE_YES:
1142 path = dialog.get_filename()
1143 self.save_template(path)
1146 def get_image_extension(self):
1147 image_extension = {}
1148 for type in self.parameters.image_types:
1149 ext = self.handler.runCommand(["getVariable", "IMAGE_EXTENSION_%s" % type])
1151 image_extension[type] = ext.split(' ')
1153 return image_extension
1155 def show_load_my_images_dialog(self):
1156 image_extension = self.get_image_extension()
1157 dialog = ImageSelectionDialog(self.parameters.image_addr, self.parameters.image_types,
1158 "Open My Images", self,
1159 gtk.FILE_CHOOSER_ACTION_SAVE, None,
1161 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1162 HobAltButton.style_button(button)
1163 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1164 HobButton.style_button(button)
1165 response = dialog.run()
1166 if response == gtk.RESPONSE_YES:
1167 if not dialog.image_names:
1168 lbl = "<b>No selections made</b>\nYou have not made any selections"
1169 crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1170 button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
1171 HobButton.style_button(button)
1173 crumbs_dialog.destroy()
1177 self.parameters.image_addr = dialog.image_folder
1178 self.parameters.image_names = dialog.image_names[:]
1179 self.switch_page(self.MY_IMAGE_OPENED)
1183 def show_adv_settings_dialog(self):
1184 dialog = AdvancedSettingDialog(title = "Advanced configuration",
1185 configuration = copy.deepcopy(self.configuration),
1186 all_image_types = self.parameters.image_types,
1187 all_package_formats = self.parameters.all_package_formats,
1188 all_distros = self.parameters.all_distros,
1189 all_sdk_machines = self.parameters.all_sdk_machines,
1190 max_threads = self.parameters.max_threads,
1192 flags = gtk.DIALOG_MODAL
1193 | gtk.DIALOG_DESTROY_WITH_PARENT
1194 | gtk.DIALOG_NO_SEPARATOR)
1195 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1196 HobAltButton.style_button(button)
1197 button = dialog.add_button("Save", gtk.RESPONSE_YES)
1198 HobButton.style_button(button)
1199 response = dialog.run()
1200 settings_changed = False
1201 if response == gtk.RESPONSE_YES:
1202 self.configuration = dialog.configuration
1203 self.save_defaults() # remember settings
1204 settings_changed = dialog.settings_changed
1206 return response == gtk.RESPONSE_YES, settings_changed
1208 def show_simple_settings_dialog(self):
1209 dialog = SimpleSettingsDialog(title = "Settings",
1210 configuration = copy.deepcopy(self.configuration),
1211 all_image_types = self.parameters.image_types,
1212 all_package_formats = self.parameters.all_package_formats,
1213 all_distros = self.parameters.all_distros,
1214 all_sdk_machines = self.parameters.all_sdk_machines,
1215 max_threads = self.parameters.max_threads,
1217 flags = gtk.DIALOG_MODAL
1218 | gtk.DIALOG_DESTROY_WITH_PARENT
1219 | gtk.DIALOG_NO_SEPARATOR)
1220 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1221 HobAltButton.style_button(button)
1222 button = dialog.add_button("Save", gtk.RESPONSE_YES)
1223 HobButton.style_button(button)
1224 response = dialog.run()
1225 settings_changed = False
1226 if response == gtk.RESPONSE_YES:
1227 self.configuration = dialog.configuration
1228 self.save_defaults() # remember settings
1229 settings_changed = dialog.settings_changed
1231 return response == gtk.RESPONSE_YES, settings_changed
1233 def reparse_post_adv_settings(self):
1234 if not self.configuration.curr_mach:
1235 self.update_config_async()
1237 self.configuration.clear_selection()
1238 # DO reparse recipes
1239 self.populate_recipe_package_info_async()
1241 def deploy_image(self, image_name):
1243 lbl = "<b>Please select an image to deploy.</b>"
1244 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1245 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1246 HobButton.style_button(button)
1251 image_path = os.path.join(self.parameters.image_addr, image_name)
1252 dialog = DeployImageDialog(title = "Usb Image Maker",
1253 image_path = image_path,
1255 flags = gtk.DIALOG_MODAL
1256 | gtk.DIALOG_DESTROY_WITH_PARENT
1257 | gtk.DIALOG_NO_SEPARATOR)
1258 button = dialog.add_button("Close", gtk.RESPONSE_NO)
1259 HobAltButton.style_button(button)
1260 button = dialog.add_button("Make usb image", gtk.RESPONSE_YES)
1261 HobButton.style_button(button)
1262 response = dialog.run()
1265 def show_load_kernel_dialog(self):
1266 dialog = gtk.FileChooserDialog("Load Kernel Files", self,
1267 gtk.FILE_CHOOSER_ACTION_SAVE)
1268 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1269 HobAltButton.style_button(button)
1270 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1271 HobButton.style_button(button)
1272 filter = gtk.FileFilter()
1273 filter.set_name("Kernel Files")
1274 filter.add_pattern("*.bin")
1275 dialog.add_filter(filter)
1277 dialog.set_current_folder(self.parameters.image_addr)
1279 response = dialog.run()
1281 if response == gtk.RESPONSE_YES:
1282 kernel_path = dialog.get_filename()
1288 def runqemu_image(self, image_name, kernel_name):
1289 if not image_name or not kernel_name:
1290 lbl = "<b>Please select an %s to launch in QEMU.</b>" % ("kernel" if image_name else "image")
1291 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1292 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1293 HobButton.style_button(button)
1298 kernel_path = os.path.join(self.parameters.image_addr, kernel_name)
1299 image_path = os.path.join(self.parameters.image_addr, image_name)
1301 source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
1302 tmp_path = self.parameters.tmpdir
1303 cmdline = bb.ui.crumbs.utils.which_terminal()
1304 if os.path.exists(image_path) and os.path.exists(kernel_path) \
1305 and os.path.exists(source_env_path) and os.path.exists(tmp_path) \
1307 cmdline += "\' bash -c \"export OE_TMPDIR=" + tmp_path + "; "
1308 cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
1309 cmdline += "runqemu " + kernel_path + " " + image_path + "\"\'"
1310 subprocess.Popen(shlex.split(cmdline))
1312 lbl = "<b>Path error</b>\nOne of your paths is wrong,"
1313 lbl = lbl + " please make sure the following paths exist:\n"
1314 lbl = lbl + "image path:" + image_path + "\n"
1315 lbl = lbl + "kernel path:" + kernel_path + "\n"
1316 lbl = lbl + "source environment path:" + source_env_path + "\n"
1317 lbl = lbl + "tmp path: " + tmp_path + "."
1318 lbl = lbl + "You may be missing either xterm or vte for terminal services."
1319 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
1320 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1321 HobButton.style_button(button)
1325 def show_packages(self, ask=True):
1326 _, selected_recipes = self.recipe_model.get_selected_recipes()
1327 if selected_recipes and ask:
1328 lbl = "<b>Package list may be incomplete!</b>\nDo you want to build selected recipes"
1329 lbl = lbl + " to get a full list or just view the existing packages?"
1330 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1331 button = dialog.add_button("View packages", gtk.RESPONSE_NO)
1332 HobAltButton.style_button(button)
1333 button = dialog.add_button("Build packages", gtk.RESPONSE_YES)
1334 HobButton.style_button(button)
1335 dialog.set_default_response(gtk.RESPONSE_YES)
1336 response = dialog.run()
1338 if response == gtk.RESPONSE_YES:
1339 self.generate_packages_async(True)
1341 self.switch_page(self.PACKAGE_SELECTION)
1343 self.switch_page(self.PACKAGE_SELECTION)
1345 def show_recipes(self):
1346 self.switch_page(self.RECIPE_SELECTION)
1348 def show_image_details(self):
1349 self.switch_page(self.IMAGE_GENERATED)
1351 def show_configuration(self):
1352 self.switch_page(self.BASEIMG_SELECTED)
1354 def stop_build(self):
1356 lbl = "<b>Force Stop build?</b>\nYou've already selected Stop once,"
1357 lbl = lbl + " would you like to 'Force Stop' the build?\n\n"
1358 lbl = lbl + "This will stop the build as quickly as possible but may"
1359 lbl = lbl + " well leave your build directory in an unusable state"
1360 lbl = lbl + " that requires manual steps to fix.\n"
1361 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
1362 button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
1363 HobAltButton.style_button(button)
1364 button = dialog.add_button("Force Stop", gtk.RESPONSE_YES)
1365 HobButton.style_button(button)
1367 lbl = "<b>Stop build?</b>\n\nAre you sure you want to stop this"
1368 lbl = lbl + " build?\n\n'Stop' will stop the build as soon as all in"
1369 lbl = lbl + " progress build tasks are finished. However if a"
1370 lbl = lbl + " lengthy compilation phase is in progress this may take"
1371 lbl = lbl + " some time.\n\n"
1372 lbl = lbl + "'Force Stop' will stop the build as quickly as"
1373 lbl = lbl + " possible but may well leave your build directory in an"
1374 lbl = lbl + " unusable state that requires manual steps to fix."
1375 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
1376 button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
1377 HobAltButton.style_button(button)
1378 button = dialog.add_button("Force stop", gtk.RESPONSE_YES)
1379 HobAltButton.style_button(button)
1380 button = dialog.add_button("Stop", gtk.RESPONSE_OK)
1381 HobButton.style_button(button)
1382 response = dialog.run()
1384 if response != gtk.RESPONSE_CANCEL:
1385 self.stopping = True
1386 if response == gtk.RESPONSE_OK:
1387 self.cancel_build_sync()
1388 elif response == gtk.RESPONSE_YES:
1389 self.cancel_build_sync(True)
1391 def do_log(self, consolelogfile = None):
1393 bb.utils.mkdirhier(os.path.dirname(consolelogfile))
1395 self.logger.removeHandler(self.consolelog)
1396 self.consolelog = None
1397 self.consolelog = logging.FileHandler(consolelogfile)
1398 bb.msg.addDefaultlogFilter(self.consolelog)
1399 format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
1400 self.consolelog.setFormatter(format)
1402 self.logger.addHandler(self.consolelog)