def legal_info(config_obj: Dict[str, Union[str, bool]]) -> bool: """Generate legal documentation.""" cmd = "{} BR2_DL_DIR={} legal-info".format(config_obj["make"], config_obj["dl_dir"]) board_name = config_obj["defconfig"].replace("_defconfig", "") legal_info_tarball = "{}-legal-info.tar.gz".format(board_name) legal_info_path = "{}/legal-info".format(config_obj["build_path"]) os.chdir(config_obj["build_path"]) if Files.exists("{}/images/{}-legal-info.tar.gz".format( config_obj["build_path"], board_name)): Logger.print_step("Legal info already generated.") return True Logger.print_step("Generating legal-info for {}".format( config_obj["defconfig"])) if os.system(cmd): print("ERROR: Failed to generate legal information for {}".format( config_obj["defconfig"])) if config_obj["make"] == "brmake": log = Files.to_buffer("{}/br.log".format( config_obj["build_path"]), split=True) for line in log[-100:]: print(line) return False # We dont want the sources bundled in the tarball. rmtree("{}/sources".format(legal_info_path)) rmtree("{}/host-sources".format(legal_info_path)) if os.system("tar -czf {} legal-info".format(legal_info_tarball)): return False if os.makedirs("images", exist_ok=True): return False if os.system("mv {} images/".format(legal_info_tarball)): return False return True
def apply(self) -> bool: """Apply all configs defined in env.json.""" Dirs.exists(self.buildroot_path, fail=True) Dirs.exists(self.config["output_dir"], make=True, fail=True) if not Dirs.exists( self.config["build_path"]) or self.config["apply_configs"]: cmd = "BR2_EXTERNAL={}/{} BR2_DEFCONFIG={} {} {} O={}".format( self.buildroot_path, self.config["external_trees"], self.config["defconfig_path"], self.config["make"], self.config["defconfig"], self.config["build_path"], ) os.chdir(self.buildroot_path) Logger.print_step("Applying {}".format( self.config["defconfig_path"])) if self.config["make"] == "make": Logger.print_step(cmd) if os.system(cmd): print("ERROR: Failed to apply {}".format( self.config["defconfig_path"])) return False self.fragments.apply() return True
def clean(self, force: bool = False) -> bool: """Clean all configs that have the clean boolean set to true.""" if self.config["remove"]: if Dirs.exists(self.config["build_path"]): Logger.print_step("Removing directory {}".format( self.config["build_path"])) return Dirs.remove(self.config["build_path"]) elif self.config["clean"] or force: if Dirs.exists(self.config["build_path"]): os.chdir(self.config["build_path"]) cmd = "{} clean".format(self.config["make"]) Logger.print_step("Cleaning {}".format( self.config["defconfig"])) if os.system(cmd): print("ERROR: Failed to clean {}".format( self.config["defconfig_path"])) return False os.chdir(self.buildroot_path) return True return True
def build(config_obj: Dict[str, Union[str, bool]]) -> bool: """Build all configs that have the build attribute set to true in env.json. :param Dict[str, Union[str, bool]] config_obj: An instantiated config object from the config class. :returns: True on success, False on failure. :rtype: bool """ build_package = os.environ.get("BUILD_PACKAGE", None) os.chdir(config_obj["build_path"]) Logger.print_step("Building {}".format(config_obj["defconfig"])) cmd = "{} BR2_DL_DIR={}".format(config_obj["make"], config_obj["dl_dir"]) # Check if per_package directories is set. If so, check if BR2_JLEVEL is set and divide # by the number of cores by JLEVEL. if config_obj["per_package"]: cores = multiprocessing.cpu_count() j_level = int( Buildroot.parse_defconfig( "BR2_JLEVEL", "{}/.config".format(config_obj["build_path"]), config_obj["buildroot_path"], )) if j_level: cores = max(int(cores / j_level), 1) cmd += " -Otarget -j{}".format(str(cores)) if build_package: cmd += " {}".format(build_package) if os.system(cmd): print("ERROR: Failed to build {}".format(config_obj["defconfig"])) if config_obj["make"] == "brmake": log = Files.to_buffer("{}/br.log".format( config_obj["build_path"]), split=True) for line in log[-100:]: print(line) return False return True
def run(self) -> bool: """Run all the steps.""" single_target = os.environ.get("SINGLE_TARGET", None) self._parse_env() config = Config(self.buildroot_path, self.apply_configs) if self.update: Buildroot.update(self.buildroot_path) for defconfig in self.env["configs"]: config_obj = config.parse(defconfig) if config_obj["skip"]: Logger.print_step("Skipping {}".format( config_obj["defconfig"])) continue if not config.clean(): return False if not config.apply(): return False if single_target: return self.__single_target(single_target, config) for defconfig in self.env["configs"]: config_obj = config.parse(defconfig) if not config_obj["build"] or config_obj["skip"] or self.no_build: Logger.print_step("{}: Skip build step".format( config_obj["defconfig"])) continue # Generate the legal information first, as to ensure the tarball is in the images # directory before post-image.sh is called. if config_obj["legal_info"]: if not Buildroot.legal_info(config_obj): return False if not Buildroot.build(config_obj): return False if self.clean_after_build: config.clean(force=True) return True