lbkit 0.8.6__tar.gz → 0.8.8__tar.gz

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.
Files changed (69) hide show
  1. {lbkit-0.8.6/lbkit.egg-info → lbkit-0.8.8}/PKG-INFO +4 -2
  2. lbkit-0.8.8/lbkit/__init__.py +2 -0
  3. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/cli.py +6 -2
  4. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/codegen.py +2 -1
  5. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/ctype_defination.py +14 -14
  6. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/template/public.c.mako +3 -3
  7. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/component/build.py +9 -9
  8. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/component/test.py +3 -3
  9. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/config.py +30 -3
  10. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/executor.py +18 -5
  11. lbkit-0.8.8/lbkit/tasks/image_maker/make_image.py +17 -0
  12. lbkit-0.8.8/lbkit/tasks/image_maker/make_qemu_image.py +75 -0
  13. lbkit-0.8.8/lbkit/tasks/image_maker/make_rockchip_image.py +78 -0
  14. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/task.py +1 -45
  15. lbkit-0.8.8/lbkit/tasks/task_build_image.py +29 -0
  16. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/task_build_manifest.py +2 -24
  17. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/task_build_prepare.py +28 -17
  18. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/task_build_rootfs.py +116 -13
  19. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/task_download.py +15 -1
  20. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/template/conanfile.py.mako +2 -2
  21. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tools.py +8 -4
  22. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/utils/env_detector.py +1 -1
  23. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/utils/images/emmc.py +11 -6
  24. {lbkit-0.8.6 → lbkit-0.8.8/lbkit.egg-info}/PKG-INFO +4 -2
  25. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit.egg-info/SOURCES.txt +4 -1
  26. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit.egg-info/requires.txt +1 -0
  27. {lbkit-0.8.6 → lbkit-0.8.8}/setup.py +1 -1
  28. lbkit-0.8.8/test/__init__.py +0 -0
  29. lbkit-0.8.6/lbkit/__init__.py +0 -2
  30. lbkit-0.8.6/lbkit/tasks/task_build_image.py +0 -45
  31. lbkit-0.8.6/lbkit/tasks/task_test.py +0 -29
  32. {lbkit-0.8.6 → lbkit-0.8.8}/AUTHORS +0 -0
  33. {lbkit-0.8.6 → lbkit-0.8.8}/LICENSE +0 -0
  34. {lbkit-0.8.6 → lbkit-0.8.8}/MANIFEST.in +0 -0
  35. {lbkit-0.8.6 → lbkit-0.8.8}/README.md +0 -0
  36. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/build_conan_parallel.py +0 -0
  37. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/ci_robot/__init__.py +0 -0
  38. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/ci_robot/gitee.py +0 -0
  39. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/__init__.py +0 -0
  40. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/idf_interface.py +0 -0
  41. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/renderer.py +0 -0
  42. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/template/client.c.mako +0 -0
  43. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/template/client.h.mako +0 -0
  44. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/template/interface.c.mako +0 -0
  45. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/template/interface.introspect.xml.mako +0 -0
  46. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/template/public.h.mako +0 -0
  47. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/template/server.c.mako +0 -0
  48. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/codegen/template/server.h.mako +0 -0
  49. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/component/__init__.py +0 -0
  50. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/component/arg_parser.py +0 -0
  51. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/component/template/conanbase.mako +0 -0
  52. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/component/template/deploy.mako +0 -0
  53. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/errors.py +0 -0
  54. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/helper.py +0 -0
  55. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/lbkit.py +0 -0
  56. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/log.py +0 -0
  57. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/misc.py +0 -0
  58. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/__init__.py +0 -0
  59. {lbkit-0.8.6/test → lbkit-0.8.8/lbkit/tasks/image_maker}/__init__.py +0 -0
  60. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/tasks/template/rootfs.py.mako +0 -0
  61. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/utils/__init__.py +0 -0
  62. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit/utils/images/__init__.py +0 -0
  63. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit.egg-info/dependency_links.txt +0 -0
  64. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit.egg-info/entry_points.txt +0 -0
  65. {lbkit-0.8.6 → lbkit-0.8.8}/lbkit.egg-info/top_level.txt +0 -0
  66. {lbkit-0.8.6 → lbkit-0.8.8}/setup.cfg +0 -0
  67. {lbkit-0.8.6 → lbkit-0.8.8}/test/test_codegen.py +0 -0
  68. {lbkit-0.8.6 → lbkit-0.8.8}/test/test_config.py +0 -0
  69. {lbkit-0.8.6 → lbkit-0.8.8}/test/test_helper.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: lbkit
