openubmc-bingo 0.5.275__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of openubmc-bingo might be problematic. Click here for more details.

Files changed (56) hide show
  1. bmcgo/__init__.py +1 -1
  2. bmcgo/bmcgo_config.py +22 -10
  3. bmcgo/cli/cli.py +86 -39
  4. bmcgo/cli/config.conan2.yaml +9 -0
  5. bmcgo/codegen/lua/codegen.py +1 -1
  6. bmcgo/codegen/lua/script/gen_intf_rpc_json.py +15 -14
  7. bmcgo/component/analysis/analysis.py +8 -8
  8. bmcgo/component/analysis/intf_validation.py +23 -12
  9. bmcgo/component/build.py +76 -14
  10. bmcgo/component/component_dt_version_parse.py +3 -2
  11. bmcgo/component/component_helper.py +43 -15
  12. bmcgo/component/coverage/incremental_cov.py +2 -2
  13. bmcgo/component/deploy.py +68 -14
  14. bmcgo/component/gen.py +1 -1
  15. bmcgo/component/package_info.py +128 -38
  16. bmcgo/component/template_v2/conanbase.py.mako +352 -0
  17. bmcgo/component/template_v2/conanfile.deploy.py.mako +26 -0
  18. bmcgo/component/test.py +53 -20
  19. bmcgo/frame.py +7 -3
  20. bmcgo/functional/analysis.py +3 -2
  21. bmcgo/functional/check.py +10 -6
  22. bmcgo/functional/conan_index_build.py +79 -20
  23. bmcgo/functional/csr_build.py +11 -3
  24. bmcgo/functional/diff.py +1 -1
  25. bmcgo/functional/fetch.py +1 -1
  26. bmcgo/functional/full_component.py +32 -24
  27. bmcgo/functional/git_history.py +220 -0
  28. bmcgo/functional/maintain.py +55 -12
  29. bmcgo/functional/new.py +1 -1
  30. bmcgo/functional/schema_valid.py +2 -2
  31. bmcgo/logger.py +2 -3
  32. bmcgo/misc.py +130 -9
  33. bmcgo/tasks/conan/__init__.py +10 -0
  34. bmcgo/tasks/conan/conanfile.py +45 -0
  35. bmcgo/tasks/task.py +27 -4
  36. bmcgo/tasks/task_build_conan.py +433 -65
  37. bmcgo/tasks/task_buildgppbin.py +8 -2
  38. bmcgo/tasks/task_download_buildtools.py +76 -0
  39. bmcgo/tasks/task_download_dependency.py +1 -0
  40. bmcgo/tasks/task_hpm_envir_prepare.py +1 -1
  41. bmcgo/utils/build_conans.py +231 -0
  42. bmcgo/utils/component_post.py +6 -4
  43. bmcgo/utils/component_version_check.py +10 -5
  44. bmcgo/utils/config.py +76 -40
  45. bmcgo/utils/fetch_component_code.py +44 -25
  46. bmcgo/utils/installations/install_plans/qemu.yml +6 -0
  47. bmcgo/utils/installations/install_plans/studio.yml +6 -0
  48. bmcgo/utils/installations/install_workflow.py +28 -2
  49. bmcgo/utils/merge_csr.py +124 -0
  50. bmcgo/utils/tools.py +239 -117
  51. bmcgo/worker.py +2 -2
  52. {openubmc_bingo-0.5.275.dist-info → openubmc_bingo-0.6.0.dist-info}/METADATA +4 -2
  53. {openubmc_bingo-0.5.275.dist-info → openubmc_bingo-0.6.0.dist-info}/RECORD +56 -46
  54. {openubmc_bingo-0.5.275.dist-info → openubmc_bingo-0.6.0.dist-info}/WHEEL +0 -0
  55. {openubmc_bingo-0.5.275.dist-info → openubmc_bingo-0.6.0.dist-info}/entry_points.txt +0 -0
  56. {openubmc_bingo-0.5.275.dist-info → openubmc_bingo-0.6.0.dist-info}/top_level.txt +0 -0
