#!/usr/bin/env python3 # -*- coding: UTF-8 -*- # ----------------------------------------------------------------------------------------------------------- # Copyright (c) 2025 Huawei Technologies Co., Ltd. # This program is free software, you can redistribute it and/or modify it under the terms and conditions of # CANN Open Software License Agreement Version 2.0 (the "License"). # Please refer to the License for details. You may not use this file except in compliance with the License. # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. # ----------------------------------------------------------------------------------------------------------- import os import shutil import subprocess from argparse import Namespace from collections.abc import Callable from itertools import chain from subprocess import PIPE, STDOUT from typing import NamedTuple from .utils.comm_log import CommLog from .utils.pkg_utils import CompressError class PackageName: """包名。""" def __init__(self, package_attr, args: Namespace, version: str): self.product_name = package_attr.get("product_name") self.chip_name = args.chip_name or package_attr.get("chip_name") self.suffix = args.suffix or package_attr.get("suffix") self.func_name = get_func_name(args.func_name, package_attr) self.chip_plat = package_attr.get("chip_plat") self.deploy_type = package_attr.get("deploy_type") self.version = version.lower() self.not_in_name_list = args.not_in_name.split(",") self.os_arch = args.os_arch self.package_suffix = args.package_suffix self.ext_name = args.ext_name if args.pkg_name_style == "underline": self.name_sep = "_" else: self.name_sep = "-" def get_attribute(self, name: str) -> str | None: """获取属性。""" if name in self.not_in_name_list: return None return getattr(self, name) def getvalue(self) -> str: product_name = self.get_attribute("product_name") chip_name = self.get_attribute("chip_name") func_name = self.get_attribute("func_name") version = self.get_attribute("version") os_arch = self.get_attribute("os_arch") chip_plat = self.get_attribute("chip_plat") deploy_type = self.get_attribute("deploy_type") ext_name = self.get_attribute("ext_name") package_suffix = "debug" if self.package_suffix == "debug" else None region1 = "-".join(filter(None, [product_name, remove_ascend(chip_name), func_name])) region2 = ".".join(filter(None, [version])) region3 = "-".join(filter(None, [os_arch, chip_plat, deploy_type, package_suffix, ext_name])) package_name = "_".join(filter(None, [region1, region2, region3])) return f"{package_name}.{self.suffix}" class MakeselfPkgParams(NamedTuple): """run包打包参数。""" package_name: str comments: str makeself_tool: str | None = None makeself_header: str | None = None help_info: str | None = None source_target: str | None = None install_script: str | None = None independent_pkg: bool | None = False cleanup: str | None = None def remove_ascend(text): if text is None: return None text_lower = text.lower() if text_lower == "ascend910_93": return "A3" if "ascend" in text_lower: return text_lower.replace("ascend", "") return text_lower def get_func_name(func_name: str, package_attr) -> str: """获取包func_name。""" return func_name or package_attr.get("func_name") def get_compress_tool() -> str: tools = ["pigz", "gzip", "bzip2", "xz"] for tool in tools: path = shutil.which(tool) if path: return "--" + tool CommLog.cilog_error( "The system does not come with a compression tool pre-installed." "Please ensure at least one of the following compression tools is available: %s", tools, ) return "" def get_compress_format() -> str: tar_format = "gnu" path = shutil.which("bsdtar") if path: tar_format = "ustar" return tar_format def compose_makeself_command(params: MakeselfPkgParams) -> str: """组装makeself包打包命令。""" def get_cleanup_commands() -> list[str]: if params.cleanup: return ["--cleanup", params.cleanup] return [] independent_pkg = params.independent_pkg compress_tool = get_compress_tool() tar_format = get_compress_format() if independent_pkg: commands = chain( [ "TMPDIR=$pwd", params.makeself_tool, "--header", params.makeself_header, "--help-header", params.help_info, compress_tool, "--complevel", "4", "--nomd5", "--sha256", "--nooverwrite", "--chown", "--tar-format", tar_format, "--tar-extra", "--numeric-owner", "--tar-quietly", ], get_cleanup_commands(), [params.source_target, params.package_name, params.comments, params.install_script], ) else: commands = chain( [ compress_tool, "--complevel", "4", "--nomd5", "--sha256", "--nooverwrite", "--chown", "--tar-format", tar_format, "--tar-extra", "--numeric-owner", "--tar-quietly", ], get_cleanup_commands(), [params.package_name, params.comments], ) command = " ".join(commands) return command def create_makeself_pkg_params_factory( source_target: str, package_name: str, comments: str ) -> Callable[[str, dict, bool], MakeselfPkgParams]: """创建Makeself打包参数工厂。""" def create_makeself_pkg_params(makeself_dir: str, package_attr: dict, independent_pkg=False) -> MakeselfPkgParams: """创建Makeself打包参数。""" cleanup = package_attr.get("cleanup") if independent_pkg: install_script = str(package_attr.get("install_script")) help_info = str(package_attr.get("help")) makeself_tool = os.path.join(makeself_dir, "makeself.sh") makeself_header = os.path.join(makeself_dir, "makeself-header.sh") params = MakeselfPkgParams( package_name=package_name, comments=comments, makeself_tool=makeself_tool, makeself_header=makeself_header, help_info=help_info, source_target=source_target, install_script=install_script, independent_pkg=independent_pkg, cleanup=cleanup, ) else: params = MakeselfPkgParams( package_name=package_name, comments=comments, cleanup=cleanup, ) return params return create_makeself_pkg_params def create_run_package_command(params: MakeselfPkgParams) -> tuple[str | None, str | None]: """ 功能描述: 组装打run包命令 返回值: command """ return compose_makeself_command(params), None def exec_pack_cmd(delivery_dir: str, pack_cmd: str, package_name: str) -> str: """执行打包命令""" if delivery_dir: cmd = f"cd {delivery_dir} && {pack_cmd}" else: cmd = pack_cmd CommLog.cilog_info("package cmd:%s", cmd) result = subprocess.run(cmd, shell=True, check=False, stdout=PIPE, stderr=STDOUT) output = result.stdout.decode() if result.returncode != 0: CommLog.cilog_error(__file__, "compress package(%s) failed! %s.", package_name, output) raise CompressError(package_name) return package_name