3
- Version: 0.8.6
3
+ Version: 0.8.8
4
4
  Summary: Tools provided by litebmc.com
5
5
  Home-page: https://www.litebmc.com
6
6
  Author: xuhj@litebmc.com
@@ -21,12 +21,14 @@ Requires-Dist: requests
21
21
  Requires-Dist: gitpython
22
22
  Requires-Dist: inflection
23
23
  Requires-Dist: meson>=1.4.0
24
+ Requires-Dist: psutil
24
25
  Dynamic: author
25
26
  Dynamic: author-email
26
27
  Dynamic: classifier
27
28
  Dynamic: description
28
29
  Dynamic: description-content-type
29
30
  Dynamic: home-page
31
+ Dynamic: license-file
30
32
  Dynamic: requires-dist
31
33
  Dynamic: summary
32
34
 
@@ -0,0 +1,2 @@
1
+
2
+ __version__ = '0.8.8'
@@ -79,6 +79,8 @@ class Command(object):
79
79
  """
80
80
  env = EnvDetector()
81
81
  if env.component:
82
+ os.chdir(env.component.folder)
83
+ print(os.getcwd())
82
84
  arg_parser = ArgParser.new()
83
85
  build = BuildComponent(arg_parser, sys.argv[2:])
84
86
  build.run()
@@ -101,6 +103,10 @@ class Command(object):
101
103
 
102
104
  组件DT用例执行
103
105
  """
106
+ env = EnvDetector()
107
+ if not env.component:
108
+ raise Exception("The metadata/package.yml file was not detected, not a valid litebmc component.")
109
+ os.chdir(env.component.folder)
104
110
  argv = sys.argv[2:]
105
111
  build = TestComponent(argv)
106
112
  build.run()
@@ -239,11 +245,9 @@ def main(args):
239
245
  shutil.rmtree(misc.LOG_DIR, ignore_errors=True)
240
246
  os.makedirs(misc.LOG_DIR, exist_ok=True)
241
247
  def ctrl_c_handler(_, __):
242
- print('You pressed Ctrl+C!')
243
248
  sys.exit(-3)
244
249
 
245
250
  def sigterm_handler(_, __):
246
- print('Received SIGTERM!')
247
251
  sys.exit(-4)
248
252
 
249
253
  signal.signal(signal.SIGINT, ctrl_c_handler)
@@ -67,8 +67,9 @@ history_versions = {
67
67
  "5.0": CodeGenHistory("lb_base/[>=0.8.1 <0.9.0]", "简化接口类名定义;简化枚举变量在接口间传递时的字符串定义", "0"),
68
68
  "5.1": CodeGenHistory("lb_base/[>=0.8.3 <0.9.0]", "方法和信号添加保留字段用于功能扩展,同时设置请求和响应为空标志位", "8002"),
69
69
  "5.2": CodeGenHistory("lb_base/[>=0.8.4 <0.9.0]", "支持校验数值边界、字符串正则以及数组匹配等规则", "8004"),
70
+ "5.3": CodeGenHistory("lb_base/[>=0.8.5 <0.9.0]", "支持32位操作系统", "8004"),
70
71
  }
71
- __version__=Version("5.1")
72
+ __version__=Version("5.3")
72
73
 
73
74
 
74
75
  def version_check(ver_str: str):
@@ -93,9 +93,9 @@ class IdfValidator():
93
93
  val_str = f"static const gchar *_items[] = {{"
94
94
  val_str += '"' + '", "'.join(self.matches) + '", NULL'
95
95
  else:
96
- if self.ctype in ["int16", "int32", "int64"]:
96
+ if self.ctype in ["int16", "int32", "int64", "ssize"]:
97
97
  val_str = f"static gint64 _items[] = {{"
98
- elif self.ctype in ["uint8", "uint16", "uint32", "uint64"]:
98
+ elif self.ctype in ["uint8", "uint16", "uint32", "uint64", "size"]:
99
99
  val_str = f"static guint64 _items[] = {{"
100
100
  elif self.ctype in ["double"]:
101
101
  val_str = f"static gdouble _items[] = {{"
@@ -784,17 +784,17 @@ CTYPE_OBJS = {
784
784
  ["gsize <arg_name>"],
785
785
  ["gsize *<arg_name>"],
786
786
  [],
787
- ["<arg_out> = g_variant_new_uint64(<arg_name>)"],
788
- ["<arg_in> = g_variant_get_uint64(<arg_name>)"],
789
- IntegerValidator("uint64", 0xffff_ffff_ffff_ffff, 0)
787
+ ["<arg_out> = g_variant_new_tsize(<arg_name>)"],
788
+ ["<arg_in> = g_variant_get_tsize(<arg_name>)"],
789
+ IntegerValidator("size", 0xffff_ffff_ffff_ffff, 0)
790
790
  ),
