lbkit 0.9.4__tar.gz → 0.9.6__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.
- {lbkit-0.9.4/lbkit.egg-info → lbkit-0.9.6}/PKG-INFO +2 -1
- lbkit-0.9.6/lbkit/__init__.py +2 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/build_conan_parallel.py +6 -5
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/cli.py +6 -17
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/codegen.py +3 -10
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/idf_interface.py +8 -15
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/template/public.c.mako +2 -2
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/component/arg_parser.py +2 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/component/build.py +96 -49
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/component/template/conanbase.mako +23 -7
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/component/test.py +12 -11
- lbkit-0.9.6/lbkit/log.py +141 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/misc.py +2 -1
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/config.py +1 -1
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/executor.py +13 -2
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/image_maker/make_qemu_image.py +1 -4
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/image_maker/make_rockchip_image.py +0 -3
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/task.py +1 -2
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/task_build_image.py +0 -3
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/task_build_manifest.py +6 -6
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/task_build_prepare.py +1 -5
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/task_build_rootfs.py +10 -13
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/task_download.py +1 -4
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tools.py +111 -42
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/ukr/build.py +9 -9
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/utils/env_detector.py +1 -1
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/utils/images/emmc.py +1 -1
- {lbkit-0.9.4 → lbkit-0.9.6/lbkit.egg-info}/PKG-INFO +2 -1
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit.egg-info/SOURCES.txt +0 -1
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit.egg-info/requires.txt +1 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/setup.py +1 -1
- {lbkit-0.9.4 → lbkit-0.9.6}/test/test_codegen.py +4 -4
- lbkit-0.9.4/lbkit/__init__.py +0 -2
- lbkit-0.9.4/lbkit/ci_robot/gitee.py +0 -248
- lbkit-0.9.4/lbkit/log.py +0 -95
- {lbkit-0.9.4 → lbkit-0.9.6}/AUTHORS +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/LICENSE +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/MANIFEST.in +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/README.md +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/ci_robot/__init__.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/__init__.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/ctype_defination.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/renderer.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/template/client.c.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/template/client.h.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/template/interface.c.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/template/interface.introspect.xml.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/template/public.h.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/template/server.c.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/codegen/template/server.h.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/component/__init__.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/component/template/deploy.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/errors.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/helper.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/lbkit.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/__init__.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/image_maker/__init__.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/image_maker/make_image.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/template/conanfile.py.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/tasks/template/rootfs.py.mako +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/ukr/__init__.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/utils/__init__.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit/utils/images/__init__.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit.egg-info/dependency_links.txt +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit.egg-info/entry_points.txt +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/lbkit.egg-info/top_level.txt +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/setup.cfg +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/test/__init__.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/test/test_config.py +0 -0
- {lbkit-0.9.4 → lbkit-0.9.6}/test/test_helper.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lbkit
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.6
|
|
4
4
|
Summary: Tools provided by litebmc.com
|
|
5
5
|
Home-page: https://www.litebmc.com
|
|
6
6
|
Author: xuhj@litebmc.com
|
|
@@ -22,6 +22,7 @@ Requires-Dist: gitpython
|
|
|
22
22
|
Requires-Dist: inflection
|
|
23
23
|
Requires-Dist: meson>=1.4.0
|
|
24
24
|
Requires-Dist: psutil
|
|
25
|
+
Requires-Dist: loguru
|
|
25
26
|
Dynamic: author
|
|
26
27
|
Dynamic: author-email
|
|
27
28
|
Dynamic: classifier
|
|
@@ -8,19 +8,20 @@ from lbkit import misc
|
|
|
8
8
|
from lbkit.tools import Tools
|
|
9
9
|
from lbkit.misc import Color
|
|
10
10
|
|
|
11
|
-
tools = Tools(
|
|
12
|
-
log =
|
|
11
|
+
tools = Tools()
|
|
12
|
+
log = tools.log
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class BuildConanParallel(object):
|
|
16
|
-
def __init__(self, orderinfo, remote):
|
|
16
|
+
def __init__(self, orderinfo, lockfile, remote):
|
|
17
17
|
self.orderinfo = orderinfo
|
|
18
18
|
self.remote = remote
|
|
19
|
+
self.lockfile = lockfile
|
|
19
20
|
|
|
20
21
|
def _build_package(self, logfile, build_args, public_args):
|
|
21
|
-
cmd = f"conan install {build_args} {public_args}"
|
|
22
|
+
cmd = f"conan install {build_args} {public_args} --lockfile={self.lockfile} --lockfile-partial"
|
|
22
23
|
log.info("{}build start: '{}".format(Color.GREEN, Color.RESET_ALL) + cmd + ' log file: ' + logfile)
|
|
23
|
-
tools.exec(cmd,
|
|
24
|
+
tools.exec(cmd, log_name=logfile, echo_cmd=False)
|
|
24
25
|
log.info("{}build finished: '{}".format(Color.GREEN, Color.RESET_ALL) + cmd + ' log file: ' + logfile)
|
|
25
26
|
|
|
26
27
|
def _build(self):
|
|
@@ -3,7 +3,6 @@ import inspect
|
|
|
3
3
|
import os
|
|
4
4
|
import signal
|
|
5
5
|
import sys
|
|
6
|
-
import shutil
|
|
7
6
|
import argparse
|
|
8
7
|
import traceback
|
|
9
8
|
from lbkit import __version__ as client_version
|
|
@@ -12,14 +11,13 @@ from lbkit.component.build import BuildComponent
|
|
|
12
11
|
from lbkit.component.test import TestComponent
|
|
13
12
|
from lbkit.tasks.executor import Executor
|
|
14
13
|
from lbkit.component.arg_parser import ArgParser
|
|
15
|
-
from lbkit.ci_robot.gitee import Gitee
|
|
16
14
|
from lbkit.log import Logger
|
|
17
15
|
from lbkit import misc
|
|
18
16
|
from lbkit import errors
|
|
19
17
|
from lbkit.ukr.build import UKRBuild
|
|
20
18
|
from lbkit.utils.env_detector import EnvDetector
|
|
21
19
|
|
|
22
|
-
log = Logger(
|
|
20
|
+
log = Logger()
|
|
23
21
|
|
|
24
22
|
|
|
25
23
|
class Command(object):
|
|
@@ -92,14 +90,6 @@ class Command(object):
|
|
|
92
90
|
exe = Executor(env)
|
|
93
91
|
exe.run()
|
|
94
92
|
|
|
95
|
-
def gitee(self, *args):
|
|
96
|
-
"""
|
|
97
|
-
Call gitee api.
|
|
98
|
-
|
|
99
|
-
CI场景调用gitee的API完成像标签、评论等基本操作
|
|
100
|
-
"""
|
|
101
|
-
_ = Gitee(sys.argv[2:])
|
|
102
|
-
|
|
103
93
|
# test package
|
|
104
94
|
def test(self, *args):
|
|
105
95
|
"""
|
|
@@ -123,7 +113,6 @@ class Command(object):
|
|
|
123
113
|
("Build Component commands", ["new", "build", "test"]),
|
|
124
114
|
("Build Product commands", ["build"]),
|
|
125
115
|
("Misc commands", ["help"]),
|
|
126
|
-
("CI Robot commands", ["gitee"])
|
|
127
116
|
]
|
|
128
117
|
|
|
129
118
|
def check_all_commands_listed():
|
|
@@ -223,7 +212,6 @@ class Command(object):
|
|
|
223
212
|
log.error(exc)
|
|
224
213
|
ret_code = 0
|
|
225
214
|
except SystemExit as exc:
|
|
226
|
-
log.error("lbk exit with exception:")
|
|
227
215
|
if exc.code != 0:
|
|
228
216
|
log.error("Exiting with code: %d" % exc.code)
|
|
229
217
|
ret_code = exc.code
|
|
@@ -233,7 +221,7 @@ class Command(object):
|
|
|
233
221
|
print(traceback.format_exc())
|
|
234
222
|
ret_code = -1
|
|
235
223
|
msg = str(exc)
|
|
236
|
-
log.error(
|
|
224
|
+
log.error(msg)
|
|
237
225
|
except errors.TestException:
|
|
238
226
|
log.error("lbk exit with exception:")
|
|
239
227
|
log.error(exc)
|
|
@@ -245,8 +233,6 @@ class Command(object):
|
|
|
245
233
|
def main(args):
|
|
246
234
|
# 使能revision功能
|
|
247
235
|
os.environ["CONAN_REVISIONS_ENABLED"] = "1"
|
|
248
|
-
# 创建并清空日志目录
|
|
249
|
-
shutil.rmtree(misc.LOG_DIR, ignore_errors=True)
|
|
250
236
|
os.makedirs(misc.LOG_DIR, exist_ok=True)
|
|
251
237
|
def ctrl_c_handler(_, __):
|
|
252
238
|
sys.exit(-3)
|
|
@@ -259,5 +245,8 @@ def main(args):
|
|
|
259
245
|
|
|
260
246
|
command = Command()
|
|
261
247
|
error = command.run(args)
|
|
248
|
+
if error != 0:
|
|
249
|
+
log.error("Build failed, You can find all build logs in the directory: " + misc.LOG_DIR)
|
|
250
|
+
else:
|
|
251
|
+
log.success("Build successfully, You can find all build logs in the directory: " + misc.LOG_DIR)
|
|
262
252
|
sys.exit(error)
|
|
263
|
-
|
|
@@ -16,7 +16,7 @@ from lbkit.errors import ArgException
|
|
|
16
16
|
from lbkit.misc import SmartFormatter
|
|
17
17
|
|
|
18
18
|
lb_cwd = os.path.split(os.path.realpath(__file__))[0]
|
|
19
|
-
log = Logger(
|
|
19
|
+
log = Logger()
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class CodeGenHistory():
|
|
@@ -102,6 +102,7 @@ def codegen_version_arg(parser: argparse.ArgumentParser, default=__version__.str
|
|
|
102
102
|
|
|
103
103
|
class CodeGen(object):
|
|
104
104
|
def __init__(self, args):
|
|
105
|
+
Logger("codegen.log")
|
|
105
106
|
self.args = args
|
|
106
107
|
self.codegen_version = __version__
|
|
107
108
|
self.log_level = "NOTSET"
|
|
@@ -152,11 +153,6 @@ class CodeGen(object):
|
|
|
152
153
|
formatter_class=SmartFormatter)
|
|
153
154
|
codegen_version_arg(parser)
|
|
154
155
|
parser.add_argument("-d", "--directory", help='generate code directory', default=".")
|
|
155
|
-
parser.add_argument("-l", "--log_level", help='show log level',
|
|
156
|
-
choices=[
|
|
157
|
-
"CRITICAL", "FATAL", "ERROR", "WARN",
|
|
158
|
-
"WARNING", "INFO", "DEBUG", "NOTSET",
|
|
159
|
-
], default=None)
|
|
160
156
|
parser.add_argument("-t", "--codetype", help='code type, default: all', default="all", choices=["public", "server", "client", "all"])
|
|
161
157
|
group2 = parser.add_argument_group('cdf file', 'Generate code using the specified CDF file')
|
|
162
158
|
group2.add_argument("-c", "--cdf_file", help='component description file, default metadata/package.yml', default=None)
|
|
@@ -164,9 +160,6 @@ class CodeGen(object):
|
|
|
164
160
|
group1.add_argument("-i", "--idf_file", help='A IDF file to be processed e.g.: com.litebmc.Upgrade.xml', default=None)
|
|
165
161
|
|
|
166
162
|
args = parser.parse_args(self.args)
|
|
167
|
-
if args.log_level:
|
|
168
|
-
self.log_level = args.log_level
|
|
169
|
-
log.setLevel(self.log_level)
|
|
170
163
|
|
|
171
164
|
if args.cdf_file:
|
|
172
165
|
if not os.path.isfile(args.cdf_file):
|
|
@@ -212,7 +205,7 @@ class CodeGen(object):
|
|
|
212
205
|
if not os.path.isfile(intf_file):
|
|
213
206
|
raise ArgException(f"The IDF file ({intf_file}) not exist")
|
|
214
207
|
if not os.path.isdir(out_dir):
|
|
215
|
-
log.
|
|
208
|
+
log.warn(f"Directory {args.directory} not exist, try create")
|
|
216
209
|
os.makedirs(out_dir)
|
|
217
210
|
self._gen(intf_file, out_dir, args.codetype)
|
|
218
211
|
|
|
@@ -11,7 +11,7 @@ from lbkit.misc import load_yml_with_json_schema_validate, get_json_schema_file
|
|
|
11
11
|
from lbkit.errors import OdfValidateException, LiteBmcException
|
|
12
12
|
from lbkit.helper import SigInvalidException, validate_glib_signature
|
|
13
13
|
|
|
14
|
-
log = Logger(
|
|
14
|
+
log = Logger()
|
|
15
15
|
alias = None
|
|
16
16
|
|
|
17
17
|
class IDFException(Exception):
|
|
@@ -124,6 +124,8 @@ CTYPE_SIGNATURE_MAP = {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
def get_intfname_and_ctype(class_alias: str, ctype: str):
|
|
127
|
+
if ctype == "self":
|
|
128
|
+
return class_alias, class_alias
|
|
127
129
|
match = re.findall(r"([\w][\w\d]*)", ctype)
|
|
128
130
|
intf = ".".join(match[:-1])
|
|
129
131
|
ctype = match[-1]
|
|
@@ -426,6 +428,8 @@ class IdfCtypeRender():
|
|
|
426
428
|
if is_array:
|
|
427
429
|
# 结构体数组初始化时为二级空指针,以空指针结束
|
|
428
430
|
return [f"{stru_name} *<const>*<arg_name>"]
|
|
431
|
+
elif stru_name == self.intf.alias:
|
|
432
|
+
return [f"<const>struct _{stru_name} *<arg_name>"]
|
|
429
433
|
else:
|
|
430
434
|
# 结构体成员初始化时为空结构体,由反序列化时填充内容
|
|
431
435
|
return [f"<const>{stru_name} *<arg_name>"]
|
|
@@ -972,7 +976,7 @@ class IdfStructure(IdfBase):
|
|
|
972
976
|
if odf is not None:
|
|
973
977
|
schema[prop.name] = odf
|
|
974
978
|
else:
|
|
975
|
-
log.
|
|
979
|
+
log.warn(f"the schema of prop {prop.name} is None")
|
|
976
980
|
odf = {
|
|
977
981
|
"type": "object",
|
|
978
982
|
"additionalProperties": False,
|
|
@@ -1078,7 +1082,7 @@ class IdfDictionary():
|
|
|
1078
1082
|
if odf is not None:
|
|
1079
1083
|
schema[prop.name] = odf
|
|
1080
1084
|
else:
|
|
1081
|
-
log.
|
|
1085
|
+
log.warn(f"the schema of prop {prop.name} is None")
|
|
1082
1086
|
key_schema = self.key_obj.odf_schema(False)
|
|
1083
1087
|
odf = {
|
|
1084
1088
|
"type": "array",
|
|
@@ -1191,7 +1195,7 @@ class IdfInterface(IdfInterfaceBase):
|
|
|
1191
1195
|
schema[prop.name] = odf
|
|
1192
1196
|
with_schema_prop_cnt += 1
|
|
1193
1197
|
else:
|
|
1194
|
-
log.
|
|
1198
|
+
log.warn(f"the schema of prop {prop.name} is None")
|
|
1195
1199
|
# 顶层属性可以有一个flags标记属性
|
|
1196
1200
|
schema[f"_{prop.name}_flags"] = {
|
|
1197
1201
|
"enum": ["per_save", "per_power_off", "per_reboot"]
|
|
@@ -1312,17 +1316,6 @@ class IdfInterface(IdfInterfaceBase):
|
|
|
1312
1316
|
for item in items:
|
|
1313
1317
|
obj = IdfPluginAction(self, item)
|
|
1314
1318
|
self.plugin.actions.append(obj)
|
|
1315
|
-
log.debug("interface signature: " + self.signature)
|
|
1316
|
-
for signal in self.signals:
|
|
1317
|
-
log.debug(f"{signal.name} signature: " + signal.signature)
|
|
1318
|
-
for method in self.methods:
|
|
1319
|
-
log.debug(f"{method.name} in signature: " + method.in_signature + ", out signature: " + method.out_signature)
|
|
1320
|
-
# for name, stru in self.structures.items():
|
|
1321
|
-
# log.debug(f"{name} signature: " + stru.signature)
|
|
1322
|
-
# for name, enum in self.enumerations.items():
|
|
1323
|
-
# log.debug(f"{name} signature: " + enum.signature)
|
|
1324
|
-
# for name, dictionary in self.dictionaries.items():
|
|
1325
|
-
# log.debug(f"{name} signature: " + dictionary.signature)
|
|
1326
1319
|
# 接口本身也是一个结构体
|
|
1327
1320
|
intf_stru = IdfStructure(self, idf, propety_key="properties")
|
|
1328
1321
|
self.structures[self.alias] = intf_stru
|
|
@@ -971,7 +971,7 @@ static ${class_name}_Properties _${class_name}_properties =
|
|
|
971
971
|
% if (prop.signature in ["b", "y", "n", "q", "i", "u", "x", "t", "d", "o", "s", "g", "ab", "ay", "an", "aq", "ai", "au", "ax", "at", "ad", "as", "ao", "ag"] and prop.val_validate()):
|
|
972
972
|
.check = ${class_name}_check_${prop.name}_variant,
|
|
973
973
|
% else:
|
|
974
|
-
<% match = re.match(
|
|
974
|
+
<% match = re.match(rf"^array\[enum\[(.*)\]\]$", prop.ctype) %>\
|
|
975
975
|
% if match:
|
|
976
976
|
<% match_enum = re.findall(r"([\w][\w\d]*)", match.group(1)) %>\
|
|
977
977
|
% if match_enum[0] == "self":
|
|
@@ -980,7 +980,7 @@ static ${class_name}_Properties _${class_name}_properties =
|
|
|
980
980
|
.check = ${match_enum[0]}_${match_enum[-1]}_check_enum_variant_v,
|
|
981
981
|
% endif
|
|
982
982
|
% else:
|
|
983
|
-
<% match = re.match(
|
|
983
|
+
<% match = re.match(rf"^enum\[(.*)\]$", prop.ctype) %>\
|
|
984
984
|
% if match:
|
|
985
985
|
<% match_enum = re.findall(r"([\w][\w\d]*)", match.group(1)) %>\
|
|
986
986
|
% if match_enum[0] == "self":
|
|
@@ -25,6 +25,8 @@ class ArgParser():
|
|
|
25
25
|
help="Upload package to remote")
|
|
26
26
|
parser.add_argument("-s", "--from_source", action="store_true",
|
|
27
27
|
help="Build all depencencies component from source")
|
|
28
|
+
parser.add_argument("-ts", "--tar_source", action="store_true",
|
|
29
|
+
help="Use the tar command to compress the source code package.")
|
|
28
30
|
parser.add_argument("--summary", action="store_true",
|
|
29
31
|
help=argparse.SUPPRESS)
|
|
30
32
|
parser.add_argument("--cov", action="store_true",
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"""组件构建"""
|
|
2
2
|
import os
|
|
3
3
|
import yaml
|
|
4
|
-
import
|
|
4
|
+
import shlex
|
|
5
5
|
import re
|
|
6
6
|
import json
|
|
7
|
-
import sys
|
|
8
7
|
from multiprocessing import Pool
|
|
9
8
|
import traceback
|
|
10
9
|
from argparse import ArgumentParser
|
|
@@ -12,14 +11,15 @@ from jsonschema import validate, ValidationError
|
|
|
12
11
|
from git import Repo
|
|
13
12
|
from git.exc import InvalidGitRepositoryError
|
|
14
13
|
from mako.lookup import TemplateLookup
|
|
15
|
-
from lbkit.misc import
|
|
14
|
+
from lbkit.misc import load_yml_with_json_schema_validate, get_json_schema_file, load_json_schema
|
|
16
15
|
from lbkit import errors
|
|
17
16
|
from lbkit.codegen.codegen import CodeGen, history_versions
|
|
18
17
|
from lbkit.tools import Tools
|
|
18
|
+
from lbkit.log import Logger
|
|
19
19
|
from lbkit.build_conan_parallel import BuildConanParallel
|
|
20
20
|
from lbkit.codegen.codegen import Version
|
|
21
21
|
|
|
22
|
-
tools = Tools(
|
|
22
|
+
tools = Tools()
|
|
23
23
|
log = tools.log
|
|
24
24
|
lb_cwd = os.path.split(os.path.realpath(__file__))[0]
|
|
25
25
|
|
|
@@ -53,6 +53,7 @@ class DeployComponent():
|
|
|
53
53
|
class BuildComponent():
|
|
54
54
|
def __init__(self, args_parser: ArgumentParser, args=None):
|
|
55
55
|
self.cwd = os.getcwd()
|
|
56
|
+
Logger("build_comp.log")
|
|
56
57
|
self.deploy_success = True
|
|
57
58
|
self.options = args_parser.parse_args(args)
|
|
58
59
|
self.options.build_type = self.options.build_type.capitalize()
|
|
@@ -66,8 +67,16 @@ class BuildComponent():
|
|
|
66
67
|
self.from_source = self.options.from_source
|
|
67
68
|
# 当前组件及其依赖将被部署到rootfs目录
|
|
68
69
|
self.rootfs_dir = os.path.join(self.cwd, ".temp", "rootfs")
|
|
69
|
-
|
|
70
|
-
os.
|
|
70
|
+
tools.makedirs(self.rootfs_dir, True, True)
|
|
71
|
+
self.conan_index = os.path.join(self.cwd, ".temp", "conan-index")
|
|
72
|
+
tools.makedirs(self.conan_index, True, True)
|
|
73
|
+
self.enable_tar_source = self.options.tar_source
|
|
74
|
+
self.source_file = os.path.join(self.cwd, ".temp", "source.tar.gz")
|
|
75
|
+
self.graphfile = os.path.join(self.cwd, ".temp", "graph.info")
|
|
76
|
+
self.lockfile = os.path.join(self.cwd, ".temp", "conan.lock")
|
|
77
|
+
self.orderfile = os.path.join(self.cwd, ".temp", "graph.order")
|
|
78
|
+
# 当组件构建完成后可以获取到包id, 初始化时置空
|
|
79
|
+
self.package_id = None
|
|
71
80
|
|
|
72
81
|
self.pkg = None
|
|
73
82
|
self.base_cmd = ""
|
|
@@ -88,8 +97,23 @@ class BuildComponent():
|
|
|
88
97
|
for pkg_option in self.options.pkg_options:
|
|
89
98
|
self.base_cmd += " -o " + pkg_option
|
|
90
99
|
self.base_cmd += f" -o */*:codegen_version={self.options.codegen_version}"
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
self.base_cmd += f" -o */*:compatible_required={self.codegen_version.info.lb_base_compatible_required}"
|
|
101
|
+
|
|
102
|
+
@staticmethod
|
|
103
|
+
def _check_conanfile_if_tracked():
|
|
104
|
+
"""检查conanfile.py是否被git跟踪"""
|
|
105
|
+
tracked = False
|
|
106
|
+
try:
|
|
107
|
+
repo = Repo(".")
|
|
108
|
+
for entry in repo.commit().tree.traverse():
|
|
109
|
+
if entry.path == "conanfile.py":
|
|
110
|
+
tracked = True
|
|
111
|
+
break
|
|
112
|
+
except InvalidGitRepositoryError:
|
|
113
|
+
log.debug("Invalid git repository")
|
|
114
|
+
return
|
|
115
|
+
if tracked:
|
|
116
|
+
raise Exception("conanfile.py is being tracked by git. You can untrack it by executing the command `git rm --f conanfile.py`")
|
|
93
117
|
|
|
94
118
|
def get_package_version(self):
|
|
95
119
|
"""
|
|
@@ -105,17 +129,40 @@ class BuildComponent():
|
|
|
105
129
|
print(str(e))
|
|
106
130
|
return None
|
|
107
131
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
132
|
+
def tar_source(self, tar_path):
|
|
133
|
+
"""
|
|
134
|
+
将self.cwd目录下未被git跟踪的文件使用tar命令压缩到tar_path
|
|
135
|
+
|
|
136
|
+
:param tar_path: tar压缩包路径
|
|
137
|
+
"""
|
|
138
|
+
untracked_files = [".temp"]
|
|
139
|
+
if os.path.exists("test_package/test_interface"):
|
|
140
|
+
untracked_files.append("test_package/test_interface")
|
|
141
|
+
if os.path.exists("conanfile.py"):
|
|
142
|
+
untracked_files.append("conanfile.py")
|
|
143
|
+
if os.path.exists("__pycache__"):
|
|
144
|
+
untracked_files.append("__pycache__")
|
|
145
|
+
if os.path.exists(".git"):
|
|
146
|
+
untracked_files.append(".git")
|
|
147
|
+
if os.path.exists(".gitignore"):
|
|
148
|
+
untracked_files.append(".gitignore")
|
|
149
|
+
|
|
111
150
|
try:
|
|
112
|
-
repo = Repo(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
151
|
+
repo = Repo(self.cwd)
|
|
152
|
+
# 获取未被跟踪的文件
|
|
153
|
+
untracked_files.extend(repo.untracked_files)
|
|
154
|
+
except InvalidGitRepositoryError:
|
|
155
|
+
raise errors.LiteBmcException(f"{self.cwd} is not a valid git repository")
|
|
156
|
+
|
|
157
|
+
# 构建tar命令,使用-C指定工作目录
|
|
158
|
+
cmd_parts = ["tar", "--format=gnu", "-czf", tar_path, f"--transform=s|^.|{self.version}|", "-C", self.cwd]
|
|
159
|
+
for file in untracked_files:
|
|
160
|
+
cmd_parts.append("--exclude=" + file)
|
|
161
|
+
cmd_parts.append(".")
|
|
162
|
+
cmd = " ".join(shlex.quote(part) for part in cmd_parts)
|
|
163
|
+
|
|
164
|
+
tools.exec(cmd, verbose=True)
|
|
165
|
+
log.info(f"Archived {len(untracked_files)} untracked files to {tar_path}")
|
|
119
166
|
|
|
120
167
|
def gen_conaninfo(self):
|
|
121
168
|
package_yml = os.path.join(self.cwd, "metadata/package.yml")
|
|
@@ -131,10 +178,15 @@ class BuildComponent():
|
|
|
131
178
|
# 构建命令未指定channel时从package.yml中读取
|
|
132
179
|
pkg["channel"] = self.channel
|
|
133
180
|
pkg["version"] = self.get_package_version()
|
|
134
|
-
self.pkg = pkg
|
|
135
181
|
# 从package.yml加载基础信息
|
|
136
182
|
self.name = pkg.get("name")
|
|
137
183
|
self.version = pkg.get("version")
|
|
184
|
+
self.tar_source(self.source_file)
|
|
185
|
+
pkg["source_url"] = self.source_file
|
|
186
|
+
pkg["sha256"] = tools.file_digest_sha256(self.source_file)
|
|
187
|
+
pkg["enable_tar_source"] = self.enable_tar_source
|
|
188
|
+
pkg["source_dir"] = self.cwd
|
|
189
|
+
self.pkg = pkg
|
|
138
190
|
|
|
139
191
|
self.package = self.name + "/" + self.version
|
|
140
192
|
if self.user != "litebmc" or self.channel != "release":
|
|
@@ -155,17 +207,14 @@ class BuildComponent():
|
|
|
155
207
|
for k, v in option.items():
|
|
156
208
|
self.base_cmd += f" -o {conan}/*:{k}={v}"
|
|
157
209
|
|
|
158
|
-
#
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if not self._is_conanfile_tracked:
|
|
162
|
-
conanfile = os.path.join(self.cwd, "conanfile.py")
|
|
210
|
+
# 检查git是是否跟踪conanfile.py
|
|
211
|
+
self._check_conanfile_if_tracked()
|
|
212
|
+
conanfile = os.path.join(self.conan_index, "conanfile.py")
|
|
163
213
|
|
|
164
214
|
# 使用litebmc.conanfile.mako模板生成基础litebmc公共conanfile
|
|
165
215
|
lookup = TemplateLookup(directories=os.path.join(lb_cwd, "template"))
|
|
166
216
|
template = lookup.get_template("conanbase.mako")
|
|
167
217
|
conandata = template.render(lookup=lookup, pkg=pkg,
|
|
168
|
-
conanfile_tracked=self._is_conanfile_tracked,
|
|
169
218
|
codegen_version=self.codegen_version,
|
|
170
219
|
codegen_history=history_versions)
|
|
171
220
|
# 写入文件
|
|
@@ -196,6 +245,8 @@ class BuildComponent():
|
|
|
196
245
|
context = info.get("context")
|
|
197
246
|
if context != "host":
|
|
198
247
|
continue
|
|
248
|
+
if ref.startswith(self.package):
|
|
249
|
+
self.package_id = id
|
|
199
250
|
dep = DeployComponent(ref, id, self.rootfs_dir)
|
|
200
251
|
pool.apply_async(dep.run, error_callback=self._copy_failed)
|
|
201
252
|
pool.close()
|
|
@@ -203,32 +254,29 @@ class BuildComponent():
|
|
|
203
254
|
|
|
204
255
|
def build(self):
|
|
205
256
|
log.info(os.getcwd())
|
|
206
|
-
|
|
257
|
+
os.chdir(self.conan_index)
|
|
207
258
|
export_cmd = "conan export . "
|
|
208
259
|
if self.user != "litebmc" or self.channel != "release":
|
|
209
260
|
export_cmd += f"--user={self.user} --channel={self.channel}"
|
|
210
|
-
tools.
|
|
261
|
+
tools.exec(export_cmd, verbose=True)
|
|
211
262
|
|
|
212
|
-
|
|
213
|
-
orderfile = os.path.join(self.cwd, ".temp", "graph.order")
|
|
214
|
-
graph_cmd = f"conan graph build-order . {self.base_cmd} --order-by=recipe -f json --out-file={orderfile}"
|
|
263
|
+
graph_cmd = f"conan graph build-order . {self.base_cmd} --order-by=recipe -f json --out-file={self.orderfile}"
|
|
215
264
|
if self.from_source:
|
|
216
265
|
graph_cmd += " --build='*'"
|
|
217
266
|
else:
|
|
218
267
|
graph_cmd += " --build=missing"
|
|
219
|
-
graph_cmd += f" --lockfile-out={lockfile}"
|
|
220
|
-
tools.
|
|
221
|
-
bcp = BuildConanParallel(orderfile, self.options.remote)
|
|
268
|
+
graph_cmd += f" --lockfile-out={self.lockfile}"
|
|
269
|
+
tools.exec(graph_cmd, verbose=True)
|
|
270
|
+
bcp = BuildConanParallel(self.orderfile, self.lockfile, self.options.remote)
|
|
222
271
|
bcp.build()
|
|
223
272
|
cmd = f"conan create {self.base_cmd} --build='{self.name}/*'"
|
|
224
|
-
tools.
|
|
273
|
+
tools.exec(cmd, verbose=True)
|
|
225
274
|
|
|
226
|
-
|
|
227
|
-
graph_cmd =
|
|
228
|
-
tools.pipe([graph_cmd], out_file=graphfile)
|
|
275
|
+
graph_cmd = f"conan graph info . {self.base_cmd} -f json --lockfile={self.lockfile}"
|
|
276
|
+
tools.pipe([graph_cmd], out_file=self.graphfile)
|
|
229
277
|
|
|
230
278
|
log.success(f"start deploy {self.package} and is's dependency packages")
|
|
231
|
-
self.deploy(graphfile)
|
|
279
|
+
self.deploy(self.graphfile)
|
|
232
280
|
|
|
233
281
|
if not self.deploy_success:
|
|
234
282
|
raise Exception("Deploy component failed")
|
|
@@ -301,10 +349,19 @@ class BuildComponent():
|
|
|
301
349
|
if not ok:
|
|
302
350
|
raise errors.OdfValidateException("Validate odf files with error, build failed")
|
|
303
351
|
|
|
352
|
+
def conan_test(self):
|
|
353
|
+
# 仅测试远程仓登录状态,如果需要登录的,需要输入账号密码
|
|
354
|
+
log.info("Test the login status of the Conan remote repository")
|
|
355
|
+
log.info("If glib/2.81.0 not found, you must add litebmc repository using the command: conan remote add litebmc https://litebmc.com/conan/release")
|
|
356
|
+
cmd = "conan search glib/2.81.0"
|
|
357
|
+
if self.options.remote:
|
|
358
|
+
cmd += f' -r {self.options.remote}'
|
|
359
|
+
tools.run(cmd, capture_output=False)
|
|
304
360
|
|
|
305
361
|
def run(self):
|
|
306
362
|
cmd = f"conan remove {self.package} -c"
|
|
307
363
|
tools.exec(cmd)
|
|
364
|
+
self.conan_test()
|
|
308
365
|
gen = CodeGen(["-c", "./metadata/package.yml"])
|
|
309
366
|
gen.run()
|
|
310
367
|
# 部署依赖
|
|
@@ -315,15 +372,6 @@ class BuildComponent():
|
|
|
315
372
|
self.upload()
|
|
316
373
|
log.success(f"build {self.package} successfully")
|
|
317
374
|
|
|
318
|
-
@property
|
|
319
|
-
def package_id(self):
|
|
320
|
-
cmd = f"conan graph info . {self.base_cmd} --filter=package_id"
|
|
321
|
-
res = tools.run(cmd, capture_output=True)
|
|
322
|
-
match = re.search(r"package_id: ([a-f0-9]{40})", res.stdout)
|
|
323
|
-
if match is None:
|
|
324
|
-
raise errors.LiteBmcException(f"Get package if of {self.package} failed")
|
|
325
|
-
return match.group(1)
|
|
326
|
-
|
|
327
375
|
@staticmethod
|
|
328
376
|
def package_folder(self):
|
|
329
377
|
cmd = f"conan cache path {self.package}#latest:{self.package_id}"
|
|
@@ -340,7 +388,6 @@ class BuildComponent():
|
|
|
340
388
|
try:
|
|
341
389
|
self.run()
|
|
342
390
|
except Exception as e:
|
|
343
|
-
log.error(
|
|
344
|
-
f"build {self.package} {Color.RED}failed{Color.RESET_ALL}")
|
|
391
|
+
log.error(f"build {self.package} failed")
|
|
345
392
|
log.info(e)
|
|
346
393
|
os._exit(-2)
|
|
@@ -69,15 +69,30 @@ class LiteBmcConan(ConanFile):
|
|
|
69
69
|
% endif
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
% if pkg["enable_tar_source"]:
|
|
72
73
|
def export(self):
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
files.update_conandata(self, {
|
|
75
|
+
"sources": {
|
|
76
|
+
"${pkg["version"]}": {
|
|
77
|
+
"url": "${pkg["source_url"]}",
|
|
78
|
+
"sha256": "${pkg["sha256"]}"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
def source(self):
|
|
84
|
+
source = self.conan_data["sources"][self.version]
|
|
85
|
+
url = source.get("url")
|
|
86
|
+
if (not url.startswith("http")) and os.path.isfile(url):
|
|
87
|
+
files.unzip(self, url, destination=".", strip_root=True)
|
|
88
|
+
else:
|
|
89
|
+
files.get(self, **source, strip_root=True)
|
|
90
|
+
% else:
|
|
91
|
+
def export(self):
|
|
92
|
+
git = Git(self, "${pkg["source_dir"]}")
|
|
78
93
|
if git.is_dirty():
|
|
79
94
|
print(f"{Fore.YELLOW}Waring: Local repo is dirty.{Style.RESET_ALL}")
|
|
80
|
-
files.update_conandata(self, {"sources": {"commit": None, "url": None, "pwd":
|
|
95
|
+
files.update_conandata(self, {"sources": {"commit": None, "url": None, "pwd": "${pkg["source_dir"]}"}})
|
|
81
96
|
return
|
|
82
97
|
|
|
83
98
|
scm_url = None
|
|
@@ -89,7 +104,7 @@ class LiteBmcConan(ConanFile):
|
|
|
89
104
|
scm_url = git.get_remote_url(remote)
|
|
90
105
|
break
|
|
91
106
|
if not scm_url:
|
|
92
|
-
files.update_conandata(self, {"sources": {"commit": None, "url": None, "pwd":
|
|
107
|
+
files.update_conandata(self, {"sources": {"commit": None, "url": None, "pwd": "${pkg["source_dir"]}"}})
|
|
93
108
|
return
|
|
94
109
|
files.update_conandata(self, {"sources": {"commit": scm_commit, "url": scm_url}})
|
|
95
110
|
|
|
@@ -101,6 +116,7 @@ class LiteBmcConan(ConanFile):
|
|
|
101
116
|
git.checkout(commit=sources["commit"])
|
|
102
117
|
else:
|
|
103
118
|
files.copy(self, "*", src=sources["pwd"], dst=".")
|
|
119
|
+
% endif
|
|
104
120
|
|
|
105
121
|
def requirements(self):
|
|
106
122
|
% if len(pkg.get("requires", {})) > 0:
|