Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame^] | 1 | # |
| 2 | # BitBake Graphical GTK User Interface |
| 3 | # |
| 4 | # Copyright (C) 2011 Intel Corporation |
| 5 | # |
| 6 | # Authored by Joshua Lock <josh@linux.intel.com> |
| 7 | # Authored by Dongxiao Xu <dongxiao.xu@intel.com> |
| 8 | # |
| 9 | # This program is free software; you can redistribute it and/or modify |
| 10 | # it under the terms of the GNU General Public License version 2 as |
| 11 | # published by the Free Software Foundation. |
| 12 | # |
| 13 | # This program is distributed in the hope that it will be useful, |
| 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | # GNU General Public License for more details. |
| 17 | # |
| 18 | # You should have received a copy of the GNU General Public License along |
| 19 | # with this program; if not, write to the Free Software Foundation, Inc., |
| 20 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 21 | |
| 22 | import gobject |
| 23 | import logging |
| 24 | import ast |
| 25 | from bb.ui.crumbs.runningbuild import RunningBuild |
| 26 | |
| 27 | class HobHandler(gobject.GObject): |
| 28 | |
| 29 | """ |
| 30 | This object does BitBake event handling for the hob gui. |
| 31 | """ |
| 32 | __gsignals__ = { |
| 33 | "package-formats-updated" : (gobject.SIGNAL_RUN_LAST, |
| 34 | gobject.TYPE_NONE, |
| 35 | (gobject.TYPE_PYOBJECT,)), |
| 36 | "config-updated" : (gobject.SIGNAL_RUN_LAST, |
| 37 | gobject.TYPE_NONE, |
| 38 | (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT,)), |
| 39 | "command-succeeded" : (gobject.SIGNAL_RUN_LAST, |
| 40 | gobject.TYPE_NONE, |
| 41 | (gobject.TYPE_INT,)), |
| 42 | "command-failed" : (gobject.SIGNAL_RUN_LAST, |
| 43 | gobject.TYPE_NONE, |
| 44 | (gobject.TYPE_STRING,)), |
| 45 | "parsing-warning" : (gobject.SIGNAL_RUN_LAST, |
| 46 | gobject.TYPE_NONE, |
| 47 | (gobject.TYPE_STRING,)), |
| 48 | "sanity-failed" : (gobject.SIGNAL_RUN_LAST, |
| 49 | gobject.TYPE_NONE, |
| 50 | (gobject.TYPE_STRING, gobject.TYPE_INT)), |
| 51 | "generating-data" : (gobject.SIGNAL_RUN_LAST, |
| 52 | gobject.TYPE_NONE, |
| 53 | ()), |
| 54 | "data-generated" : (gobject.SIGNAL_RUN_LAST, |
| 55 | gobject.TYPE_NONE, |
| 56 | ()), |
| 57 | "parsing-started" : (gobject.SIGNAL_RUN_LAST, |
| 58 | gobject.TYPE_NONE, |
| 59 | (gobject.TYPE_PYOBJECT,)), |
| 60 | "parsing" : (gobject.SIGNAL_RUN_LAST, |
| 61 | gobject.TYPE_NONE, |
| 62 | (gobject.TYPE_PYOBJECT,)), |
| 63 | "parsing-completed" : (gobject.SIGNAL_RUN_LAST, |
| 64 | gobject.TYPE_NONE, |
| 65 | (gobject.TYPE_PYOBJECT,)), |
| 66 | "recipe-populated" : (gobject.SIGNAL_RUN_LAST, |
| 67 | gobject.TYPE_NONE, |
| 68 | ()), |
| 69 | "package-populated" : (gobject.SIGNAL_RUN_LAST, |
| 70 | gobject.TYPE_NONE, |
| 71 | ()), |
| 72 | "network-passed" : (gobject.SIGNAL_RUN_LAST, |
| 73 | gobject.TYPE_NONE, |
| 74 | ()), |
| 75 | "network-failed" : (gobject.SIGNAL_RUN_LAST, |
| 76 | gobject.TYPE_NONE, |
| 77 | ()), |
| 78 | } |
| 79 | |
| 80 | (GENERATE_CONFIGURATION, GENERATE_RECIPES, GENERATE_PACKAGES, GENERATE_IMAGE, POPULATE_PACKAGEINFO, SANITY_CHECK, NETWORK_TEST) = range(7) |
| 81 | (SUB_PATH_LAYERS, SUB_FILES_DISTRO, SUB_FILES_MACH, SUB_FILES_SDKMACH, SUB_MATCH_CLASS, SUB_PARSE_CONFIG, SUB_SANITY_CHECK, |
| 82 | SUB_GNERATE_TGTS, SUB_GENERATE_PKGINFO, SUB_BUILD_RECIPES, SUB_BUILD_IMAGE, SUB_NETWORK_TEST) = range(12) |
| 83 | |
| 84 | def __init__(self, server, recipe_model, package_model): |
| 85 | super(HobHandler, self).__init__() |
| 86 | |
| 87 | self.build = RunningBuild(sequential=True) |
| 88 | |
| 89 | self.recipe_model = recipe_model |
| 90 | self.package_model = package_model |
| 91 | |
| 92 | self.commands_async = [] |
| 93 | self.generating = False |
| 94 | self.current_phase = None |
| 95 | self.building = False |
| 96 | self.recipe_queue = [] |
| 97 | self.package_queue = [] |
| 98 | |
| 99 | self.server = server |
| 100 | self.error_msg = "" |
| 101 | self.initcmd = None |
| 102 | self.parsing = False |
| 103 | |
| 104 | def set_busy(self): |
| 105 | if not self.generating: |
| 106 | self.emit("generating-data") |
| 107 | self.generating = True |
| 108 | |
| 109 | def clear_busy(self): |
| 110 | if self.generating: |
| 111 | self.emit("data-generated") |
| 112 | self.generating = False |
| 113 | |
| 114 | def runCommand(self, commandline): |
| 115 | try: |
| 116 | result, error = self.server.runCommand(commandline) |
| 117 | if error: |
| 118 | raise Exception("Error running command '%s': %s" % (commandline, error)) |
| 119 | return result |
| 120 | except Exception as e: |
| 121 | self.commands_async = [] |
| 122 | self.clear_busy() |
| 123 | self.emit("command-failed", "Hob Exception - %s" % (str(e))) |
| 124 | return None |
| 125 | |
| 126 | def run_next_command(self, initcmd=None): |
| 127 | if initcmd != None: |
| 128 | self.initcmd = initcmd |
| 129 | |
| 130 | if self.commands_async: |
| 131 | self.set_busy() |
| 132 | next_command = self.commands_async.pop(0) |
| 133 | else: |
| 134 | self.clear_busy() |
| 135 | if self.initcmd != None: |
| 136 | self.emit("command-succeeded", self.initcmd) |
| 137 | return |
| 138 | |
| 139 | if next_command == self.SUB_PATH_LAYERS: |
| 140 | self.runCommand(["findConfigFilePath", "bblayers.conf"]) |
| 141 | elif next_command == self.SUB_FILES_DISTRO: |
| 142 | self.runCommand(["findConfigFiles", "DISTRO"]) |
| 143 | elif next_command == self.SUB_FILES_MACH: |
| 144 | self.runCommand(["findConfigFiles", "MACHINE"]) |
| 145 | elif next_command == self.SUB_FILES_SDKMACH: |
| 146 | self.runCommand(["findConfigFiles", "MACHINE-SDK"]) |
| 147 | elif next_command == self.SUB_MATCH_CLASS: |
| 148 | self.runCommand(["findFilesMatchingInDir", "rootfs_", "classes"]) |
| 149 | elif next_command == self.SUB_PARSE_CONFIG: |
| 150 | self.runCommand(["resetCooker"]) |
| 151 | elif next_command == self.SUB_GNERATE_TGTS: |
| 152 | self.runCommand(["generateTargetsTree", "classes/image.bbclass", []]) |
| 153 | elif next_command == self.SUB_GENERATE_PKGINFO: |
| 154 | self.runCommand(["triggerEvent", "bb.event.RequestPackageInfo()"]) |
| 155 | elif next_command == self.SUB_SANITY_CHECK: |
| 156 | self.runCommand(["triggerEvent", "bb.event.SanityCheck()"]) |
| 157 | elif next_command == self.SUB_NETWORK_TEST: |
| 158 | self.runCommand(["triggerEvent", "bb.event.NetworkTest()"]) |
| 159 | elif next_command == self.SUB_BUILD_RECIPES: |
| 160 | self.clear_busy() |
| 161 | self.building = True |
| 162 | self.runCommand(["buildTargets", self.recipe_queue, self.default_task]) |
| 163 | self.recipe_queue = [] |
| 164 | elif next_command == self.SUB_BUILD_IMAGE: |
| 165 | self.clear_busy() |
| 166 | self.building = True |
| 167 | target = self.image |
| 168 | |
| 169 | if self.base_image: |
| 170 | # Request the build of a custom image |
| 171 | self.generate_hob_base_image(target) |
| 172 | self.set_var_in_file("LINGUAS_INSTALL", "", "local.conf") |
| 173 | hobImage = self.runCommand(["matchFile", target + ".bb"]) |
| 174 | if self.base_image != self.recipe_model.__custom_image__: |
| 175 | baseImage = self.runCommand(["matchFile", self.base_image + ".bb"]) |
| 176 | version = self.runCommand(["generateNewImage", hobImage, baseImage, self.package_queue, True, ""]) |
| 177 | target += version |
| 178 | self.recipe_model.set_custom_image_version(version) |
| 179 | |
| 180 | targets = [target] |
| 181 | if self.toolchain_packages: |
| 182 | self.set_var_in_file("TOOLCHAIN_TARGET_TASK", " ".join(self.toolchain_packages), "local.conf") |
| 183 | targets.append(target + ":do_populate_sdk") |
| 184 | |
| 185 | self.runCommand(["buildTargets", targets, self.default_task]) |
| 186 | |
| 187 | def display_error(self): |
| 188 | self.clear_busy() |
| 189 | self.emit("command-failed", self.error_msg) |
| 190 | self.error_msg = "" |
| 191 | if self.building: |
| 192 | self.building = False |
| 193 | |
| 194 | def handle_event(self, event): |
| 195 | if not event: |
| 196 | return |
| 197 | if self.building: |
| 198 | self.current_phase = "building" |
| 199 | self.build.handle_event(event) |
| 200 | |
| 201 | if isinstance(event, bb.event.PackageInfo): |
| 202 | self.package_model.populate(event._pkginfolist) |
| 203 | self.emit("package-populated") |
| 204 | self.run_next_command() |
| 205 | |
| 206 | elif isinstance(event, bb.event.SanityCheckPassed): |
| 207 | reparse = self.runCommand(["getVariable", "BB_INVALIDCONF"]) or None |
| 208 | if reparse is True: |
| 209 | self.set_var_in_file("BB_INVALIDCONF", False, "local.conf") |
| 210 | self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""]) |
| 211 | self.commands_async.prepend(self.SUB_PARSE_CONFIG) |
| 212 | self.run_next_command() |
| 213 | |
| 214 | elif isinstance(event, bb.event.SanityCheckFailed): |
| 215 | self.emit("sanity-failed", event._msg, event._network_error) |
| 216 | |
| 217 | elif isinstance(event, logging.LogRecord): |
| 218 | if not self.building: |
| 219 | if event.levelno >= logging.ERROR: |
| 220 | formatter = bb.msg.BBLogFormatter() |
| 221 | msg = formatter.format(event) |
| 222 | self.error_msg += msg + '\n' |
| 223 | elif event.levelno >= logging.WARNING and self.parsing == True: |
| 224 | formatter = bb.msg.BBLogFormatter() |
| 225 | msg = formatter.format(event) |
| 226 | warn_msg = msg + '\n' |
| 227 | self.emit("parsing-warning", warn_msg) |
| 228 | |
| 229 | elif isinstance(event, bb.event.TargetsTreeGenerated): |
| 230 | self.current_phase = "data generation" |
| 231 | if event._model: |
| 232 | self.recipe_model.populate(event._model) |
| 233 | self.emit("recipe-populated") |
| 234 | elif isinstance(event, bb.event.ConfigFilesFound): |
| 235 | self.current_phase = "configuration lookup" |
| 236 | var = event._variable |
| 237 | values = event._values |
| 238 | values.sort() |
| 239 | self.emit("config-updated", var, values) |
| 240 | elif isinstance(event, bb.event.ConfigFilePathFound): |
| 241 | self.current_phase = "configuration lookup" |
| 242 | elif isinstance(event, bb.event.FilesMatchingFound): |
| 243 | self.current_phase = "configuration lookup" |
| 244 | # FIXME: hard coding, should at least be a variable shared between |
| 245 | # here and the caller |
| 246 | if event._pattern == "rootfs_": |
| 247 | formats = [] |
| 248 | for match in event._matches: |
| 249 | classname, sep, cls = match.rpartition(".") |
| 250 | fs, sep, format = classname.rpartition("_") |
| 251 | formats.append(format) |
| 252 | formats.sort() |
| 253 | self.emit("package-formats-updated", formats) |
| 254 | elif isinstance(event, bb.command.CommandCompleted): |
| 255 | self.current_phase = None |
| 256 | self.run_next_command() |
| 257 | elif isinstance(event, bb.command.CommandFailed): |
| 258 | if event.error not in ("Forced shutdown", "Stopped build"): |
| 259 | self.error_msg += event.error |
| 260 | self.commands_async = [] |
| 261 | self.display_error() |
| 262 | elif isinstance(event, (bb.event.ParseStarted, |
| 263 | bb.event.CacheLoadStarted, |
| 264 | bb.event.TreeDataPreparationStarted, |
| 265 | )): |
| 266 | message = {} |
| 267 | message["eventname"] = bb.event.getName(event) |
| 268 | message["current"] = 0 |
| 269 | message["total"] = None |
| 270 | message["title"] = "Parsing recipes" |
| 271 | self.emit("parsing-started", message) |
| 272 | if isinstance(event, bb.event.ParseStarted): |
| 273 | self.parsing = True |
| 274 | elif isinstance(event, (bb.event.ParseProgress, |
| 275 | bb.event.CacheLoadProgress, |
| 276 | bb.event.TreeDataPreparationProgress)): |
| 277 | message = {} |
| 278 | message["eventname"] = bb.event.getName(event) |
| 279 | message["current"] = event.current |
| 280 | message["total"] = event.total |
| 281 | message["title"] = "Parsing recipes" |
| 282 | self.emit("parsing", message) |
| 283 | elif isinstance(event, (bb.event.ParseCompleted, |
| 284 | bb.event.CacheLoadCompleted, |
| 285 | bb.event.TreeDataPreparationCompleted)): |
| 286 | message = {} |
| 287 | message["eventname"] = bb.event.getName(event) |
| 288 | message["current"] = event.total |
| 289 | message["total"] = event.total |
| 290 | message["title"] = "Parsing recipes" |
| 291 | self.emit("parsing-completed", message) |
| 292 | if isinstance(event, bb.event.ParseCompleted): |
| 293 | self.parsing = False |
| 294 | elif isinstance(event, bb.event.NetworkTestFailed): |
| 295 | self.emit("network-failed") |
| 296 | self.run_next_command() |
| 297 | elif isinstance(event, bb.event.NetworkTestPassed): |
| 298 | self.emit("network-passed") |
| 299 | self.run_next_command() |
| 300 | |
| 301 | if self.error_msg and not self.commands_async: |
| 302 | self.display_error() |
| 303 | |
| 304 | return |
| 305 | |
| 306 | def init_cooker(self): |
| 307 | self.runCommand(["createConfigFile", ".hob.conf"]) |
| 308 | |
| 309 | def set_extra_inherit(self, bbclass): |
| 310 | self.append_var_in_file("INHERIT", bbclass, ".hob.conf") |
| 311 | |
| 312 | def set_bblayers(self, bblayers): |
| 313 | self.set_var_in_file("BBLAYERS", " ".join(bblayers), "bblayers.conf") |
| 314 | |
| 315 | def set_machine(self, machine): |
| 316 | if machine: |
| 317 | self.early_assign_var_in_file("MACHINE", machine, "local.conf") |
| 318 | |
| 319 | def set_sdk_machine(self, sdk_machine): |
| 320 | self.set_var_in_file("SDKMACHINE", sdk_machine, "local.conf") |
| 321 | |
| 322 | def set_image_fstypes(self, image_fstypes): |
| 323 | self.set_var_in_file("IMAGE_FSTYPES", image_fstypes, "local.conf") |
| 324 | |
| 325 | def set_distro(self, distro): |
| 326 | self.set_var_in_file("DISTRO", distro, "local.conf") |
| 327 | |
| 328 | def set_package_format(self, format): |
| 329 | package_classes = "" |
| 330 | for pkgfmt in format.split(): |
| 331 | package_classes += ("package_%s" % pkgfmt + " ") |
| 332 | self.set_var_in_file("PACKAGE_CLASSES", package_classes, "local.conf") |
| 333 | |
| 334 | def set_bbthreads(self, threads): |
| 335 | self.set_var_in_file("BB_NUMBER_THREADS", threads, "local.conf") |
| 336 | |
| 337 | def set_pmake(self, threads): |
| 338 | pmake = "-j %s" % threads |
| 339 | self.set_var_in_file("PARALLEL_MAKE", pmake, "local.conf") |
| 340 | |
| 341 | def set_dl_dir(self, directory): |
| 342 | self.set_var_in_file("DL_DIR", directory, "local.conf") |
| 343 | |
| 344 | def set_sstate_dir(self, directory): |
| 345 | self.set_var_in_file("SSTATE_DIR", directory, "local.conf") |
| 346 | |
| 347 | def set_sstate_mirrors(self, url): |
| 348 | self.set_var_in_file("SSTATE_MIRRORS", url, "local.conf") |
| 349 | |
| 350 | def set_extra_size(self, image_extra_size): |
| 351 | self.set_var_in_file("IMAGE_ROOTFS_EXTRA_SPACE", str(image_extra_size), "local.conf") |
| 352 | |
| 353 | def set_rootfs_size(self, image_rootfs_size): |
| 354 | self.set_var_in_file("IMAGE_ROOTFS_SIZE", str(image_rootfs_size), "local.conf") |
| 355 | |
| 356 | def set_incompatible_license(self, incompat_license): |
| 357 | self.set_var_in_file("INCOMPATIBLE_LICENSE", incompat_license, "local.conf") |
| 358 | |
| 359 | def set_extra_setting(self, extra_setting): |
| 360 | self.set_var_in_file("EXTRA_SETTING", extra_setting, "local.conf") |
| 361 | |
| 362 | def set_extra_config(self, extra_setting): |
| 363 | old_extra_setting = self.runCommand(["getVariable", "EXTRA_SETTING"]) or {} |
| 364 | old_extra_setting = str(old_extra_setting) |
| 365 | |
| 366 | old_extra_setting = ast.literal_eval(old_extra_setting) |
| 367 | if not type(old_extra_setting) == dict: |
| 368 | old_extra_setting = {} |
| 369 | |
| 370 | # settings not changed |
| 371 | if old_extra_setting == extra_setting: |
| 372 | return |
| 373 | |
| 374 | # remove the old EXTRA SETTING variable |
| 375 | self.remove_var_from_file("EXTRA_SETTING") |
| 376 | |
| 377 | # remove old settings from conf |
| 378 | for key in old_extra_setting.keys(): |
| 379 | if key not in extra_setting: |
| 380 | self.remove_var_from_file(key) |
| 381 | |
| 382 | # add new settings |
| 383 | for key, value in extra_setting.iteritems(): |
| 384 | self.set_var_in_file(key, value, "local.conf") |
| 385 | |
| 386 | if extra_setting: |
| 387 | self.set_var_in_file("EXTRA_SETTING", extra_setting, "local.conf") |
| 388 | |
| 389 | def set_http_proxy(self, http_proxy): |
| 390 | self.set_var_in_file("http_proxy", http_proxy, "local.conf") |
| 391 | |
| 392 | def set_https_proxy(self, https_proxy): |
| 393 | self.set_var_in_file("https_proxy", https_proxy, "local.conf") |
| 394 | |
| 395 | def set_ftp_proxy(self, ftp_proxy): |
| 396 | self.set_var_in_file("ftp_proxy", ftp_proxy, "local.conf") |
| 397 | |
| 398 | def set_socks_proxy(self, socks_proxy): |
| 399 | self.set_var_in_file("all_proxy", socks_proxy, "local.conf") |
| 400 | |
| 401 | def set_cvs_proxy(self, host, port): |
| 402 | self.set_var_in_file("CVS_PROXY_HOST", host, "local.conf") |
| 403 | self.set_var_in_file("CVS_PROXY_PORT", port, "local.conf") |
| 404 | |
| 405 | def request_package_info(self): |
| 406 | self.commands_async.append(self.SUB_GENERATE_PKGINFO) |
| 407 | self.run_next_command(self.POPULATE_PACKAGEINFO) |
| 408 | |
| 409 | def trigger_sanity_check(self): |
| 410 | self.commands_async.append(self.SUB_SANITY_CHECK) |
| 411 | self.run_next_command(self.SANITY_CHECK) |
| 412 | |
| 413 | def trigger_network_test(self): |
| 414 | self.commands_async.append(self.SUB_NETWORK_TEST) |
| 415 | self.run_next_command(self.NETWORK_TEST) |
| 416 | |
| 417 | def generate_configuration(self): |
| 418 | self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""]) |
| 419 | self.commands_async.append(self.SUB_PARSE_CONFIG) |
| 420 | self.commands_async.append(self.SUB_PATH_LAYERS) |
| 421 | self.commands_async.append(self.SUB_FILES_DISTRO) |
| 422 | self.commands_async.append(self.SUB_FILES_MACH) |
| 423 | self.commands_async.append(self.SUB_FILES_SDKMACH) |
| 424 | self.commands_async.append(self.SUB_MATCH_CLASS) |
| 425 | self.run_next_command(self.GENERATE_CONFIGURATION) |
| 426 | |
| 427 | def generate_recipes(self): |
| 428 | self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""]) |
| 429 | self.commands_async.append(self.SUB_PARSE_CONFIG) |
| 430 | self.commands_async.append(self.SUB_GNERATE_TGTS) |
| 431 | self.run_next_command(self.GENERATE_RECIPES) |
| 432 | |
| 433 | def generate_packages(self, tgts, default_task="build"): |
| 434 | targets = [] |
| 435 | targets.extend(tgts) |
| 436 | self.recipe_queue = targets |
| 437 | self.default_task = default_task |
| 438 | self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""]) |
| 439 | self.commands_async.append(self.SUB_PARSE_CONFIG) |
| 440 | self.commands_async.append(self.SUB_BUILD_RECIPES) |
| 441 | self.run_next_command(self.GENERATE_PACKAGES) |
| 442 | |
| 443 | def generate_image(self, image, base_image, image_packages=None, toolchain_packages=None, default_task="build"): |
| 444 | self.image = image |
| 445 | self.base_image = base_image |
| 446 | if image_packages: |
| 447 | self.package_queue = image_packages |
| 448 | else: |
| 449 | self.package_queue = [] |
| 450 | if toolchain_packages: |
| 451 | self.toolchain_packages = toolchain_packages |
| 452 | else: |
| 453 | self.toolchain_packages = [] |
| 454 | self.default_task = default_task |
| 455 | self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""]) |
| 456 | self.commands_async.append(self.SUB_PARSE_CONFIG) |
| 457 | self.commands_async.append(self.SUB_BUILD_IMAGE) |
| 458 | self.run_next_command(self.GENERATE_IMAGE) |
| 459 | |
| 460 | def generate_new_image(self, image, base_image, package_queue, description): |
| 461 | if base_image: |
| 462 | base_image = self.runCommand(["matchFile", self.base_image + ".bb"]) |
| 463 | self.runCommand(["generateNewImage", image, base_image, package_queue, False, description]) |
| 464 | |
| 465 | def generate_hob_base_image(self, hob_image): |
| 466 | image_dir = self.get_topdir() + "/recipes/images/" |
| 467 | recipe_name = hob_image + ".bb" |
| 468 | self.ensure_dir(image_dir) |
| 469 | self.generate_new_image(image_dir + recipe_name, None, [], "") |
| 470 | |
| 471 | def ensure_dir(self, directory): |
| 472 | self.runCommand(["ensureDir", directory]) |
| 473 | |
| 474 | def build_succeeded_async(self): |
| 475 | self.building = False |
| 476 | |
| 477 | def build_failed_async(self): |
| 478 | self.initcmd = None |
| 479 | self.commands_async = [] |
| 480 | self.building = False |
| 481 | |
| 482 | def cancel_parse(self): |
| 483 | self.runCommand(["stateForceShutdown"]) |
| 484 | |
| 485 | def cancel_build(self, force=False): |
| 486 | if force: |
| 487 | # Force the cooker to stop as quickly as possible |
| 488 | self.runCommand(["stateForceShutdown"]) |
| 489 | else: |
| 490 | # Wait for tasks to complete before shutting down, this helps |
| 491 | # leave the workdir in a usable state |
| 492 | self.runCommand(["stateShutdown"]) |
| 493 | |
| 494 | def reset_build(self): |
| 495 | self.build.reset() |
| 496 | |
| 497 | def get_logfile(self): |
| 498 | return self.server.runCommand(["getVariable", "BB_CONSOLELOG"])[0] |
| 499 | |
| 500 | def get_topdir(self): |
| 501 | return self.runCommand(["getVariable", "TOPDIR"]) or "" |
| 502 | |
| 503 | def _remove_redundant(self, string): |
| 504 | ret = [] |
| 505 | for i in string.split(): |
| 506 | if i not in ret: |
| 507 | ret.append(i) |
| 508 | return " ".join(ret) |
| 509 | |
| 510 | def set_var_in_file(self, var, val, default_file=None): |
| 511 | self.runCommand(["enableDataTracking"]) |
| 512 | self.server.runCommand(["setVarFile", var, val, default_file, "set"]) |
| 513 | self.runCommand(["disableDataTracking"]) |
| 514 | |
| 515 | def early_assign_var_in_file(self, var, val, default_file=None): |
| 516 | self.runCommand(["enableDataTracking"]) |
| 517 | self.server.runCommand(["setVarFile", var, val, default_file, "earlyAssign"]) |
| 518 | self.runCommand(["disableDataTracking"]) |
| 519 | |
| 520 | def remove_var_from_file(self, var): |
| 521 | self.server.runCommand(["removeVarFile", var]) |
| 522 | |
| 523 | def append_var_in_file(self, var, val, default_file=None): |
| 524 | self.server.runCommand(["setVarFile", var, val, default_file, "append"]) |
| 525 | |
| 526 | def append_to_bbfiles(self, val): |
| 527 | bbfiles = self.runCommand(["getVariable", "BBFILES", "False"]) or "" |
| 528 | bbfiles = bbfiles.split() |
| 529 | if val not in bbfiles: |
| 530 | self.append_var_in_file("BBFILES", val, "bblayers.conf") |
| 531 | |
| 532 | def get_parameters(self): |
| 533 | # retrieve the parameters from bitbake |
| 534 | params = {} |
| 535 | params["core_base"] = self.runCommand(["getVariable", "COREBASE"]) or "" |
| 536 | params["layer"] = self.runCommand(["getVariable", "BBLAYERS"]) or "" |
| 537 | params["layers_non_removable"] = self.runCommand(["getVariable", "BBLAYERS_NON_REMOVABLE"]) or "" |
| 538 | params["dldir"] = self.runCommand(["getVariable", "DL_DIR"]) or "" |
| 539 | params["machine"] = self.runCommand(["getVariable", "MACHINE"]) or "" |
| 540 | params["distro"] = self.runCommand(["getVariable", "DISTRO"]) or "defaultsetup" |
| 541 | params["pclass"] = self.runCommand(["getVariable", "PACKAGE_CLASSES"]) or "" |
| 542 | params["sstatedir"] = self.runCommand(["getVariable", "SSTATE_DIR"]) or "" |
| 543 | params["sstatemirror"] = self.runCommand(["getVariable", "SSTATE_MIRRORS"]) or "" |
| 544 | |
| 545 | num_threads = self.runCommand(["getCpuCount"]) |
| 546 | if not num_threads: |
| 547 | num_threads = 1 |
| 548 | max_threads = 65536 |
| 549 | else: |
| 550 | try: |
| 551 | num_threads = int(num_threads) |
| 552 | max_threads = 16 * num_threads |
| 553 | except: |
| 554 | num_threads = 1 |
| 555 | max_threads = 65536 |
| 556 | params["max_threads"] = max_threads |
| 557 | |
| 558 | bbthread = self.runCommand(["getVariable", "BB_NUMBER_THREADS"]) |
| 559 | if not bbthread: |
| 560 | bbthread = num_threads |
| 561 | else: |
| 562 | try: |
| 563 | bbthread = int(bbthread) |
| 564 | except: |
| 565 | bbthread = num_threads |
| 566 | params["bbthread"] = bbthread |
| 567 | |
| 568 | pmake = self.runCommand(["getVariable", "PARALLEL_MAKE"]) |
| 569 | if not pmake: |
| 570 | pmake = num_threads |
| 571 | elif isinstance(pmake, int): |
| 572 | pass |
| 573 | else: |
| 574 | try: |
| 575 | pmake = int(pmake.lstrip("-j ")) |
| 576 | except: |
| 577 | pmake = num_threads |
| 578 | params["pmake"] = "-j %s" % pmake |
| 579 | |
| 580 | params["image_addr"] = self.runCommand(["getVariable", "DEPLOY_DIR_IMAGE"]) or "" |
| 581 | |
| 582 | image_extra_size = self.runCommand(["getVariable", "IMAGE_ROOTFS_EXTRA_SPACE"]) |
| 583 | if not image_extra_size: |
| 584 | image_extra_size = 0 |
| 585 | else: |
| 586 | try: |
| 587 | image_extra_size = int(image_extra_size) |
| 588 | except: |
| 589 | image_extra_size = 0 |
| 590 | params["image_extra_size"] = image_extra_size |
| 591 | |
| 592 | image_rootfs_size = self.runCommand(["getVariable", "IMAGE_ROOTFS_SIZE"]) |
| 593 | if not image_rootfs_size: |
| 594 | image_rootfs_size = 0 |
| 595 | else: |
| 596 | try: |
| 597 | image_rootfs_size = int(image_rootfs_size) |
| 598 | except: |
| 599 | image_rootfs_size = 0 |
| 600 | params["image_rootfs_size"] = image_rootfs_size |
| 601 | |
| 602 | image_overhead_factor = self.runCommand(["getVariable", "IMAGE_OVERHEAD_FACTOR"]) |
| 603 | if not image_overhead_factor: |
| 604 | image_overhead_factor = 1 |
| 605 | else: |
| 606 | try: |
| 607 | image_overhead_factor = float(image_overhead_factor) |
| 608 | except: |
| 609 | image_overhead_factor = 1 |
| 610 | params['image_overhead_factor'] = image_overhead_factor |
| 611 | |
| 612 | params["incompat_license"] = self._remove_redundant(self.runCommand(["getVariable", "INCOMPATIBLE_LICENSE"]) or "") |
| 613 | params["sdk_machine"] = self.runCommand(["getVariable", "SDKMACHINE"]) or self.runCommand(["getVariable", "SDK_ARCH"]) or "" |
| 614 | |
| 615 | params["image_fstypes"] = self._remove_redundant(self.runCommand(["getVariable", "IMAGE_FSTYPES"]) or "") |
| 616 | |
| 617 | params["image_types"] = self._remove_redundant(self.runCommand(["getVariable", "IMAGE_TYPES"]) or "") |
| 618 | |
| 619 | params["conf_version"] = self.runCommand(["getVariable", "CONF_VERSION"]) or "" |
| 620 | params["lconf_version"] = self.runCommand(["getVariable", "LCONF_VERSION"]) or "" |
| 621 | |
| 622 | params["runnable_image_types"] = self._remove_redundant(self.runCommand(["getVariable", "RUNNABLE_IMAGE_TYPES"]) or "") |
| 623 | params["runnable_machine_patterns"] = self._remove_redundant(self.runCommand(["getVariable", "RUNNABLE_MACHINE_PATTERNS"]) or "") |
| 624 | params["deployable_image_types"] = self._remove_redundant(self.runCommand(["getVariable", "DEPLOYABLE_IMAGE_TYPES"]) or "") |
| 625 | params["kernel_image_type"] = self.runCommand(["getVariable", "KERNEL_IMAGETYPE"]) or "" |
| 626 | params["tmpdir"] = self.runCommand(["getVariable", "TMPDIR"]) or "" |
| 627 | params["distro_version"] = self.runCommand(["getVariable", "DISTRO_VERSION"]) or "" |
| 628 | params["target_os"] = self.runCommand(["getVariable", "TARGET_OS"]) or "" |
| 629 | params["target_arch"] = self.runCommand(["getVariable", "TARGET_ARCH"]) or "" |
| 630 | params["tune_pkgarch"] = self.runCommand(["getVariable", "TUNE_PKGARCH"]) or "" |
| 631 | params["bb_version"] = self.runCommand(["getVariable", "BB_MIN_VERSION"]) or "" |
| 632 | |
| 633 | params["default_task"] = self.runCommand(["getVariable", "BB_DEFAULT_TASK"]) or "build" |
| 634 | |
| 635 | params["socks_proxy"] = self.runCommand(["getVariable", "all_proxy"]) or "" |
| 636 | params["http_proxy"] = self.runCommand(["getVariable", "http_proxy"]) or "" |
| 637 | params["ftp_proxy"] = self.runCommand(["getVariable", "ftp_proxy"]) or "" |
| 638 | params["https_proxy"] = self.runCommand(["getVariable", "https_proxy"]) or "" |
| 639 | |
| 640 | params["cvs_proxy_host"] = self.runCommand(["getVariable", "CVS_PROXY_HOST"]) or "" |
| 641 | params["cvs_proxy_port"] = self.runCommand(["getVariable", "CVS_PROXY_PORT"]) or "" |
| 642 | |
| 643 | params["image_white_pattern"] = self.runCommand(["getVariable", "BBUI_IMAGE_WHITE_PATTERN"]) or "" |
| 644 | params["image_black_pattern"] = self.runCommand(["getVariable", "BBUI_IMAGE_BLACK_PATTERN"]) or "" |
| 645 | return params |