@@ -48,8 +48,14 @@ class TaskClass(Task):
48
48
  raise errors.BmcGoException("获取 manifest.yml 中 gpp/pkg_headers 配置失败, 退出码: -1")
49
49
  else:
50
50
  files = []
51
- files.append({"file": "/usr/local/bin/hpm_header.config", "dst": "hpm_header.config"})
52
- files.append({"file": "/usr/local/bin/emmc_uboot_header.config", "dst": "emmc_uboot_header.config"})
51
+ src = "/usr/share/bingo/hpm_header.config"
52
+ if not os.path.isfile(src):
53
+ src = "/usr/local/bin/hpm_header.config"
54
+ files.append({"file": src, "dst": "hpm_header.config"})
55
+ src = "/usr/share/bingo/emmc_uboot_header.config"
56
+ if not os.path.isfile(src):
57
+ src = "/usr/local/bin/emmc_uboot_header.config"
58
+ files.append({"file": src, "dst": "emmc_uboot_header.config"})
53
59
 
54
60
  self.copy_manifest_files(files)
55
61
 
@@ -15,7 +15,10 @@
15
15
  修改记录:2021-10-11 创建
16
16
  '''
17
17
  import os
18
+ import tempfile
18
19
  import shutil
20
+ from pathlib import Path
21
+ from urllib.parse import urlparse
19
22
 
20
23
  from bmcgo.tasks.task import Task
21
24
  from bmcgo.tasks.misc import BUILD_TOOLS_SHA256_PATH
@@ -72,8 +75,81 @@ class DownloadDefaultBuildtools(Task):
72
75
  self.run_command(f"cp -rf {self.config.cross_compile_install_path}/{self.config.cross_prefix}/lib64/" +
73
76
  f" {libstdcpp_install_path}")
74
77
  self.run_command("cp -af {} {}".format(self.buildtools_new_sha256, BUILD_TOOLS_SHA256_PATH), sudo=True)
78
+ self.run_command("chmod a+r {}".format(BUILD_TOOLS_SHA256_PATH), sudo=True)
79
+
80
+ def download_sdk(self):
81
+ downloads = self.get_manufacture_config("sdk/downloads")
82
+ if downloads is None:
83
+ self.log.warning("请在 manifest.yml 配置 sdk 字段或更新 manifest 仓库")
84
+ return
85
+
86
+ download_path = Path.home() / "downloads"
87
+ download_path.mkdir(exist_ok=True, parents=True)
88
+
89
+ for item in downloads:
90
+ self.log.info(f"配置 {item['name']}...")
91
+
92
+ curr_file_name = Path(urlparse(item['url']).path).name
93
+ curr_file = download_path / curr_file_name
94
+ curr_file_path = curr_file.as_posix()
95
+
96
+ need_download = True
97
+ if curr_file.exists():
98
+ curr_pkg_sha256 = self.tools.sha256sum(curr_file_path)
99
+ if curr_pkg_sha256 == item['sha256']:
100
+ self.log.info(f"已下载 {item["name"]}, 跳过.")
101
+ need_download = False
102
+
103
+ if need_download:
104
+ with tempfile.TemporaryDirectory() as tmp:
105
+ self.log.info(f"开始下载 {item['url']}...")
106
+ download_pkg_path = os.path.join(tmp, curr_file_name)
107
+ self.tools.download_file(item['url'], download_pkg_path)
108
+ downloaded_sha256 = self.tools.sha256sum(download_pkg_path)
109
+
110
+ if item['sha256'] != downloaded_sha256:
111
+ raise RuntimeError(f"manifest.yml /sdk/downloads/{item['name']} sha256 内容和下载包体不符,请检查配置!")
112
+
113
+ shutil.move(download_pkg_path, curr_file_path)
114
+
115
+ if hasattr(self, f"install_{item['name']}"):
116
+ getattr(self, f"install_{item['name']}")(curr_file_path)
117
+
118
+ self.log.info(f"配置 {item['name']} 完成!")
119
+
120
+ def install_bmc_sdk(self, zip_path):
121
+ with tempfile.TemporaryDirectory() as tmp:
122
+ self.log.info("安装 bmc_sdk")
123
+ home_path = Path.home().as_posix()
124
+ real_path = zip_path
125
+
126
+ self.log.debug(f"解压 {real_path} 到 {tmp}")
127
+ self.run_command(f"unzip {real_path} -d {tmp}")
128
+
129
+ rtos_compiler_path = Path.home() / "rtos_compiler"
130
+ if rtos_compiler_path.exists():
131
+ shutil.rmtree(rtos_compiler_path)
132
+
133
+ sdk_path = Path.home() / "sdk"
134
+ if sdk_path.exists():
135
+ shutil.rmtree(sdk_path)
136
+
137
+ self.log.debug(f"move {tmp}/rtos_compiler -> {home_path}")
138
+ self.run_command(f"mv {tmp}/rtos_compiler/ {home_path}")
139
+ self.log.debug(f"move {tmp}/sdk -> {home_path}")
140
+ self.run_command(f"mv {tmp}/sdk/ {home_path}")
141
+ self.log.debug(f"move {tmp}/lua-format -> /usr/bin")
142
+ self.run_command(f"chmod +x {tmp}/lua-format")
143
+ self.run_command(f"mv -f {tmp}/lua-format /usr/bin/", sudo=True)
144
+
145
+ self.log.debug(f"copy {tmp}/hpm_tools/. -> {home_path}")
146
+ self.run_command(f"chmod -R +x {tmp}/hpm_tools")
147
+ self.run_command(f"cp -rf {tmp}/hpm_tools/. /usr/local/bin/", sudo=True)
148
+
149
+ self.log.info(f"安装 bmc_sdk 完成!")
75
150
 
76
151
  def run(self):
152
+ self.download_sdk()
77
153
  self.download_tools()
78
154
  self.info("下载依赖工具结束")
79
155
 
@@ -64,6 +64,7 @@ class TaskClass(Task):
64
64
  self.run_command(f"chown {user_group} {SDK_PATH} -R", sudo=True)
65
65
  self.run_command(f"ln -s {SDK_PATH} {old_sdk_dir}", sudo=True)
66
66
  self.run_command("cp -af {} {}".format(self.sdk_new_sha256, SDK_SHA256_PATH), sudo=True)
67
+ self.run_command("chmod a+r {}".format(SDK_SHA256_PATH), sudo=True)
67
68
 
68
69
  def run(self):
69
70
  self.download_dependency()
@@ -71,7 +71,7 @@ class TaskClass(Task):
71
71
 
72
72
  def prepare_hpm(self):
73
73
  hpm_build_dir = self.config.hpm_build_dir
74
- hpm_build_dir_src = f"/usr/share/bmcgo/ipmcimage"
74
+ hpm_build_dir_src = f"/usr/share/bingo/ipmcimage"
75
75
  self.tools.copy_all(hpm_build_dir_src, hpm_build_dir)
76
76
 
77
77
  self.run_command(f"cp {self.config.board_path}/update_ext4.cfg {hpm_build_dir}/update.cfg")
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env python
2
+ # coding=utf-8
3
+ # Copyright (c) 2025 Huawei Technologies Co., Ltd.
4
+ # openUBMC is licensed under Mulan PSL v2.
5
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
6
+ # You may obtain a copy of Mulan PSL v2 at:
7
+ # http://license.coscl.org.cn/MulanPSL2
8
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11
+ # See the Mulan PSL v2 for more details.
12
+ import os
13
+ import stat
14
+ import subprocess
15
+ import shlex
16
+ import time
17
+ import json
18
+ import tempfile
19
+ from queue import Queue
20
+ from threading import Thread
21
+ from bmcgo.logger import Logger
22
+ from bmcgo import errors
23
+ from bmcgo.utils.tools import Tools
24
+
25
+ tools = Tools("build_parallel")
26
+ log = tools.log
27
+
28
+
29
+ class GraphNode():
30
+ def __init__(self, node):
31
+ self.node = node
32
+ self.host_packages: dict[str, GraphNode] = {}
33
+ self.build_packages: dict[str, GraphNode] = {}
34
+ self.ref = node.get("ref")
35
+ self.name = self.ref.split("/")[0]
36
+ self.context = node.get("context")
37
+ self.pkg = self.ref.split("#")[0] + "-" + self.context
38
+ self.is_host = self.context == "host"
39
+ self.building = False
40
+ binary = node.get("binary")
41
+ self.binary_exist = (binary in ["Cache"])
42
+ self.builded = False
43
+
44
+ @property
45
+ def package_options(self):
46
+ return self.node.get("options", {})
47
+
48
+ @property
49
+ def package_setting(self):
50
+ return self.node.get("settings", {})
51
+
52
+ @property
53
+ def default_options(self):
54
+ return self.node.get("default_options", {})
55
+
56
+ def append_host_package(self, dep):
57
+ self.host_packages[dep.pkg] = dep
58
+
59
+ def append_build_package(self, dep):
60
+ self.build_packages[dep.pkg] = dep
61
+
62
+
63
+ class BuildConans(object):
64
+ def __init__(self, graphinfo, lockfile, conan_args, force_build, log_dir):
65
+ self.tools = Tools()
66
+ self.queue = Queue()
67
+ self.graphinfo = os.path.realpath(graphinfo)
68
+ if not os.path.isfile(graphinfo):
69
+ raise errors.BmcGoException(f"graph file {graphinfo} not exist")
70
+ self.lockfile = os.path.realpath(lockfile)
71
+ self.cmd = ""
72
+ args = conan_args.split()
73
+ skip = False
74
+ for arg in args:
75
+ if skip:
76
+ skip = False
77
+ continue
78
+ if arg in ["--user", "--channel", "--version", "--name"]:
79
+ skip = True
80
+ continue
81
+ self.cmd += f"{arg} "
82
+ self.exception = None
83
+ self.force_build = force_build
84
+ self.log_dir = log_dir
85
+ if not os.path.isdir(log_dir):
86
+ os.makedirs(log_dir)
87
+
88
+ def build_task(self, node: GraphNode, options):
89
+ for name, value in node.package_setting.items():
90
+ options += f" -s {name}={value}"
91
+
92
+ cmd = f"conan install --requires={node.ref} {self.cmd} {options}"
93
+ cmd += f" --build=\"{node.name}/*\" --build=missing -f json --lockfile={self.lockfile}"
94
+ try:
95
+ logfile = f"{self.log_dir}/conan_build_{node.name}.log"
96
+ log.debug(f">>>> {cmd}")
97
+ log.info(f">>>> build {node.ref} start, logfile: {logfile}")
98
+ with os.fdopen(os.open(logfile, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), "a+") as f:
99
+ real_cmd = shlex.split(cmd)
100
+ pipe = subprocess.Popen(real_cmd, stdout=f, stderr=f)
101
+ start_time = time.time()
102
+ while True:
103
+ if pipe.poll() is not None:
104
+ break
105
+ # 1800秒超时
106
+ if time.time() - start_time > 1800:
107
+ pipe.kill()
108
+ raise errors.BmcGoException(f"================== {node.name} 构建超时 ==================")
109
+ time.sleep(1)
110
+ if pipe.returncode != 0:
111
+ log.error(f"================== {node.name} 构建失败日志起始位置 ==================")
112
+ f.seek(0)
113
+ conan_log = f.read()
114
+ log.error(conan_log)
115
+ log.error(f"================== {node.name} 构建失败日志结束位置 ==================")
116
+ raise errors.BmcGoException(f"================== {node.name} 构建失败 ==================")
117
+ log.success(f"<<<< build {node.ref} finished")
118
+ except Exception as e:
119
+ self.exception = e
120
+ self.queue.put(node)
121
+
122
+ def build(self):
123
+ cwd = os.getcwd()
124
+ tmp = tempfile.TemporaryDirectory()
125
+ os.chdir(tmp.name)
126
+ self._build()
127
+ os.chdir(cwd)
128
+
129
+ def _build(self):
130
+ with open(self.graphinfo, "r") as fp:
131
+ grapth = json.load(fp)
132
+ nodes = grapth.get("graph", {}).get("nodes", {})
133
+ dependencies: dict[str, GraphNode] = {}
134
+
135
+ build_tasks = {}
136
+ for refid, node in nodes.items():
137
+ if refid == "0":
138
+ continue
139
+ cp = GraphNode(node)
140
+ dependencies[cp.pkg] = cp
141
+ build_tasks[cp.name] = False
142
+ for refid, node in nodes.items():
143
+ if refid == "0":
144
+ continue
145
+ ref = node.get("ref")
146
+ context = node.get("context")
147
+ cp = dependencies[ref.split("#")[0] + "-" + context]
148
+ host_packages = node.get("dependencies", {})
149
+ for _, dep in host_packages.items():
150
+ dep_ref = dep.get("ref")
151
+ build = dep.get("build")
152
+ if build:
153
+ build_dep = dependencies[dep_ref + "-build"]
154
+ cp.append_build_package(build_dep)
155
+ # 存在同名host组件时,将build组件作为host的依赖,避免并发构建
156
+ host_dep = dependencies.get(dep_ref + "-host")
157
+ if host_dep:
158
+ host_dep.append_build_package(build_dep)
159
+ else:
160
+ host_dep = dependencies[dep_ref + "-host"]
161
+ cp.append_host_package(host_dep)
162
+ options = ""
163
+ for _, cp in dependencies.items():
164
+ # 跳过build包
165
+ if not cp.is_host:
166
+ continue
167
+ for name, value in cp.package_options.items():
168
+ if value is None:
169
+ continue
170
+ def_val = cp.default_options.get(name)
171
+ if name == "enable_luajit":
172
+ conan_name = "*"
173
+ else:
174
+ conan_name = cp.pkg.split("@")[0]
175
+ option = ""
176
+ if isinstance(def_val, bool):
177
+ if def_val and "False" == value:
178
+ option = f" -o {conan_name}:{name}={value}"
179
+ elif not def_val and "True" == value:
180
+ option = f" -o {conan_name}:{name}={value}"
181
+ elif def_val != value:
182
+ option = f" -o {conan_name}:{name}={value}"
183
+ if option not in options:
184
+ options += option
185
+ tasks_cnt = 0
186
+ while True:
187
+ for _, dep in dependencies.items():
188
+ if tasks_cnt >= 4:
189
+ break
190
+ # 如果是构建工具,不参与构建
191
+ if not dep.is_host:
192
+ continue
193
+ # 如果还有依赖未构建完成,不参与构建
194
+ if len(dep.host_packages) != 0:
195
+ continue
196
+ # 相同名称的组件正在构建时不启动新的构建
197
+ if build_tasks.get(dep.name):
198
+ continue
199
+ if dep.builded:
200
+ continue
201
+ if not dep.binary_exist or self.force_build:
202
+ # 当依赖的构建工具存在正在构建的组件时不能构建
203
+ skip_build = False
204
+ for _, build_dep in dep.build_packages.items():
205
+ # 正在构建且未构建出制品时
206
+ if build_dep.building and not build_dep.builded:
207
+ skip_build = True
208
+ break
209
+ if skip_build:
210
+ continue
211
+ # 启动构建前将其依赖的构建工具置为正在构建
212
+ for _, build_dep in dep.build_packages.items():
213
+ build_dep.building = True
214
+ tasks_cnt += 1
215
+ thread = Thread(target=self.build_task, args=(dep, options,))
216
+ thread.start()
217
+ build_tasks[dep.name] = True
218
+ if not tasks_cnt:
219
+ return
220
+ dep = self.queue.get()
221
+ if not dep or self.exception:
222
+ raise self.exception
223
+ dep.builded = True
224
+ build_tasks[dep.name] = False
225
+ tasks_cnt -= 1
226
+ for _, sub_cp in dependencies.items():
227
+ if sub_cp.host_packages.get(dep.pkg):
228
+ sub_cp.host_packages.pop(dep.pkg)
229
+ # 构建完成后,组件的构建依赖工具一定构建完成且制品存在
230
+ for _, build_dep in dep.build_packages.items():
231
+ build_dep.builded = True
@@ -20,7 +20,6 @@ import importlib
20
20
  import sys
21
21
  from inspect import getmembers, isfunction
22
22
 
23
- from conans.model.profile import Profile
24
23
  from bmcgo.utils.config import Config
25
24
  from bmcgo.utils.tools import Tools
26
25
  from bmcgo.logger import Logger
@@ -29,9 +28,12 @@ log = Logger("component_post")
29
28
 
30
29
 
31
30
  class ComponentPost():
32
- def __init__(self, config: Config, component_path, profile: Profile):
33
- sys.path.insert(0, os.path.dirname(component_path))
34
- cust_py = importlib.import_module(f"{os.path.basename(component_path)}.include.customization", "customization")
31
+ def __init__(self, config: Config, component_path, profile):
32
+ dir_path = os.path.dirname(component_path)
33
+ if dir_path not in sys.path:
34
+ sys.path.append(dir_path)
35
+ cust_py = importlib.import_module(f"{os.path.basename(component_path)}.include.customization",
36
+ "customization")
35
37
  self.cust_cls = getattr(cust_py, "Customization")
36
38
  self.config = config
37
39
  self.component_path = component_path
@@ -31,7 +31,7 @@ class ComponentVersionCheck:
31
31
  conan 目录的 manifest.yml 文件是由单板目录下的 manifest.yml 自动生成的
32
32
  """
33
33
 
34
- def __init__(self, manifest_yml: str, ibmc_lock: str):
34
+ def __init__(self, manifest_yml: str, ibmc_lock: str, community_name: str):
35
35
  """读取 manifest.yml(conan目录) 文件与 openubmc.lock 文件
36
36
 
37
37
  Args:
@@ -42,6 +42,7 @@ class ComponentVersionCheck:
42
42
  self.manifest = yaml.safe_load(manifest_fp)
43
43
  with open(ibmc_lock, "r") as ibmc_lock_fp:
44
44
  self.ibmc_lock = json.load(ibmc_lock_fp)
45
+ self.community_name = community_name
45
46
 
46
47
  def generate_manifest_dict(self) -> dict:
47
48
  """根据 manifest.yml(conan目录) 配置生成 组件名: 组件配置 的字典
@@ -59,10 +60,14 @@ class ComponentVersionCheck:
59
60
  Returns:
60
61
  dict: 返回 组件名: 组件配置 的字典
61
62
  """
62
- component_list = self.ibmc_lock["graph_lock"]["nodes"]
63
- ibmc_lock_dict = {x["ref"].split('/')[0]: x["ref"].split('@')[0]
64
- for x in [component_conf for _, component_conf in component_list.items()]}
65
- ibmc_lock_dict.pop("openubmc")
63
+ if misc.conan_v1():
64
+ component_list = self.ibmc_lock["graph_lock"]["nodes"]
65
+ ibmc_lock_dict = {x["ref"].split('/')[0]: x["ref"].split('@')[0]
66
+ for x in [component_conf for _, component_conf in component_list.items()]}
67
+ ibmc_lock_dict.pop("openubmc")
68
+ else:
69
+ component_list = self.ibmc_lock["requires"]
70
+ ibmc_lock_dict = {x.split('/')[0]: x.split('@')[0] for x in component_list}
66
71
  return ibmc_lock_dict
67
72
 
68
73
  def run(self):