lbkit 0.5.2__tar.gz → 0.5.5__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.5.2/lbkit.egg-info → lbkit-0.5.5}/PKG-INFO +2 -1
- lbkit-0.5.5/lbkit/__init__.py +2 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/codegen.py +2 -1
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/idf_interface.py +57 -33
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/template/public.c.mako +9 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/template/public.h.mako +3 -1
- lbkit-0.5.5/lbkit/codegen/template/server.c.mako +357 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/component/arg_parser.py +2 -2
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/component/build.py +28 -7
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/component/template/conanbase.mako +22 -0
- lbkit-0.5.5/lbkit/component/template/deploy.mako +42 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/misc.py +39 -1
- {lbkit-0.5.2 → lbkit-0.5.5/lbkit.egg-info}/PKG-INFO +2 -1
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit.egg-info/requires.txt +1 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/setup.py +1 -1
- lbkit-0.5.2/lbkit/__init__.py +0 -2
- lbkit-0.5.2/lbkit/codegen/template/server.c.mako +0 -113
- lbkit-0.5.2/lbkit/component/template/deploy.mako +0 -20
- {lbkit-0.5.2 → lbkit-0.5.5}/AUTHORS +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/LICENSE +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/MANIFEST.in +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/README.md +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/ci_robot/__init__.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/ci_robot/gitee.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/cli.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/__init__.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/ctype_defination.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/renderer.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/template/client.c.mako +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/template/client.h.mako +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/template/interface.c.mako +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/template/interface.introspect.xml.mako +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/codegen/template/server.h.mako +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/component/__init__.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/component/test.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/errors.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/helper.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/integration/__init__.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/integration/build_manifest.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/integration/build_prepare.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/integration/build_rootfs.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/integration/config.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/integration/task.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/integration/template/conanfile.py.mako +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/lbkit.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/log.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit/tools.py +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit.egg-info/SOURCES.txt +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit.egg-info/dependency_links.txt +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit.egg-info/entry_points.txt +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/lbkit.egg-info/top_level.txt +0 -0
- {lbkit-0.5.2 → lbkit-0.5.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lbkit
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.5
|
|
4
4
|
Summary: Tools provided by litebmc.com
|
|
5
5
|
Home-page: https://www.litebmc.com
|
|
6
6
|
Author: xuhj@litebmc.com
|
|
@@ -19,5 +19,6 @@ Requires-Dist: jsonschema
|
|
|
19
19
|
Requires-Dist: conan==2.1
|
|
20
20
|
Requires-Dist: requests
|
|
21
21
|
Requires-Dist: gitpython
|
|
22
|
+
Requires-Dist: inflection
|
|
22
23
|
|
|
23
24
|
build and code generate tools
|
|
@@ -16,6 +16,7 @@ from lbkit.misc import SmartFormatter
|
|
|
16
16
|
lb_cwd = os.path.split(os.path.realpath(__file__))[0]
|
|
17
17
|
log = Logger("codegen")
|
|
18
18
|
|
|
19
|
+
__version__=1
|
|
19
20
|
|
|
20
21
|
class CodeGen(object):
|
|
21
22
|
def __init__(self, args):
|
|
@@ -66,7 +67,7 @@ class CodeGen(object):
|
|
|
66
67
|
sys.exit(-1)
|
|
67
68
|
outdir = cfg.get("outdir", os.getcwd())
|
|
68
69
|
self._gen(file, outdir)
|
|
69
|
-
|
|
70
|
+
return
|
|
70
71
|
|
|
71
72
|
parser = argparse.ArgumentParser(description=self.run.__doc__,
|
|
72
73
|
prog="lbkit gen",
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import yaml
|
|
2
2
|
import os
|
|
3
|
-
import json
|
|
4
3
|
import re
|
|
5
4
|
import hashlib
|
|
6
|
-
from jsonschema import validate, ValidationError
|
|
7
5
|
from lbkit.log import Logger
|
|
8
6
|
from lbkit.codegen.renderer import Renderer
|
|
9
|
-
from lbkit.codegen.ctype_defination import CTYPE_OBJS
|
|
7
|
+
from lbkit.codegen.ctype_defination import CTYPE_OBJS
|
|
8
|
+
from lbkit.misc import validate_yml_with_json_schema
|
|
10
9
|
|
|
11
10
|
log = Logger("gen_interface")
|
|
12
11
|
|
|
@@ -67,7 +66,8 @@ STRU_NAME_REGEX = METHOD_NAME_REGEX
|
|
|
67
66
|
ENUM_NAME_REGEX = METHOD_NAME_REGEX
|
|
68
67
|
DICT_NAME_REGEX = METHOD_NAME_REGEX
|
|
69
68
|
|
|
70
|
-
|
|
69
|
+
CTYPE_BASE_REG = "boolean|byte|int16|uint16|int32|uint32|int64|uint64|size|ssize|double|string|object_path|signature|unixfd"
|
|
70
|
+
CTYPE_REGEX = CTYPE_BASE_REG + "|variant"
|
|
71
71
|
|
|
72
72
|
CTYPE_SIGNATURE_MAP = {
|
|
73
73
|
"boolean": "b",
|
|
@@ -137,7 +137,7 @@ class IdfCtypeRender():
|
|
|
137
137
|
def declare(self):
|
|
138
138
|
"""变量申明,用于结构体(接口类、方法请求和响应、信号消息等)申明"""
|
|
139
139
|
log.debug(f"Get declare info, name: {self.name}, ctype: {self.ctype}")
|
|
140
|
-
match = re.match(f"^array\[({
|
|
140
|
+
match = re.match(f"^array\[({CTYPE_BASE_REG})\]$", self.ctype)
|
|
141
141
|
if match:
|
|
142
142
|
ctype_obj = CTYPE_OBJS.get(self.ctype)
|
|
143
143
|
return ctype_obj.declare
|
|
@@ -177,7 +177,7 @@ class IdfCtypeRender():
|
|
|
177
177
|
def free_func(self):
|
|
178
178
|
"""生成释放数据的C函数,如果是结构体、字典需要生成对象的释放函数"""
|
|
179
179
|
log.debug(f"Get free function info, name: {self.name}, ctype: {self.ctype}")
|
|
180
|
-
match = re.match(f"^array\[({
|
|
180
|
+
match = re.match(f"^array\[({CTYPE_BASE_REG})\]$", self.ctype)
|
|
181
181
|
if match:
|
|
182
182
|
ctype_obj = CTYPE_OBJS.get(self.ctype)
|
|
183
183
|
return ctype_obj.free_func
|
|
@@ -206,7 +206,7 @@ class IdfCtypeRender():
|
|
|
206
206
|
|
|
207
207
|
def encode_func(self):
|
|
208
208
|
log.debug(f"Get encode function info, name: {self.name}, ctype: {self.ctype}")
|
|
209
|
-
match = re.match(f"^array\[({
|
|
209
|
+
match = re.match(f"^array\[({CTYPE_BASE_REG})\]$", self.ctype)
|
|
210
210
|
if match:
|
|
211
211
|
ctype_obj = CTYPE_OBJS.get(self.ctype)
|
|
212
212
|
return ctype_obj.encode_func
|
|
@@ -239,7 +239,7 @@ class IdfCtypeRender():
|
|
|
239
239
|
|
|
240
240
|
def decode_func(self):
|
|
241
241
|
log.debug(f"Get decode info, name: {self.name}, ctype: {self.ctype}")
|
|
242
|
-
match = re.match(f"^array\[({
|
|
242
|
+
match = re.match(f"^array\[({CTYPE_BASE_REG})\]$", self.ctype)
|
|
243
243
|
if match:
|
|
244
244
|
ctype_obj = CTYPE_OBJS.get(self.ctype)
|
|
245
245
|
return ctype_obj.decode_func
|
|
@@ -269,6 +269,47 @@ class IdfCtypeRender():
|
|
|
269
269
|
else:
|
|
270
270
|
return [f"<arg_in> = {stru_name}_decode(<arg_name>)"]
|
|
271
271
|
|
|
272
|
+
def odf_load_func(self):
|
|
273
|
+
log.debug(f"Get odf_load function, name: {self.name}, ctype: {self.ctype}")
|
|
274
|
+
# odf不支持gariant
|
|
275
|
+
match = re.match(f"^array\[(variant)\]$", self.ctype)
|
|
276
|
+
if match:
|
|
277
|
+
return None
|
|
278
|
+
match = re.match(f"^variant$", self.ctype)
|
|
279
|
+
if match:
|
|
280
|
+
return None
|
|
281
|
+
# 字符串数组由结束NULL表示,不需要长度
|
|
282
|
+
match = re.match(f"^array\[(string|object_path|signature)\]$", self.ctype)
|
|
283
|
+
if match:
|
|
284
|
+
return "<arg_name> = load_odf_as_" + match.group(1) + "_v(doc, <node>)"
|
|
285
|
+
match = re.match(f"^array\[({CTYPE_BASE_REG})\]$", self.ctype)
|
|
286
|
+
if match:
|
|
287
|
+
return "<arg_name> = load_odf_as_" + match.group(1) + "_v(doc, <node>, &n_<arg_name>)"
|
|
288
|
+
match = re.match(f"^({CTYPE_REGEX})$", self.ctype)
|
|
289
|
+
if match:
|
|
290
|
+
return "<arg_name> = load_odf_as_" + match.group(1) + "(doc, <node>)"
|
|
291
|
+
# 非基础类型
|
|
292
|
+
is_array = False
|
|
293
|
+
ctype = self.ctype
|
|
294
|
+
match = re.match(f"^array\[(.*)\]$", ctype)
|
|
295
|
+
if match:
|
|
296
|
+
is_array = True
|
|
297
|
+
ctype = match.group(1)
|
|
298
|
+
match = re.match(f"^(struct|enum|dict)\[(.*)\]$", ctype)
|
|
299
|
+
_, stru_name = get_intfname_and_ctype(match.group(2))
|
|
300
|
+
if match.group(1) == "enum":
|
|
301
|
+
if is_array:
|
|
302
|
+
# 入参为二级指针
|
|
303
|
+
return f"<arg_name> = _load_odf_as_{stru_name}_v(doc, <node>, &n_<arg_name>)"
|
|
304
|
+
else:
|
|
305
|
+
return f"<arg_name> = _load_odf_as_{stru_name}(doc, <node>)"
|
|
306
|
+
else:
|
|
307
|
+
if is_array:
|
|
308
|
+
# 入参为二级指针
|
|
309
|
+
return f"<arg_name> = _load_odf_as_{stru_name}_v(doc, <node>)"
|
|
310
|
+
else:
|
|
311
|
+
return f"<arg_name> = _load_odf_as_{stru_name}(doc, <node>)"
|
|
312
|
+
|
|
272
313
|
class IdfProperty(IdfCtypeRender):
|
|
273
314
|
def __init__(self, intf: IdfInterfaceBase, prop_data):
|
|
274
315
|
self.intf = intf
|
|
@@ -279,8 +320,12 @@ class IdfProperty(IdfCtypeRender):
|
|
|
279
320
|
self.annotations: list[IdfAnnotation] = []
|
|
280
321
|
self.description = prop_data.get("description", "")
|
|
281
322
|
flags = prop_data.get("flags", "").split(",")
|
|
323
|
+
self.flags = flags
|
|
282
324
|
self.private = True if ("private" in flags) else False
|
|
283
325
|
self.deprecated = True if ("deprecated" in flags) else False
|
|
326
|
+
# refobj的ctype只能是s或as
|
|
327
|
+
if "refobj" in flags and self.ctype != "string" and self.ctype != "array[string]":
|
|
328
|
+
raise IDFException(f"property {self.name} with refobj flag but type is neither s nor as")
|
|
284
329
|
for k, v in ACCESS_MAP.items():
|
|
285
330
|
if k in flags:
|
|
286
331
|
self.access = v
|
|
@@ -487,34 +532,13 @@ class IdfInterface(IdfInterfaceBase):
|
|
|
487
532
|
sig += prop.signature
|
|
488
533
|
return "(" + sig + ")"
|
|
489
534
|
|
|
490
|
-
def _validate(self, idf):
|
|
491
|
-
schema_file = None
|
|
492
|
-
with open(self.file, "r") as fp:
|
|
493
|
-
for line in fp:
|
|
494
|
-
match = re.search(r"#[ ]*yaml-language-server:[ ]*\$schema=(.*)\n", line)
|
|
495
|
-
if match is not None:
|
|
496
|
-
schema_file = match.group(1)
|
|
497
|
-
break
|
|
498
|
-
if schema_file is None:
|
|
499
|
-
schema_file = "/usr/share/litebmc/schema/metadata/interfaces/idf.v1.yaml"
|
|
500
|
-
with open(schema_file, "r") as fp:
|
|
501
|
-
tmp = fp.read()
|
|
502
|
-
schema = json.loads(tmp)
|
|
503
|
-
try:
|
|
504
|
-
validate(idf, schema)
|
|
505
|
-
except ValidationError as exc:
|
|
506
|
-
log.error(f"validate {self.file} failed, schema file is {schema_file}, message:")
|
|
507
|
-
log.error(str(exc))
|
|
508
|
-
return False
|
|
509
|
-
log.info(f"validate {self.file} successfully")
|
|
510
|
-
return True
|
|
511
|
-
|
|
512
535
|
def load_elements(self):
|
|
536
|
+
# 使用schema校验数据,确保IDF文件符合格式要求,减少程序处理过程中的异常处理
|
|
537
|
+
# 验证失败时抛异常,此处不用处理,由外层处理
|
|
538
|
+
validate_yml_with_json_schema(self.file, "/usr/share/litebmc/schema/idf.v1.json")
|
|
539
|
+
log.info(f"validate {self.file} successfully")
|
|
513
540
|
with open(self.file, "r") as fp:
|
|
514
541
|
idf = yaml.load(fp, yaml.FullLoader)
|
|
515
|
-
# 使用schema校验数据,确保IDF文件符合格式要求,减少程序处理过程中的异常处理
|
|
516
|
-
if not self._validate(idf):
|
|
517
|
-
return -1
|
|
518
542
|
self.version = idf.get("version")
|
|
519
543
|
self.description = idf.get("description", "")
|
|
520
544
|
# 别名
|
|
@@ -140,6 +140,14 @@ static const gchar *_${name}StrMap[] = {
|
|
|
140
140
|
% endfor
|
|
141
141
|
};
|
|
142
142
|
|
|
143
|
+
const gchar *${name}_as_string(${name} value)
|
|
144
|
+
{
|
|
145
|
+
if (value >= _${name}Invalid) {
|
|
146
|
+
return "com.litebmc.Errors.Enum.Invalid";
|
|
147
|
+
}
|
|
148
|
+
return _${name}StrMap[value];
|
|
149
|
+
}
|
|
150
|
+
|
|
143
151
|
/* ${name}枚举类型序列化(enum转string)函数 */
|
|
144
152
|
GVariant *${name}_encode(${name} value)
|
|
145
153
|
{
|
|
@@ -165,6 +173,7 @@ ${name} ${name}_decode(GVariant *in)
|
|
|
165
173
|
}
|
|
166
174
|
return _${name}Invalid;
|
|
167
175
|
}
|
|
176
|
+
|
|
168
177
|
/* ${name}枚举类型序列化(enum转string)函数 */
|
|
169
178
|
GVariant *${name}_encode_v(const ${name} *values, gsize n)
|
|
170
179
|
{
|
|
@@ -50,6 +50,8 @@ enum _${name} {
|
|
|
50
50
|
_${name}Invalid,
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
const gchar *${name}_as_string(${name} value);
|
|
54
|
+
|
|
53
55
|
% endfor
|
|
54
56
|
% for name, dictionary in intf.dictionaries.items():
|
|
55
57
|
|
|
@@ -82,7 +84,7 @@ ${name} *${name}_new(void);
|
|
|
82
84
|
|
|
83
85
|
## 定义结构体编解码和释放函数
|
|
84
86
|
% for name, stru in intf.structures.items():
|
|
85
|
-
/* ${name}
|
|
87
|
+
/* ${name} structure object */
|
|
86
88
|
/* START: 结构体${name}及其数组类型的序列化、反序列化、释放函数 */
|
|
87
89
|
GVariant *${name}_encode(const ${name} *value);
|
|
88
90
|
${name} *${name}_decode(GVariant *in);
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
#include "gcl_base.h"
|
|
2
|
+
#include "${intf.name}.h"
|
|
3
|
+
|
|
4
|
+
<%
|
|
5
|
+
class_name = intf.alias
|
|
6
|
+
properties = "_" + class_name + "_properties"
|
|
7
|
+
signal_processer = "_" + class_name + "_signals"
|
|
8
|
+
%>\
|
|
9
|
+
## 定义结构体ODF加载函数
|
|
10
|
+
% for name, stru in intf.structures.items():
|
|
11
|
+
/* ${name} structure object */
|
|
12
|
+
/* START: 结构体${name}及其数组类型的ODF加载函数 */
|
|
13
|
+
${name} *_load_odf_as_${name}(yaml_document_t *doc, yaml_node_t *node);
|
|
14
|
+
${name} **_load_odf_as_${name}_v(yaml_document_t *doc, yaml_node_t *node);
|
|
15
|
+
|
|
16
|
+
% endfor
|
|
17
|
+
## 定义枚举ODF加载函数
|
|
18
|
+
% for name, enum in intf.enumerations.items():
|
|
19
|
+
/* START: 枚举${name}及其数组类型的ODF加载函数 */
|
|
20
|
+
${name} _load_odf_as_${name}(yaml_document_t *doc, yaml_node_t *node);
|
|
21
|
+
${name} *_load_odf_as_${name}_v(yaml_document_t *doc, yaml_node_t *node, gsize *n);
|
|
22
|
+
|
|
23
|
+
% endfor
|
|
24
|
+
## 定义字典ODF加载函数
|
|
25
|
+
% for name, dictionary in intf.dictionaries.items():
|
|
26
|
+
/* START: 字典${name}及其数组类型的ODF加载函数 */
|
|
27
|
+
${name} *_load_odf_as_${name}(yaml_document_t *doc, yaml_node_t *node);
|
|
28
|
+
${name} **_load_odf_as_${name}_v(yaml_document_t *doc, yaml_node_t *node);
|
|
29
|
+
|
|
30
|
+
% endfor
|
|
31
|
+
## 定义结构体ODF加载函数
|
|
32
|
+
% for name, stru in intf.structures.items():
|
|
33
|
+
/* ${name} structure object */
|
|
34
|
+
/* START: 结构体${name}及其数组类型的ODF加载函数 */
|
|
35
|
+
|
|
36
|
+
${name} *_load_odf_as_${name}(yaml_document_t *doc, yaml_node_t *node)
|
|
37
|
+
{
|
|
38
|
+
<% cnt = 0 %>\
|
|
39
|
+
% for prop in stru.values.parameters:
|
|
40
|
+
% if prop.odf_load_func() is not None:
|
|
41
|
+
<% cnt = cnt + 1 %>\
|
|
42
|
+
% endif
|
|
43
|
+
% endfor
|
|
44
|
+
% if cnt == 0:
|
|
45
|
+
return g_new0(${name}, 1);
|
|
46
|
+
% else:
|
|
47
|
+
yaml_node_t *val;
|
|
48
|
+
${name} *output = g_new0(${name}, 1);
|
|
49
|
+
GHashTable *prop_table = load_yaml_mapping_to_hash_table(doc, node);
|
|
50
|
+
% for prop in stru.values.parameters:
|
|
51
|
+
% if prop.odf_load_func() is not None:
|
|
52
|
+
/* process ${prop.name} */
|
|
53
|
+
val = g_hash_table_lookup(prop_table, "${prop.name}");
|
|
54
|
+
if (val)
|
|
55
|
+
${prop.odf_load_func().replace("n_<arg_name>", "output->n_" + prop.name).replace("<arg_name>", "output->" + prop.name).replace("<node>", "val")};
|
|
56
|
+
% endif
|
|
57
|
+
% endfor
|
|
58
|
+
|
|
59
|
+
g_hash_table_destroy(prop_table);
|
|
60
|
+
return output;
|
|
61
|
+
% endif
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
${name} **_load_odf_as_${name}_v(yaml_document_t *doc, yaml_node_t *node)
|
|
65
|
+
{
|
|
66
|
+
yaml_node_t *val;
|
|
67
|
+
gint i = 0;
|
|
68
|
+
if (node->type != YAML_SEQUENCE_NODE) {
|
|
69
|
+
log_warn("Load array ${name} failed because node type error, need type 1(sequence), get type %d", node->type);
|
|
70
|
+
return g_new0(${name} *, 1);
|
|
71
|
+
}
|
|
72
|
+
yaml_node_item_t *top = node->data.sequence.items.top;
|
|
73
|
+
yaml_node_item_t *start = node->data.sequence.items.start;
|
|
74
|
+
gsize cnt = ((gsize)top - (gsize)start) / sizeof(yaml_node_item_t);
|
|
75
|
+
${name} **output = g_new0(${name} *, cnt + 1);
|
|
76
|
+
|
|
77
|
+
for (yaml_node_item_t *item = start; item < top; item++) {
|
|
78
|
+
val = yaml_document_get_node(doc, *item);
|
|
79
|
+
output[i++] = _load_odf_as_${name}(doc, val);
|
|
80
|
+
}
|
|
81
|
+
return output;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
% endfor
|
|
85
|
+
## 定义枚举ODF加载函数
|
|
86
|
+
% for name, enum in intf.enumerations.items():
|
|
87
|
+
|
|
88
|
+
${name} _load_odf_as_${name}(yaml_document_t *doc, yaml_node_t *node)
|
|
89
|
+
{
|
|
90
|
+
g_assert(node->type == YAML_SCALAR_NODE);
|
|
91
|
+
if (node->type != YAML_SCALAR_NODE) {
|
|
92
|
+
return _${name}Invalid;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
for (int i = 0; i <= ${len(enum.values.parameters)}; i++) {
|
|
96
|
+
if (g_strcmp0(node->data.scalar.value, ${name}_as_string(i)) == 0) {
|
|
97
|
+
return (${name})i;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return _${name}Invalid;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
${name} *_load_odf_as_${name}_v(yaml_document_t *doc, yaml_node_t *node, gsize *n)
|
|
104
|
+
{
|
|
105
|
+
g_assert(doc && node && n);
|
|
106
|
+
yaml_node_t *val;
|
|
107
|
+
gint i = 0;
|
|
108
|
+
if (node->type != YAML_SEQUENCE_NODE) {
|
|
109
|
+
log_warn("Load array ${name} failed because node type error, need type 1(sequence), get type %d", node->type);
|
|
110
|
+
return g_new0(${name}, 1);
|
|
111
|
+
}
|
|
112
|
+
yaml_node_item_t *top = node->data.sequence.items.top;
|
|
113
|
+
yaml_node_item_t *start = node->data.sequence.items.start;
|
|
114
|
+
*n = ((gsize)top - (gsize)start) / sizeof(yaml_node_item_t);
|
|
115
|
+
${name} *output = g_new0(${name}, *n);
|
|
116
|
+
|
|
117
|
+
for (yaml_node_item_t *item = start; item < top; item++) {
|
|
118
|
+
val = yaml_document_get_node(doc, *item);
|
|
119
|
+
output[i++] = _load_odf_as_${name}(doc, val);
|
|
120
|
+
}
|
|
121
|
+
return output;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
% endfor
|
|
125
|
+
## 定义字典ODF加载函数
|
|
126
|
+
% for name, dictionary in intf.dictionaries.items():
|
|
127
|
+
|
|
128
|
+
${name} *_load_odf_as_${name}(yaml_document_t *doc, yaml_node_t *node)
|
|
129
|
+
{
|
|
130
|
+
GHashTable *prop_table = NULL;
|
|
131
|
+
yaml_node_t *val = NULL;
|
|
132
|
+
${name} *dict = ${name}_new();
|
|
133
|
+
yaml_node_item_t *top = node->data.sequence.items.top;
|
|
134
|
+
yaml_node_item_t *start = node->data.sequence.items.start;
|
|
135
|
+
for (yaml_node_item_t *item = start; item < top; item++) {
|
|
136
|
+
val = yaml_document_get_node(doc, *item);
|
|
137
|
+
## 转换成hash表以获取key和properties
|
|
138
|
+
prop_table = load_yaml_mapping_to_hash_table(doc, val);
|
|
139
|
+
yaml_node_t *key = g_hash_table_lookup(prop_table, "key");
|
|
140
|
+
yaml_node_t *properties = g_hash_table_lookup(prop_table, "properties");
|
|
141
|
+
g_hash_table_destroy(prop_table);
|
|
142
|
+
|
|
143
|
+
${", ".join(dictionary.key_obj.declare()).replace("<arg_name>", "key_val").replace("<const>", "")};
|
|
144
|
+
${dictionary.key_obj.odf_load_func().replace("<arg_name>", "key_val").replace("<node>", "key")};
|
|
145
|
+
|
|
146
|
+
## 创建一个新的字典成员
|
|
147
|
+
${name}${dictionary.key} *item = g_new0(${name}${dictionary.key}, 1);
|
|
148
|
+
## 转换成hash表
|
|
149
|
+
prop_table = load_yaml_mapping_to_hash_table(doc, properties);
|
|
150
|
+
## 迭代所有成员并从odf中还原数据
|
|
151
|
+
% for prop in dictionary.values.parameters:
|
|
152
|
+
% if prop.odf_load_func() is not None:
|
|
153
|
+
val = g_hash_table_lookup(prop_table, "${prop.name}");
|
|
154
|
+
if (val)
|
|
155
|
+
${prop.odf_load_func().replace("n_<arg_name>", "item->n_" + prop.name).replace("<arg_name>", "item->" + prop.name).replace("<node>", "val")};
|
|
156
|
+
% endif
|
|
157
|
+
% endfor
|
|
158
|
+
g_hash_table_destroy(prop_table);
|
|
159
|
+
dict->insert(dict, key_val, &item);
|
|
160
|
+
% for line in dictionary.key_obj.free_func():
|
|
161
|
+
${line.replace("<arg_name>", "key_val")};
|
|
162
|
+
% endfor
|
|
163
|
+
}
|
|
164
|
+
return dict;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
${name} **_load_odf_as_${name}_v(yaml_document_t *doc, yaml_node_t *node)
|
|
168
|
+
{
|
|
169
|
+
yaml_node_t *val;
|
|
170
|
+
gint i = 0;
|
|
171
|
+
if (node->type != YAML_SEQUENCE_NODE) {
|
|
172
|
+
log_warn("Load array ${name} failed because node type error, need type 1(sequence), get type %d", node->type);
|
|
173
|
+
return g_new0(${name} *, 1);
|
|
174
|
+
}
|
|
175
|
+
yaml_node_item_t *top = node->data.sequence.items.top;
|
|
176
|
+
yaml_node_item_t *start = node->data.sequence.items.start;
|
|
177
|
+
gsize cnt = ((gsize)top - (gsize)start) / sizeof(yaml_node_item_t);
|
|
178
|
+
${name} **output = g_new0(${name} *, cnt + 1);
|
|
179
|
+
|
|
180
|
+
for (yaml_node_item_t *item = start; item < top; item++) {
|
|
181
|
+
val = yaml_document_get_node(doc, *item);
|
|
182
|
+
output[i++] = _load_odf_as_${name}(doc, val);
|
|
183
|
+
}
|
|
184
|
+
return output;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
% endfor
|
|
188
|
+
static ${class_name}_Properties ${properties};
|
|
189
|
+
static const ${class_name}_Signals *${signal_processer} = NULL;
|
|
190
|
+
|
|
191
|
+
% for prop in intf.properties:
|
|
192
|
+
/* ${prop.description} */
|
|
193
|
+
% if prop.deprecated:
|
|
194
|
+
__attribute__((__deprecated__)) void ${class_name}_set_${prop.name}(const ${class_name} *object,
|
|
195
|
+
${", ".join(prop.declare()).replace("<arg_name>", "value").replace("<const>", "const ")})
|
|
196
|
+
% else:
|
|
197
|
+
void ${class_name}_set_${prop.name}(const ${class_name} *object,
|
|
198
|
+
${", ".join(prop.declare()).replace("<arg_name>", "value").replace("<const>", "const ")})
|
|
199
|
+
% endif
|
|
200
|
+
{
|
|
201
|
+
GVariant *tmp = NULL;
|
|
202
|
+
% for line in prop.encode_func():
|
|
203
|
+
${line.replace("<arg_out>", "tmp").replace("n_<arg_name>", "n_value").replace("<arg_name>", "value")};
|
|
204
|
+
% endfor
|
|
205
|
+
gcl_set_value((GclObject *)object, &_${class_name}_properties.${prop.name}, tmp);
|
|
206
|
+
g_variant_unref(tmp);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
% endfor
|
|
210
|
+
% for signal in intf.signals:
|
|
211
|
+
/*
|
|
212
|
+
* Signal: ${signal.name}
|
|
213
|
+
* ${signal.description}
|
|
214
|
+
*/
|
|
215
|
+
% if signal.deprecated:
|
|
216
|
+
__attribute__((__deprecated__)) gboolean ${class_name}_${signal.name}_Signal(const ${class_name} *object,
|
|
217
|
+
const gchar *destination, const ${class_name}_${signal.name}_Msg *msg, GError **error)
|
|
218
|
+
% else:
|
|
219
|
+
gboolean ${class_name}_${signal.name}_Signal(const ${class_name} *object, const gchar *destination,
|
|
220
|
+
const ${class_name}_${signal.name}_Msg *msg, GError **error)
|
|
221
|
+
% endif
|
|
222
|
+
{
|
|
223
|
+
if (error == NULL) {
|
|
224
|
+
log_error("Emit ${signal.name} with parameter error, error is NULL");
|
|
225
|
+
return FALSE;
|
|
226
|
+
}
|
|
227
|
+
if (object == NULL) {
|
|
228
|
+
*error = g_error_new(G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Emit ${signal.name} with parameter error, object is NULL");
|
|
229
|
+
return FALSE;
|
|
230
|
+
}
|
|
231
|
+
return gcl_impl.emit_signal((GclObject *)object, destination,
|
|
232
|
+
(const GclSignal *)&${signal_processer}->${signal.name}, msg, error);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
% endfor
|
|
236
|
+
static GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque);
|
|
237
|
+
static void _load_from_odf(yaml_document_t *doc, yaml_node_t *node, GclObject *gcl_obj,
|
|
238
|
+
property_reference_loaded ref_loaded, gpointer user_data);
|
|
239
|
+
/*
|
|
240
|
+
* interface: ${intf.name}
|
|
241
|
+
% for c in intf.description.split("\n"):
|
|
242
|
+
* ${c}
|
|
243
|
+
% endfor
|
|
244
|
+
*/
|
|
245
|
+
static GclInterface _${class_name}_interface = {
|
|
246
|
+
.create = _${intf.alias}_create,
|
|
247
|
+
.load_from_odf = (object_load_from_odf)_load_from_odf,
|
|
248
|
+
.is_remote = 0,
|
|
249
|
+
.name = "${intf.name}",
|
|
250
|
+
.properties = (GclProperty *)&${properties},
|
|
251
|
+
.interface = NULL, /* load from usr/share/dbus-1/interfaces/${intf.name} by gcl_init */
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
% for prop in intf.properties:
|
|
255
|
+
static void _load_odf_as_prop_${prop.name}(yaml_document_t *doc, GHashTable *prop_table,
|
|
256
|
+
${class_name} *obj, property_reference_loaded ref_loaded, gpointer user_data)
|
|
257
|
+
{
|
|
258
|
+
const gchar *flags = NULL;
|
|
259
|
+
yaml_node_t *val = g_hash_table_lookup(prop_table, "_${prop.name}_flags");
|
|
260
|
+
if (val && val->type == YAML_SCALAR_NODE) {
|
|
261
|
+
flags = val->data.scalar.value;
|
|
262
|
+
}
|
|
263
|
+
val = g_hash_table_lookup(prop_table, "${prop.name}");
|
|
264
|
+
if (!val) {
|
|
265
|
+
if (flags) {
|
|
266
|
+
ref_loaded(obj, &${properties}.${prop.name}, NULL, NULL, user_data, flags);
|
|
267
|
+
}
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
% if "refobj" in prop.flags:
|
|
271
|
+
ref_loaded(obj, &${properties}.${prop.name}, doc, val, user_data, flags);
|
|
272
|
+
% else:
|
|
273
|
+
if (val->type == YAML_SCALAR_NODE && val->data.scalar.value[0] == '$' &&
|
|
274
|
+
g_regex_match(gcl_ref_prop_regex(), val->data.scalar.value, 0, NULL)) {
|
|
275
|
+
ref_loaded(obj, &${properties}.${prop.name}, doc, val, user_data, flags);
|
|
276
|
+
} else {
|
|
277
|
+
% if prop.odf_load_func() is not None:
|
|
278
|
+
${prop.odf_load_func().replace("n_<arg_name>", "obj->n_" + prop.name).replace("<arg_name>", "obj->" + prop.name).replace("<node>", "val")};
|
|
279
|
+
% endif
|
|
280
|
+
if (flags) {
|
|
281
|
+
ref_loaded(obj, &${properties}.${prop.name}, NULL, NULL, user_data, flags);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
% endif
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
% endfor
|
|
288
|
+
static void _load_from_odf(yaml_document_t *doc, yaml_node_t *node, GclObject *gcl_obj,
|
|
289
|
+
property_reference_loaded ref_loaded, gpointer user_data)
|
|
290
|
+
{
|
|
291
|
+
g_assert(doc && node && gcl_obj);
|
|
292
|
+
if (!gcl_obj) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
<% cnt = 0 %>\
|
|
296
|
+
% for prop in intf.properties:
|
|
297
|
+
% if prop.odf_load_func() is not None:
|
|
298
|
+
<% cnt = cnt + 1 %>\
|
|
299
|
+
% endif
|
|
300
|
+
% endfor
|
|
301
|
+
% if cnt == 0:
|
|
302
|
+
return;
|
|
303
|
+
% else:
|
|
304
|
+
${class_name} *obj = (${class_name} *)gcl_obj;
|
|
305
|
+
${class_name}_clean(obj);
|
|
306
|
+
GHashTable *prop_table = load_yaml_mapping_to_hash_table(doc, node);
|
|
307
|
+
% for prop in intf.properties:
|
|
308
|
+
_load_odf_as_prop_${prop.name}(doc, prop_table, obj, ref_loaded, user_data);
|
|
309
|
+
% endfor
|
|
310
|
+
|
|
311
|
+
g_hash_table_destroy(prop_table);
|
|
312
|
+
% endif
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* @brief 分配对象
|
|
317
|
+
*
|
|
318
|
+
* @param obj_name 对象名,需要由调用者分配内存
|
|
319
|
+
* @param opaque 上层应用需要写入对象的用户数据,由上层应用使用
|
|
320
|
+
*/
|
|
321
|
+
GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque)
|
|
322
|
+
{
|
|
323
|
+
${class_name} *obj = g_new0(${class_name}, 1);
|
|
324
|
+
memcpy(obj->_base.magic, GCL_MAGIC, strlen(GCL_MAGIC) + 1);
|
|
325
|
+
obj->_base.lock = g_new0(GRecMutex, 1);
|
|
326
|
+
g_rec_mutex_init(obj->_base.lock);
|
|
327
|
+
obj->_base.name = obj_name;
|
|
328
|
+
obj->_base.intf = &_${class_name}_interface;
|
|
329
|
+
obj->_base.opaque = opaque;
|
|
330
|
+
return (GclObject *)obj;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
GclInterface *${class_name}_interface(void)
|
|
334
|
+
{
|
|
335
|
+
return &_${class_name}_interface;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
${class_name}_Properties *${class_name}_properties(void)
|
|
339
|
+
{
|
|
340
|
+
return &${properties};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
static void __attribute__((constructor(150))) ${class_name}_register(void)
|
|
344
|
+
{
|
|
345
|
+
|
|
346
|
+
// 从公共库中复制信号处理函数
|
|
347
|
+
${signal_processer} = ${class_name}_signals();
|
|
348
|
+
// 从公共库中复制方法处理函数
|
|
349
|
+
_${class_name}_interface.methods = (GclMethod *)${class_name}_methods();
|
|
350
|
+
_${class_name}_interface.signals = (GclSignal *)${class_name}_signals();
|
|
351
|
+
|
|
352
|
+
// 从公共库中复制属性信息
|
|
353
|
+
memcpy(&${properties}, ${class_name}_properties_const(), sizeof(${properties}));
|
|
354
|
+
gcl_interface_register(&_${class_name}_interface,
|
|
355
|
+
"${intf.introspect_xml_sha256}",
|
|
356
|
+
"/usr/share/dbus-1/interfaces/${intf.name}.xml");
|
|
357
|
+
}
|
|
@@ -33,6 +33,6 @@ class ArgParser():
|
|
|
33
33
|
parser.add_argument(
|
|
34
34
|
"-r", "--remote", default="litebmc", help="Conan仓别名(等同conan的-r选项)")
|
|
35
35
|
parser.add_argument(
|
|
36
|
-
"-c", "--channel", help='Provide a channel if not specified in
|
|
37
|
-
parser.add_argument('-o','--pkg_options', action='append', help='Define options values (host machine), e.g.: -o pkg/*:shared=
|
|
36
|
+
"-c", "--channel", help='Provide a channel if not specified in mds/package.yml\ndefault value: dev', default="dev")
|
|
37
|
+
parser.add_argument('-o','--pkg_options', action='append', help='Define options values (host machine), e.g.: -o pkg/*:shared=True', required=False, default=[])
|
|
38
38
|
return parser
|
|
@@ -8,7 +8,7 @@ from argparse import ArgumentParser
|
|
|
8
8
|
from git import Repo
|
|
9
9
|
from git.exc import InvalidGitRepositoryError
|
|
10
10
|
from mako.lookup import TemplateLookup
|
|
11
|
-
from lbkit.misc import Color
|
|
11
|
+
from lbkit.misc import Color, validate_yml_with_json_schema
|
|
12
12
|
from lbkit import errors
|
|
13
13
|
from lbkit.codegen.codegen import CodeGen
|
|
14
14
|
from lbkit.tools import Tools
|
|
@@ -53,6 +53,7 @@ class BuildComponent():
|
|
|
53
53
|
shutil.rmtree(self.rootfs_dir, ignore_errors=True)
|
|
54
54
|
os.makedirs(self.rootfs_dir, exist_ok=True)
|
|
55
55
|
|
|
56
|
+
self.pkg = None
|
|
56
57
|
self.gen_conaninfo()
|
|
57
58
|
self.base_cmd = f" --user {self.user} --channel {self.channel}"
|
|
58
59
|
self.base_cmd += f" -pr {self.profile} -s build_type={self.build_type} -r " + self.options.remote
|
|
@@ -94,6 +95,10 @@ class BuildComponent():
|
|
|
94
95
|
package_yml = os.path.join(cwd, "metadata/package.yml")
|
|
95
96
|
if not os.path.isfile(package_yml):
|
|
96
97
|
raise FileNotFoundError("metadata/package.yml文件不存在")
|
|
98
|
+
# 验证失败时抛异常,此处不用处理,由外层处理
|
|
99
|
+
validate_yml_with_json_schema(package_yml, "/usr/share/litebmc/schema/cdf.v1.json")
|
|
100
|
+
log.info(f"validate {package_yml} successfully")
|
|
101
|
+
|
|
97
102
|
# 加载package.yml文件
|
|
98
103
|
fp = open(package_yml, "r")
|
|
99
104
|
pkg = yaml.safe_load(fp)
|
|
@@ -104,13 +109,10 @@ class BuildComponent():
|
|
|
104
109
|
# 构建命令未指定channel时从package.yml中读取
|
|
105
110
|
pkg["channel"] = self.channel
|
|
106
111
|
pkg["version"] = self.get_package_version()
|
|
112
|
+
self.pkg = pkg
|
|
107
113
|
# 从package.yml加载基础信息
|
|
108
114
|
self.name = pkg.get("name")
|
|
109
|
-
if self.name is None:
|
|
110
|
-
raise errors.PackageConfigException("metadata/package.yml未配置name属性")
|
|
111
115
|
self.version = pkg.get("version")
|
|
112
|
-
if self.version is None:
|
|
113
|
-
raise errors.PackageConfigException("metadata/package.yml未配置version属性")
|
|
114
116
|
|
|
115
117
|
self.package = self.name + "/" + self.version + \
|
|
116
118
|
"@" + self.user + "/" + self.channel
|
|
@@ -156,7 +158,7 @@ class BuildComponent():
|
|
|
156
158
|
# 生成部署deploy命令
|
|
157
159
|
lookup = TemplateLookup(directories=os.path.join(lb_cwd, "template"))
|
|
158
160
|
template = lookup.get_template("deploy.mako")
|
|
159
|
-
deploy = template.render(lookup=lookup, packages=self.runtime_packages)
|
|
161
|
+
deploy = template.render(lookup=lookup, pkg=self.pkg, packages=self.runtime_packages)
|
|
160
162
|
dir = os.path.join(cwd, ".temp", "deploy")
|
|
161
163
|
# 创建临时目录并写入conanfile.py文件
|
|
162
164
|
os.makedirs(dir, exist_ok=True)
|
|
@@ -178,7 +180,7 @@ class BuildComponent():
|
|
|
178
180
|
template = lookup.get_template("deploy.mako")
|
|
179
181
|
packages = self.runtime_packages
|
|
180
182
|
packages.append(self.package)
|
|
181
|
-
deploy = template.render(lookup=lookup, packages=packages)
|
|
183
|
+
deploy = template.render(lookup=lookup, pkg=self.pkg, packages=packages)
|
|
182
184
|
dir = os.path.join(cwd, ".temp", "deploy")
|
|
183
185
|
# 创建临时目录并写入conanfile.py文件
|
|
184
186
|
os.makedirs(dir, exist_ok=True)
|
|
@@ -202,7 +204,26 @@ class BuildComponent():
|
|
|
202
204
|
# 设置ROOTFS_DIR环境变量,为DT测试提供相对路径
|
|
203
205
|
os.environ["ROOTFS_DIR"] = self.rootfs_dir
|
|
204
206
|
|
|
207
|
+
def _validate_odf_files(self):
|
|
208
|
+
odf_dirs = self.pkg.get("odf_dirs", [])
|
|
209
|
+
for dir in odf_dirs:
|
|
210
|
+
for filename in os.listdir(dir):
|
|
211
|
+
filename = os.path.join(dir, filename)
|
|
212
|
+
if not os.path.isfile(filename):
|
|
213
|
+
continue
|
|
214
|
+
if not filename.endswith(".yaml"):
|
|
215
|
+
log.debug(f"file {filename} not endswith .yaml, skip validate")
|
|
216
|
+
continue
|
|
217
|
+
|
|
218
|
+
log.info(f"start validate {filename}")
|
|
219
|
+
validate_yml_with_json_schema(filename, "/usr/share/litebmc/schema/odf.v1.json")
|
|
220
|
+
|
|
205
221
|
def run(self):
|
|
222
|
+
# start validate all odf(Object Description file) files
|
|
223
|
+
self._validate_odf_files()
|
|
224
|
+
|
|
225
|
+
cmd = f"conan remove {self.package} -c"
|
|
226
|
+
tools.exec(cmd)
|
|
206
227
|
gen = CodeGen([])
|
|
207
228
|
gen.run("./metadata/package.yml")
|
|
208
229
|
self._build_dependencies()
|
|
@@ -114,6 +114,28 @@ class LiteBmcConan(ConanFile):
|
|
|
114
114
|
% endif
|
|
115
115
|
pass
|
|
116
116
|
|
|
117
|
+
def configure(self):
|
|
118
|
+
% if len(pkg.get("requires", {})) > 0:
|
|
119
|
+
% for conan in pkg["requires"].get("compile", []):
|
|
120
|
+
% if conan.get("option") is not None:
|
|
121
|
+
% for k, v in conan.get("option").items():
|
|
122
|
+
self.options["${conan.get("conan").split("/")[0]}"].${k} = ${("\"" + v + "\"") if isinstance(v, str) else str(v)}
|
|
123
|
+
% endfor
|
|
124
|
+
% endif
|
|
125
|
+
% endfor
|
|
126
|
+
<%test_requires=pkg["requires"].get("test", [])%>\
|
|
127
|
+
% if len(test_requires):
|
|
128
|
+
% for conan in test_requires:
|
|
129
|
+
% if conan.get("option") is not None:
|
|
130
|
+
% for k, v in conan.get("option").items():
|
|
131
|
+
self.options["${conan.get("conan").split("/")[0]}"].${k} = ${("\"" + v + "\"") if isinstance(v, str) else str(v)}
|
|
132
|
+
% endfor
|
|
133
|
+
% endif
|
|
134
|
+
% endfor
|
|
135
|
+
% endif
|
|
136
|
+
% endif
|
|
137
|
+
pass
|
|
138
|
+
|
|
117
139
|
def _append_default_flags(self):
|
|
118
140
|
flags = []
|
|
119
141
|
if self.options.gcov:
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from conan import ConanFile
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DeployConan(ConanFile):
|
|
5
|
+
name = "deploy"
|
|
6
|
+
settings = "os", "arch", "compiler", "build_type"
|
|
7
|
+
description = "部署组件"
|
|
8
|
+
url = "https://litebmc.com"
|
|
9
|
+
homepage = ""
|
|
10
|
+
generators = "CMakeDeps"
|
|
11
|
+
package_type = "application"
|
|
12
|
+
version = "0.0.1"
|
|
13
|
+
license = "MulanPSL v2"
|
|
14
|
+
|
|
15
|
+
def requirements(self):
|
|
16
|
+
% for package in packages:
|
|
17
|
+
self.requires("${package}")
|
|
18
|
+
% endfor
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
def configure(self):
|
|
22
|
+
% if len(pkg.get("requires", {})) > 0:
|
|
23
|
+
% for conan in pkg["requires"].get("compile", []):
|
|
24
|
+
% if conan.get("option") is not None:
|
|
25
|
+
% for k, v in conan.get("option").items():
|
|
26
|
+
self.options["${conan.get("conan").split("/")[0]}"].${k} = ${("\"" + v + "\"") if isinstance(v, str) else str(v)}
|
|
27
|
+
% endfor
|
|
28
|
+
% endif
|
|
29
|
+
% endfor
|
|
30
|
+
<%test_requires=pkg["requires"].get("test", [])%>\
|
|
31
|
+
% if len(test_requires):
|
|
32
|
+
% for conan in test_requires:
|
|
33
|
+
% if conan.get("option") is not None:
|
|
34
|
+
% for k, v in conan.get("option").items():
|
|
35
|
+
self.options["${conan.get("conan").split("/")[0]}"].${k} = ${("\"" + v + "\"") if isinstance(v, str) else str(v)}
|
|
36
|
+
% endfor
|
|
37
|
+
% endif
|
|
38
|
+
% endfor
|
|
39
|
+
% endif
|
|
40
|
+
% endif
|
|
41
|
+
pass
|
|
42
|
+
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import argparse
|
|
3
3
|
import textwrap
|
|
4
|
+
import json
|
|
5
|
+
import yaml
|
|
6
|
+
import re
|
|
7
|
+
import requests
|
|
4
8
|
from colorama import Fore, Style
|
|
5
|
-
|
|
9
|
+
from jsonschema import validate, ValidationError
|
|
10
|
+
from lbkit.errors import PackageConfigException, HttpRequestException
|
|
6
11
|
|
|
7
12
|
LOG_DIR = "/tmp/lbkit/log"
|
|
8
13
|
|
|
14
|
+
|
|
9
15
|
class Color(object):
|
|
10
16
|
""" Wrapper around colorama colors that are undefined in importing
|
|
11
17
|
"""
|
|
@@ -43,3 +49,35 @@ class SmartFormatter(argparse.HelpFormatter):
|
|
|
43
49
|
"""重写HelpFormatter"""
|
|
44
50
|
text = textwrap.dedent(text)
|
|
45
51
|
return ''.join(indent + line for line in text.splitlines(True))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def validate_yml_with_json_schema(yml_file, default_json_schema_file):
|
|
55
|
+
"""使用json schema文件校验yml_file配置文件"""
|
|
56
|
+
schema_file = None
|
|
57
|
+
with open(yml_file, "r") as fp:
|
|
58
|
+
for line in fp:
|
|
59
|
+
match = re.search(r"#[ ]*yaml-language-server:[ ]*\$schema=(.*)\n", line)
|
|
60
|
+
if match is not None:
|
|
61
|
+
schema_file = match.group(1)
|
|
62
|
+
break
|
|
63
|
+
if schema_file is None:
|
|
64
|
+
schema_file = default_json_schema_file
|
|
65
|
+
if schema_file.startswith("https://litebmc.com/"):
|
|
66
|
+
resp = requests.get(schema_file)
|
|
67
|
+
if resp.status_code != 200:
|
|
68
|
+
raise HttpRequestException(f"Get {schema_file} failed, status code: {resp.status_code}")
|
|
69
|
+
schema = json.loads(resp.content)
|
|
70
|
+
elif not os.path.isfile(schema_file):
|
|
71
|
+
raise FileNotFoundError(f"schemafile {schema_file} not exist")
|
|
72
|
+
else:
|
|
73
|
+
with open(schema_file, "r") as fp:
|
|
74
|
+
tmp = fp.read()
|
|
75
|
+
schema = json.loads(tmp)
|
|
76
|
+
try:
|
|
77
|
+
fp = open(yml_file, "r")
|
|
78
|
+
data = yaml.safe_load(fp)
|
|
79
|
+
validate(data, schema)
|
|
80
|
+
except ValidationError as exc:
|
|
81
|
+
raise PackageConfigException(f"validate {yml_file} failed, schema file is {schema_file}, "
|
|
82
|
+
f"message: {exc.message}\n"
|
|
83
|
+
"installing redhat.vscode-yaml plugin in vscode will help you write odf files")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lbkit
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.5
|
|
4
4
|
Summary: Tools provided by litebmc.com
|
|
5
5
|
Home-page: https://www.litebmc.com
|
|
6
6
|
Author: xuhj@litebmc.com
|
|
@@ -19,5 +19,6 @@ Requires-Dist: jsonschema
|
|
|
19
19
|
Requires-Dist: conan==2.1
|
|
20
20
|
Requires-Dist: requests
|
|
21
21
|
Requires-Dist: gitpython
|
|
22
|
+
Requires-Dist: inflection
|
|
22
23
|
|
|
23
24
|
build and code generate tools
|
|
@@ -19,7 +19,7 @@ setup(
|
|
|
19
19
|
description="Tools provided by litebmc.com",
|
|
20
20
|
long_description="build and code generate tools",
|
|
21
21
|
long_description_content_type="text/markdown",
|
|
22
|
-
install_requires=["pyyaml", "colorama", "mako", "node-semver==0.6.1", "jsonschema", "conan==2.1", "requests", "gitpython"],
|
|
22
|
+
install_requires=["pyyaml", "colorama", "mako", "node-semver==0.6.1", "jsonschema", "conan==2.1", "requests", "gitpython", "inflection"],
|
|
23
23
|
url="https://www.litebmc.com",
|
|
24
24
|
packages=find_packages(),
|
|
25
25
|
include_package_data=True,
|
lbkit-0.5.2/lbkit/__init__.py
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
#include "gcl_base.h"
|
|
2
|
-
#include "${intf.name}.h"
|
|
3
|
-
|
|
4
|
-
<%
|
|
5
|
-
class_name = intf.alias
|
|
6
|
-
properties = "_" + class_name + "_properties"
|
|
7
|
-
signal_processer = "_" + class_name + "_signals"
|
|
8
|
-
%>\
|
|
9
|
-
static ${class_name}_Properties ${properties};
|
|
10
|
-
static const ${class_name}_Signals *${signal_processer} = NULL;
|
|
11
|
-
|
|
12
|
-
% for prop in intf.properties:
|
|
13
|
-
/* ${prop.description} */
|
|
14
|
-
% if prop.deprecated:
|
|
15
|
-
__attribute__((__deprecated__)) void ${class_name}_set_${prop.name}(const ${class_name} *object,
|
|
16
|
-
${", ".join(prop.declare()).replace("<arg_name>", "value").replace("<const>", "const ")})
|
|
17
|
-
% else:
|
|
18
|
-
void ${class_name}_set_${prop.name}(const ${class_name} *object,
|
|
19
|
-
${", ".join(prop.declare()).replace("<arg_name>", "value").replace("<const>", "const ")})
|
|
20
|
-
% endif
|
|
21
|
-
{
|
|
22
|
-
GVariant *tmp = NULL;
|
|
23
|
-
% for line in prop.encode_func():
|
|
24
|
-
${line.replace("<arg_out>", "tmp").replace("n_<arg_name>", "n_value").replace("<arg_name>", "value")};
|
|
25
|
-
% endfor
|
|
26
|
-
gcl_set_value((GclObject *)object, &_${class_name}_properties.${prop.name}, tmp);
|
|
27
|
-
g_variant_unref(tmp);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
% endfor
|
|
31
|
-
% for signal in intf.signals:
|
|
32
|
-
/*
|
|
33
|
-
* Signal: ${signal.name}
|
|
34
|
-
* ${signal.description}
|
|
35
|
-
*/
|
|
36
|
-
% if signal.deprecated:
|
|
37
|
-
__attribute__((__deprecated__)) gboolean ${class_name}_${signal.name}_Signal(const ${class_name} *object,
|
|
38
|
-
const gchar *destination, const ${class_name}_${signal.name}_Msg *msg, GError **error)
|
|
39
|
-
% else:
|
|
40
|
-
gboolean ${class_name}_${signal.name}_Signal(const ${class_name} *object, const gchar *destination,
|
|
41
|
-
const ${class_name}_${signal.name}_Msg *msg, GError **error)
|
|
42
|
-
% endif
|
|
43
|
-
{
|
|
44
|
-
if (error == NULL) {
|
|
45
|
-
log_error("Emit ${signal.name} with parameter error, error is NULL");
|
|
46
|
-
return FALSE;
|
|
47
|
-
}
|
|
48
|
-
if (object == NULL) {
|
|
49
|
-
*error = g_error_new(G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Emit ${signal.name} with parameter error, object is NULL");
|
|
50
|
-
return FALSE;
|
|
51
|
-
}
|
|
52
|
-
return gcl_impl.emit_signal((GclObject *)object, destination,
|
|
53
|
-
(const GclSignal *)&${signal_processer}->${signal.name}, msg, error);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
% endfor
|
|
57
|
-
static GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque);
|
|
58
|
-
/*
|
|
59
|
-
* interface: ${intf.name}
|
|
60
|
-
% for c in intf.description.split("\n"):
|
|
61
|
-
* ${c}
|
|
62
|
-
% endfor
|
|
63
|
-
*/
|
|
64
|
-
static GclInterface _${class_name}_interface = {
|
|
65
|
-
.create = _${intf.alias}_create,
|
|
66
|
-
.is_remote = 0,
|
|
67
|
-
.name = "${intf.name}",
|
|
68
|
-
.properties = (GclProperty *)&${properties},
|
|
69
|
-
.interface = NULL, /* load from usr/share/dbus-1/interfaces/${intf.name} by gcl_init */
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* @brief 分配对象
|
|
74
|
-
*
|
|
75
|
-
* @param obj_name 对象名,需要由调用者分配内存
|
|
76
|
-
* @param opaque 上层应用需要写入对象的用户数据,由上层应用使用
|
|
77
|
-
*/
|
|
78
|
-
GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque)
|
|
79
|
-
{
|
|
80
|
-
${class_name} *obj = g_new0(${class_name}, 1);
|
|
81
|
-
memcpy(obj->_base.magic, GCL_MAGIC, strlen(GCL_MAGIC) + 1);
|
|
82
|
-
obj->_base.lock = g_new0(GRecMutex, 1);
|
|
83
|
-
g_rec_mutex_init(obj->_base.lock);
|
|
84
|
-
obj->_base.name = obj_name;
|
|
85
|
-
obj->_base.intf = &_${class_name}_interface;
|
|
86
|
-
obj->_base.opaque = opaque;
|
|
87
|
-
return (GclObject *)obj;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
GclInterface *${class_name}_interface(void)
|
|
91
|
-
{
|
|
92
|
-
return &_${class_name}_interface;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
${class_name}_Properties *${class_name}_properties(void)
|
|
96
|
-
{
|
|
97
|
-
return &${properties};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
static void __attribute__((constructor(150))) ${class_name}_register(void)
|
|
101
|
-
{
|
|
102
|
-
// 从公共库中复制信号处理函数
|
|
103
|
-
${signal_processer} = ${class_name}_signals();
|
|
104
|
-
// 从公共库中复制方法处理函数
|
|
105
|
-
_${class_name}_interface.methods = (GclMethod *)${class_name}_methods();
|
|
106
|
-
_${class_name}_interface.signals = (GclSignal *)${class_name}_signals();
|
|
107
|
-
|
|
108
|
-
// 从公共库中复制属性信息
|
|
109
|
-
memcpy(&${properties}, ${class_name}_properties_const(), sizeof(${properties}));
|
|
110
|
-
gcl_interface_register(&_${class_name}_interface,
|
|
111
|
-
"${intf.introspect_xml_sha256}",
|
|
112
|
-
"/usr/share/dbus-1/interfaces/${intf.name}.xml");
|
|
113
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
from conan import ConanFile
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class DeployConan(ConanFile):
|
|
5
|
-
name = "deploy"
|
|
6
|
-
settings = "os", "arch", "compiler", "build_type"
|
|
7
|
-
description = "部署组件"
|
|
8
|
-
url = "https://litebmc.com"
|
|
9
|
-
homepage = ""
|
|
10
|
-
generators = "CMakeDeps"
|
|
11
|
-
package_type = "application"
|
|
12
|
-
version = "0.0.1"
|
|
13
|
-
license = "MulanPSL v2"
|
|
14
|
-
|
|
15
|
-
def requirements(self):
|
|
16
|
-
% for package in packages:
|
|
17
|
-
self.requires("${package}")
|
|
18
|
-
% endfor
|
|
19
|
-
pass
|
|
20
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|