791
791
  "ssize": CTypeBase(
792
792
  ["gssize <arg_name>"],
793
793
  ["gssize *<arg_name>"],
794
794
  [],
795
- ["<arg_out> = g_variant_new_int64(<arg_name>)"],
796
- ["<arg_in> = g_variant_get_int64(<arg_name>)"],
797
- IntegerValidator("int64", 0x7fff_ffff_ffff_ffff, -(0x8000_0000_0000_0000), True)
795
+ ["<arg_out> = g_variant_new_tssize(<arg_name>)"],
796
+ ["<arg_in> = g_variant_get_tssize(<arg_name>)"],
797
+ IntegerValidator("ssize", 0x7fff_ffff_ffff_ffff, -(0x8000_0000_0000_0000), True)
798
798
  ),
799
799
  "double": CTypeBase(
800
800
  ["gdouble <arg_name>"],
@@ -921,17 +921,17 @@ CTYPE_OBJS = {
921
921
  ["gsize n_<arg_name>" ,"<const>gssize *<arg_name>"],
922
922
  ["gsize *n_<arg_name>" ,"gssize **<arg_name>"],
923
923
  ["lb_free_p((void **)&<arg_name>)"],
924
- ["<arg_out> = lb_array_int64_encode(<arg_name>, n_<arg_name>)"],
925
- ["<arg_in> = lb_array_int64_decode(<arg_name>, &n_<arg_in>)"],
926
- IntegerArrayValidator("int64",0x7fff_ffff_ffff_ffff, -(0x8000_0000_0000_0000), True)
924
+ ["<arg_out> = lb_array_ssize_encode(<arg_name>, n_<arg_name>)"],
925
+ ["<arg_in> = lb_array_ssize_decode(<arg_name>, &n_<arg_in>)"],
926
+ IntegerArrayValidator("ssize",0x7fff_ffff_ffff_ffff, -(0x8000_0000_0000_0000), True)
927
927
  ),
928
928
  "array[size]": CTypeBase(
929
929
  ["gsize n_<arg_name>" ,"<const>gsize *<arg_name>"],
930
930
  ["gsize *n_<arg_name>" ,"gsize **<arg_name>"],
931
931
  ["lb_free_p((void **)&<arg_name>)"],
932
- ["<arg_out> = lb_array_uint64_encode(<arg_name>, n_<arg_name>)"],
933
- ["<arg_in> = lb_array_uint64_decode(<arg_name>, &n_<arg_in>)"],
934
- IntegerArrayValidator("uint64", 0xffff_ffff_ffff_ffff, 0)
932
+ ["<arg_out> = lb_array_size_encode(<arg_name>, n_<arg_name>)"],
933
+ ["<arg_in> = lb_array_size_decode(<arg_name>, &n_<arg_in>)"],
934
+ IntegerArrayValidator("size", 0xffff_ffff_ffff_ffff, 0)
935
935
  ),
936
936
  "array[double]": CTypeBase(
937
937
  ["gsize n_<arg_name>" ,"<const>gdouble *<arg_name>"],
@@ -526,7 +526,7 @@ static ${name}${dictionary.key} *${name}_lookup(const ${name} *dict, ${key_decla
526
526
  }
527
527
 
528
528
  const ${name}Real *dict_real = CONTAINER_OF(dict, ${name}Real, dict);
529
- return (${name}${dictionary.key} *)g_hash_table_lookup(dict_real->_hash, GUINT_TO_POINTER((guint64)key));
529
+ return (${name}${dictionary.key} *)g_hash_table_lookup(dict_real->_hash, GUINT_TO_POINTER(key));
530
530
  }
531
531
 
532
532
  /**
@@ -547,7 +547,7 @@ static gboolean ${name}_insert(const ${name} *dict, ${key_declare}, ${name}${dic
547
547
  % if dictionary.key_type in ["string", "object_path", "signature"]:
548
548
  gboolean ret = g_hash_table_insert(dict_real->_hash, g_strdup(key), *value);
549
549
  % else:
550
- gboolean ret = g_hash_table_insert(dict_real->_hash, GUINT_TO_POINTER((guint64)key), *value);
550
+ gboolean ret = g_hash_table_insert(dict_real->_hash, GUINT_TO_POINTER(key), *value);
551
551
  % endif
552
552
  if (ret) {
553
553
  *value = NULL;
@@ -571,7 +571,7 @@ static gboolean ${name}_remove(const ${name} *dict, ${key_declare})
571
571
  }
572
572
 
573
573
  const ${name}Real *dict_real = CONTAINER_OF(dict, ${name}Real, dict);
574
- return g_hash_table_remove(dict_real->_hash, GUINT_TO_POINTER((guint64)key));
574
+ return g_hash_table_remove(dict_real->_hash, GUINT_TO_POINTER(key));
575
575
  }
576
576
 
577
577
  /**
@@ -20,7 +20,6 @@ from lbkit.codegen.codegen import Version
20
20
 
21
21
  tools = Tools("comp_build")
22
22
  log = tools.log
23
- cwd = os.getcwd()
24
23
  lb_cwd = os.path.split(os.path.realpath(__file__))[0]
25
24
 
26
25
 
@@ -52,6 +51,7 @@ class DeployComponent():
52
51
 
53
52
  class BuildComponent():
54
53
  def __init__(self, args_parser: ArgumentParser, args=None):
54
+ self.cwd = os.getcwd()
55
55
  self.deploy_success = True
56
56
  self.options = args_parser.parse_args(args)
57
57
  self.options.build_type = self.options.build_type.capitalize()
@@ -64,7 +64,7 @@ class BuildComponent():
64
64
  self.verbose = False if self.options.summary else True
65
65
  self.from_source = self.options.from_source
66
66
  # 当前组件及其依赖将被部署到rootfs目录
67
- self.rootfs_dir = os.path.join(cwd, ".temp", "rootfs")
67
+ self.rootfs_dir = os.path.join(self.cwd, ".temp", "rootfs")
68
68
  shutil.rmtree(self.rootfs_dir, ignore_errors=True)
69
69
  os.makedirs(self.rootfs_dir, exist_ok=True)
70
70
 
@@ -117,7 +117,7 @@ class BuildComponent():
117
117
  return False
118
118
 
119
119
  def gen_conaninfo(self):
120
- package_yml = os.path.join(cwd, "metadata/package.yml")
120
+ package_yml = os.path.join(self.cwd, "metadata/package.yml")
121
121
  if not os.path.isfile(package_yml):
122
122
  raise FileNotFoundError("metadata/package.yml文件不存在")
123
123
  # 验证失败时抛异常,此处不用处理,由外层处理
@@ -155,10 +155,10 @@ class BuildComponent():
155
155
  self.base_cmd += f" -o {conan}/*:{k}={v}"
156
156
 
157
157
  # 生成conan构建脚本
158
- conanfile = os.path.join(cwd, "conanbase.py")
158
+ conanfile = os.path.join(self.cwd, "conanbase.py")
159
159
  # 当git未跟踪conanfile.py时生成新的conanfile.py
160
160
  if not self._is_conanfile_tracked:
161
- conanfile = os.path.join(cwd, "conanfile.py")
161
+ conanfile = os.path.join(self.cwd, "conanfile.py")
162
162
 
163
163
  # 使用litebmc.conanfile.mako模板生成基础litebmc公共conanfile
164
164
  lookup = TemplateLookup(directories=os.path.join(lb_cwd, "template"))
@@ -210,8 +210,8 @@ class BuildComponent():
210
210
  # import sys
211
211
  # sys.exit(-1)
212
212
 
213
- lockfile = os.path.join(cwd, ".temp", "conan.lock")
214
- graphfile = os.path.join(cwd, ".temp", "graph.info")
213
+ lockfile = os.path.join(self.cwd, ".temp", "conan.lock")
214
+ graphfile = os.path.join(self.cwd, ".temp", "graph.info")
215
215
  lock_cmd = f"conan lock create . {self.base_cmd} --lockfile-out={lockfile}"
216
216
  tools.run(lock_cmd, capture_output=False)
217
217
  graph_cmd = f"conan graph info . {self.base_cmd} -f json --lockfile={lockfile}"
@@ -232,7 +232,7 @@ class BuildComponent():
232
232
 
233
233
  # 设置ROOTFS_DIR环境变量,为DT测试提供相对路径
234
234
  os.environ["ROOTFS_DIR"] = self.rootfs_dir
235
- os.chdir(cwd)
235
+ os.chdir(self.cwd)
236
236
 
237
237
  def _validate_odf_object(self, name, obj):
238
238
  properties = obj.get("properties")
@@ -276,7 +276,7 @@ class BuildComponent():
276
276
  for root, _, files in os.walk(self.rootfs_dir):
277
277
  for file in files:
278
278
  file = os.path.join(root, file)
279
- file = os.path.relpath(file, cwd)
279
+ file = os.path.relpath(file, self.cwd)
280
280
  if not file.endswith(".yaml"):
281
281
  log.debug(f"file {file} not endswith .yaml, skip validate")
282
282
  continue
@@ -12,11 +12,11 @@ from lbkit.misc import Color
12
12
 
13
13
  tool = Tools("comp_test")
14
14
  log = tool.log
15
- cwd = os.getcwd()
16
15
 
17
16
 
18
17
  class TestComponent():
19
18
  def __init__(self, args=None):
19
+ self.cwd = os.getcwd()
20
20
  self.build_parser = ArgParser.new(True)
21
21
  self.build_parser.parse_args(args) # 共享命令参数
22
22
  self.origin_args = args
@@ -95,13 +95,13 @@ class TestComponent():
95
95
  self._make_ld_library_path(build.rootfs_dir)
96
96
 
97
97
  # 为确保路径正确,切换到初始路径
98
- os.chdir(cwd)
98
+ os.chdir(self.cwd)
99
99
  # 必须存在test.py时才测试
100
100
  if not os.path.isfile("test.py"):
101
101
  log.warn("Test file(test.py) not exist, skip test")
102
102
  return 0
103
103
  # 从test.py加载LiteBmcComponentTest实例并运行用命
104
- loader = importlib.machinery.SourceFileLoader("test", os.path.join(cwd, "test.py"))
104
+ loader = importlib.machinery.SourceFileLoader("test", os.path.join(self.cwd, "test.py"))
105
105
  mod = loader.load_module()
106
106
  klass = getattr(mod, "LiteBmcComponentTest")
107
107
  if klass is None:
@@ -55,9 +55,6 @@ class Config(object):
55
55
  self.mnt_path = os.path.join(self.temp_path, "mnt_path")
56
56
  self.rootfs_img = os.path.join(self.output_path, "rootfs.img")
57
57
  # rootfs、uboot和kernel关键文件路径
58
- self.uboot_bin = None
59
- self.linux_bin = None
60
- self.rootfs_tar = None
61
58
  os.makedirs(self.temp_path, exist_ok=True)
62
59
  os.makedirs(self.tool_path, exist_ok=True)
63
60
  os.makedirs(self.output_path, exist_ok=True)
@@ -148,6 +145,36 @@ class Config(object):
148
145
  return product_cfg
149
146
  return Config.merge_cfg(global_cfg, product_cfg)
150
147
 
148
+ def _trans_dependencies_to_dict(self, deps):
149
+ out = {}
150
+ for dep in deps:
151
+ name = dep["package"]
152
+ name = name.split("/")[0]
153
+ out[name] = dep
154
+ return out
155
+
156
+ def _merge_dependencies(self, dst, src: dict[str, dict]):
157
+ for key, val in src.items():
158
+ dst[key] = val
159
+ return dst
160
+
161
+ def get_dependencies(self):
162
+ debug_cfg = self.get_manifest_config("debug_dependencies", [])
163
+ debug_dict = self._trans_dependencies_to_dict(debug_cfg)
164
+ global_cfg = self.get_manifest_config("dependencies", [])
165
+ global_dict = self._trans_dependencies_to_dict(global_cfg)
166
+ # debug_cfg优先级更高
167
+ tmp = self._merge_dependencies(global_dict, debug_dict)
168
+ key = f"products/{self.product}/dependencies"
169
+ # product_cfg优先级最高
170
+ product_cfg = self.get_manifest_config(key, [])
171
+ product_dict = self._trans_dependencies_to_dict(product_cfg)
172
+ tmp = self._merge_dependencies(tmp, product_dict)
173
+ out = []
174
+ for _, value in tmp.items():
175
+ out.append(value)
176
+ return out
177
+
151
178
  def load_manifest(self):
152
179
  """加载manifest.yml并验证schema文件"""
153
180
  template = {}
@@ -5,6 +5,7 @@ import os
5
5
  import time
6
6
  import traceback
7
7
  import sys
8
+ import psutil
8
9
 
9
10
  from multiprocessing import Process
10
11
  from multiprocessing import Manager
@@ -139,7 +140,7 @@ def task_handler(te:TaskExecutor):
139
140
  try:
140
141
  ret = te.run()
141
142
  except Exception as e:
142
- log.error(traceback.print_exc())
143
+ traceback.print_exc()
143
144
  log.error(f"Task {te.status_key} exit with exceiption: {str(e)}")
144
145
  with status_lock:
145
146
  status_dict[te.status_key] = TASK_STATUS_EXCEPT
@@ -160,6 +161,19 @@ class TaskInfo():
160
161
  self.proc = proc
161
162
 
162
163
 
164
+ def kill_process_and_children(pid):
165
+ try:
166
+ parent = psutil.Process(pid)
167
+ except psutil.NoSuchProcess:
168
+ return
169
+
170
+ children = parent.children(recursive=True)
171
+ for child in children:
172
+ child.terminate()
173
+
174
+ parent.terminate()
175
+
176
+
163
177
  def wait_tasks(tasks: dict[str, TaskInfo], alow_processes_alive=0):
164
178
  while True:
165
179
  new_results = {}
@@ -172,13 +186,12 @@ def wait_tasks(tasks: dict[str, TaskInfo], alow_processes_alive=0):
172
186
  continue
173
187
  with status_lock:
174
188
  status = status_dict.get(ti.te.status_key)
175
- if status == TASK_STATUS_EXCEPT:
189
+ if status == TASK_STATUS_EXCEPT or status == TASK_STATUS_FAILED:
176
190
  killall = True
177
191
  break
178
192
  if killall:
179
193
  for _, ti in tasks.items():
180
- if ti.proc.is_alive():
181
- ti.proc.terminate()
194
+ kill_process_and_children(ti.proc.pid)
182
195
  return None, False
183
196
  tasks = new_results
184
197
  if cnt > 0 and cnt >= alow_processes_alive:
@@ -244,7 +257,7 @@ class Executor(object):
244
257
  target = config.target
245
258
  succ = target_executor(config)
246
259
  except Exception as e:
247
- log.error(str(e))
260
+ traceback.print_exc()
248
261
  raise Exception(f"任务 {target} 执行失败")
249
262
  if succ:
250
263
  log.success(f"任务 {target} 执行成功")
@@ -0,0 +1,17 @@
1
+ """环境准备"""
2
+ import os
3
+ from lbkit.tasks.config import Config
4
+ from lbkit.tasks.task import Task
5
+
6
+
7
+ class TaskMakeImage(Task):
8
+ def available(self):
9
+ return False
10
+
11
+ def run(self):
12
+ return
13
+
14
+ if __name__ == "__main__":
15
+ config = Config()
16
+ build = TaskMakeImage(config, "test")
17
+ build.run()
@@ -0,0 +1,75 @@
1
+ """环境准备"""
2
+ import os
3
+ import tempfile
4
+ from lbkit.tasks.config import Config
5
+ from lbkit.log import Logger
6
+ from lbkit.utils.images.emmc import MakeImage as MekeEmmcImage
7
+ from lbkit.tasks.image_maker.make_image import TaskMakeImage
8
+
9
+ log = Logger("build_image")
10
+
11
+ src_cwd = os.path.split(os.path.realpath(__file__))[0]
12
+
13
+ class TaskMakeQemuImage(TaskMakeImage):
14
+ def __init__(self, config, name):
15
+ super().__init__(config, name)
16
+ self.chip_model = None
17
+ chip_model = self.config.get_product_config("chip_model")
18
+ if chip_model not in ["qemu_arm64"]:
19
+ return
20
+ self.chip_model = chip_model
21
+ self.uboot = self.config.get_product_config("flash/uboot")
22
+ self.kernel = self.config.get_product_config("flash/kernel")
23
+ self.rootfs = self.config.rootfs_img
24
+
25
+ @staticmethod
26
+ def _trans_to_blk_1m(cfg: str):
27
+ if cfg.endswith("K"):
28
+ return int(cfg[:-1]) / 1024
29
+ elif cfg.endswith("M"):
30
+ return int(cfg[:-1])
31
+ elif cfg.endswith("G"):
32
+ return int(cfg[:-1]) * 1024
33
+
34
+ def available(self):
35
+ if not self.chip_model:
36
+ return False
37
+ if self.config.get_product_config("flash/type") != "emmc":
38
+ return False
39
+ return True
40
+
41
+ def run(self):
42
+ """任务入口"""
43
+ """检查manifest文件是否满足schema格式描述"""
44
+ os.chdir(self.config.output_path)
45
+
46
+ mk = MekeEmmcImage(os.path.join(self.config.temp_path, "emmc_tmp_dir"))
47
+ rootfs_size = self.config.get_product_config("rootfs/size")
48
+ if rootfs_size:
49
+ mk.rootfs_blk_1m = self._trans_to_blk_1m(rootfs_size)
50
+ emmc_size = self.config.get_product_config("flash/size")
51
+ if emmc_size:
52
+ mk.size_1m = self._trans_to_blk_1m(emmc_size)
53
+ tmpdir = tempfile.TemporaryDirectory()
54
+ cmd = f"fuse2fs {self.rootfs} {tmpdir.name} -o fakeroot"
55
+ self.exec(cmd)
56
+ # 复制内核文件到boot/extlinux/Image
57
+ cmd = f"cp {self.kernel} {tmpdir.name}/boot/Image"
58
+ self.exec(cmd)
59
+ cmd = f"umount {tmpdir.name}"
60
+ self.exec(cmd)
61
+ mk.run(self.config.rootfs_img, "qemu.img")
62
+ cmd = 'cp /usr/share/litebmc/qemu.conf qemu.conf'
63
+ self.exec(cmd)
64
+ cmd = f'cp {self.uboot} u-boot.bin'
65
+ self.exec(cmd)
66
+ output_img = os.path.join(self.config.output_path, "litebmc_qemu.tar.gz")
67
+ cmd = f'tar -czf {output_img} -C . qemu.img u-boot.bin qemu.conf'
68
+ self.exec(cmd)
69
+ log.success(f"Create litebmc image {output_img} successfully")
70
+ return 0
71
+
72
+ if __name__ == "__main__":
73
+ config = Config()
74
+ build = TaskMakeQemuImage(config, "test")
75
+ build.run()
@@ -0,0 +1,78 @@
1
+ """环境准备"""
2
+ import os
3
+ import shutil
4
+ from lbkit.tasks.config import Config
5
+ from lbkit.tasks.task import Task
6
+ from lbkit.log import Logger
7
+
8
+ log = Logger("build_image")
9
+
10
+ src_cwd = os.path.split(os.path.realpath(__file__))[0]
11
+
12
+ class TaskMakeRockchipImage(Task):
13
+ def __init__(self, config, name):
14
+ super().__init__(config, name)
15
+ self.chip_model = None
16
+ chip_model = self.config.get_product_config("chip_model")
17
+ if chip_model not in ["rk3506"]:
18
+ return
19
+ self.chip_model = chip_model
20
+ self.uboot = self.config.get_product_config("flash/uboot")
21
+ self.kernel = self.config.get_product_config("flash/kernel")
22
+ self.loader = self.config.get_product_config("flash/loader")
23
+ self.parameter = self.config.get_product_config("flash/parameter")
24
+ self.package_file = self.config.get_product_config("flash/package-file")
25
+ self.rootfs = self.config.rootfs_img
26
+
27
+ def available(self):
28
+ if not self.chip_model:
29
+ return False
30
+ if self.config.get_product_config("flash/type") != "spi_nand":
31
+ return False
32
+ return True
33
+
34
+ def run(self):
35
+ """任务入口"""
36
+ if not self.available():
37
+ return -1
38
+ cwd = os.getcwd()
39
+ tmpdir = os.path.join(self.config.output_path, "temp_files")
40
+ if os.path.isdir(tmpdir):
41
+ shutil.rmtree(tmpdir)
42
+ os.makedirs(tmpdir)
43
+ os.chdir(tmpdir)
44
+ self.copyfile(self.uboot, os.path.basename(self.uboot))
45
+ self.copyfile(self.kernel, os.path.basename(self.kernel))
46
+ self.copyfile(self.loader, os.path.basename(self.loader))
47
+ self.copyfile(self.parameter, "parameter.txt")
48
+ self.copyfile(self.package_file, "package-file")
49
+ self.copyfile(self.rootfs, os.path.basename(self.rootfs))
50
+ with open(self.package_file) as fp:
51
+ lines = fp.readlines()
52
+ for line in lines:
53
+ line = line.strip()
54
+ if line.startswith("#"):
55
+ continue
56
+ infos = line.split("\t")
57
+ if len(infos) != 2:
58
+ raise Exception("the package-file with format error, each line of text must be in the format of `name\tfile\n`")
59
+ filename = infos[1]
60
+ if not os.path.isfile(filename):
61
+ cmd = f"dd if=/dev/zero of={filename} bs=1K count=1"
62
+ self.exec(cmd)
63
+ cmd = "rk_afptool -pack . firmware.img.raw"
64
+ self.exec(cmd, verbose=True)
65
+ cmds = [f"hexdump -s 21 -n 4 -e '4 \"%c\"' {self.loader}", "rev"]
66
+ tag = "RK" + self.pipe(cmds).decode("utf-8")
67
+ cmd = f"rk_image_maker -{tag} {self.loader} firmware.img.raw firmware.img -os_type:androidos"
68
+ self.exec(cmd, verbose=True)
69
+ cmd = f"mv firmware.img " + os.path.join(self.config.output_path, "firmware.img")
70
+ self.exec(cmd)
71
+ os.chdir(cwd)
72
+ return 0
73
+
74
+
75
+ if __name__ == "__main__":
76
+ config = Config()
77
+ build = TaskMakeRockchipImage(config, "test")
78
+ build.run()
@@ -7,7 +7,6 @@ import shutil
7
7
  from multiprocessing import Process
8
8
  from lbkit.log import Logger
9
9
  from lbkit.tools import Tools
10
- from lbkit.misc import load_yml_with_json_schema_validate, DownloadFlag
11
10
 
12
11
  from lbkit.tasks.config import Config
13
12
 
@@ -33,7 +32,7 @@ class Task(Process):
33
32
 
34
33
  def pipe(self, cmds: list[str], ignore_error=False, out_file = None, **kwargs):
35
34
  kwargs["uptrace"] = kwargs.get("uptrace", 0) + 1
36
- self.tools.pipe(cmds, ignore_error, out_file, **kwargs)
35
+ return self.tools.pipe(cmds, ignore_error, out_file, **kwargs)
37
36
 
38
37
  def exec_easy(self, cmd, ignore_error=False, **kwargs):
39
38
  kwargs["uptrace"] = kwargs.get("uptrace", 0) + 1
@@ -57,50 +56,7 @@ class Task(Process):
57
56
  """加载manifest.yml并验证schema文件"""
58
57
  return self.config.load_manifest()
59
58
 
60
- def waitfile(self, src, timeout=1):
61
- src = os.path.realpath(src)
62
- if os.path.islink(src):
63
- raise FileNotFoundError(f"Source file {src} is a symlink, copying failed")
64
- if not os.path.isfile(src):
65
- if timeout:
66
- # 如果有timeout的,可能是正在下载的文件,需要等待超时时间再检查一次
67
- time.sleep(timeout)
68
- if not os.path.isfile(src):
69
- raise FileNotFoundError(f"Source file {src} does not exist, copying failed")
70
- else:
71
- raise FileNotFoundError(f"Source file {src} does not exist, copying failed")
72
-
73
- # 检查是否由download下载器下载,如果是,需要检查是否下载完成
74
- if src.startswith(self.config.download_path):
75
- timeout_cnt = 0
76
- timeout_sec = 0
77
- while True:
78
- _, hash = DownloadFlag.read(src)
79
- if hash:
80
- filehash = self.tools.file_digest_sha256(src)
81
- if hash != filehash:
82
- DownloadFlag.clean(src)
83
- raise Exception(f"The hash of file {src} is {filehash}, not equal to {hash}")
84
- break
85
- else:
86
- time.sleep(0.1)
87
- timeout_sec += 0.1
88
- timeout_cnt += 0.1
89
- # 每10秒打印一次等等日志
90
- if timeout_sec == 10:
91
- self.log.info(f"Wait file {src} download success")
92
- timeout_sec = 0
93
- # 60秒未创建文件的,判定文件不存在,中止构建
94
- if timeout_cnt == 60 and not os.path.isfile(src):
95
- raise Exception(f"Check file {src} failed because source file does not exist")
96
- if timeout_cnt == 300:
97
- raise Exception(f"Check file {src} failed because file was not downloaded within 300 seconds")
98
-
99
59
  def copyfile(self, src, dst):
100
- try:
101
- self.waitfile(src)
102
- except Exception as e:
103
- raise Exception(f"Copy file {src} to {dst} failed because source file not ready") from e
104
60
 
105
61
  dst = os.path.realpath(dst)
106
62
  if not dst.startswith(self.config.temp_path):
@@ -0,0 +1,29 @@
1
+ """环境准备"""
2
+ import os
3
+ from lbkit.tasks.config import Config
4
+ from lbkit.tasks.task import Task
5
+ from lbkit.log import Logger
6
+ from lbkit.tasks.image_maker.make_rockchip_image import TaskMakeRockchipImage
7
+ from lbkit.tasks.image_maker.make_qemu_image import TaskMakeQemuImage
8
+
9
+ log = Logger("build_image")
10
+
11
+ src_cwd = os.path.split(os.path.realpath(__file__))[0]
12
+
13
+ class TaskClass(Task):
14
+ def run(self):
15
+ """任务入口"""
16
+ maker = TaskMakeRockchipImage(self.config, self.name)
17
+ if maker.available():
18
+ maker.run()
19
+ return 0
20
+ maker = TaskMakeQemuImage(self.config, self.name)
21
+ if maker.available():
22
+ maker.run()
23
+ return 0
24
+ return -1
25
+
26
+ if __name__ == "__main__":
27
+ config = Config()
28
+ build = TaskClass(config, "test")
29
+ build.run()