mirror of
https://github.com/openharmony/developtools_syscap_codec.git
synced 2026-08-27 02:11:19 -04:00
@@ -27,7 +27,10 @@ Main function:
|
||||
│ │ ├── main.c # command line implement
|
||||
│ │ └── syscap_tool.c # codec implement
|
||||
│ └── test
|
||||
│ └── syscap_tool_test.c # syscap_tool test codec implement
|
||||
│ | └── syscap_tool_test.c # syscap_tool test codec implement
|
||||
| |—— tools
|
||||
| │ │
|
||||
| │ └── syscap_check.py # syscap一致性检查脚本
|
||||
```
|
||||
|
||||
### API
|
||||
@@ -79,6 +82,42 @@ SysCap tools usually integrate to IDE, APP store and bundle tools. Follow instru
|
||||
-o outpath, --input outpath : output path
|
||||
```
|
||||
|
||||
## Syscap consistency check tool
|
||||
|
||||
### Functions and dependencies
|
||||
|
||||
The tool provides the following functions:
|
||||
|
||||
1. Collect syscap fields of all components (or specified components), compare them with arraySyscap in developtools/ syscap_codec/include/syscap_define.h, and output the check results. If they are inconsistent, output the cause of the discrepancy.
|
||||
2. Collect the syscap fields of all components and compare them with the @syscap property set in *.d.ts in the Interface/sdk-js/api directory. If the check results are inconsistent, output the cause of the inconsistency.
|
||||
3. Compare syscap attributes in *.d.ts in all interface/ sdK-JS/API directories with arraySyscap in developtools/syscap_codec/include/syscap_define.h. If they are inconsistent, output the cause of the inconsistency.
|
||||
|
||||
### How to use it
|
||||
|
||||
This tool is written in Python language and needs to be executed using the Python interpreter.
|
||||
|
||||
requirements:
|
||||
|
||||
```txt
|
||||
prettytable==3.3.0
|
||||
```
|
||||
|
||||
usage:
|
||||
|
||||
```shell
|
||||
# check syscap field in all components for consistency with arraySyscap in syscap_define.h
|
||||
python3 syscap_check.py -p path_of_openarmony -t component_codec
|
||||
|
||||
# check that the SYSCAP field in bundle.json of the specified part is consistent with arraySyscap in syscap_define.h. Note: --bundles is valid only if --check_target is component_codec
|
||||
python3 syscap_check.py -p path_of_openarmony -t component_codec -b path_of_component1/bundle.json path_of_component2/bundle.json
|
||||
|
||||
# check the consistency of the syscap field of all components with the "@syscap" property set in *.d.ts
|
||||
python3 syscap_check.py -p path_of_openarmony -t component_sdk
|
||||
|
||||
# check the "@syscap" attribute set in *.d.ts for consistency with arraSyscap in syscap_define.h
|
||||
python3 syscap_check.py -p path_of_openarmony -t sdk_codec
|
||||
```
|
||||
|
||||
### Release Note
|
||||
|
||||
v1.0.0 2022-3-8 first release, SysCap codec supported for Windows/Linux/Mac host.
|
||||
v1.0.0 2022-3-8 first release, SysCap codec supported for Windows/Linux/Mac host.
|
||||
|
||||
+60
-1
@@ -1,4 +1,5 @@
|
||||
# 系统能力编解码工具
|
||||
|
||||
系统能力(SystemCapability, 本文中使用SysCap缩写)编解码工具应用场景如下:
|
||||
|
||||
应用开发时,IDE会根据应用配置的SysCap和API版本生成描述RPCID(Required Product Compatibility ID)的json文件,并调用编解码工具syscap_tool将该json文件编码成RPCID。另一方面,IDE拿到开发者导入PCID(Product Compatibility ID),使用该工具解码出设备的SysCap集合。该工具仅供IDE使用,对用户不可见。
|
||||
@@ -43,6 +44,9 @@
|
||||
│ │ │ │ └── syscap_codec_test.h
|
||||
│ │ │ └── syscap_codec_test.cpp
|
||||
│ │ └── syscap_tool_test.c # syscap_tool功能测试代码实现
|
||||
| |—— tools
|
||||
| │ │
|
||||
| │ └── syscap_check.py # syscap一致性检查脚本
|
||||
```
|
||||
|
||||
## API
|
||||
@@ -113,6 +117,61 @@ syscap_tool -Pdsi pcid.txt -o path/
|
||||
```
|
||||
**说明:** -o 选项指定输出目录,缺省为当前目录。
|
||||
|
||||
## syscap一致性检查工具
|
||||
|
||||
### 功能及依赖
|
||||
|
||||
本工具主要提供如下功能:
|
||||
|
||||
1. 收集所有部件(或指定部件)的syscap字段并与developtools/sysap_codec/include/syscap_define.h中的arraySyscap比较,输出检查结果,若不一致,输出不一致的原因
|
||||
2. 收集所有部件的syscap字段并与interface/sdk-js/api目录下的*.d.ts中的“@syscap”属性集合比较,输出检查结果,若不一致,输出不一致的原因
|
||||
3. 收集所有interface/sdk-js/api目录下的*.d.ts中的syscap属性与developtools/syscap_codec/include/syscap_define.h中的arraySyscap比较,若不一致,输出不一致的原因
|
||||
|
||||
### 使用方法
|
||||
|
||||
本工具使用python语言编写,需使用python解释器进行执行。
|
||||
|
||||
requirements:
|
||||
|
||||
```txt
|
||||
prettytable==3.3.0
|
||||
```
|
||||
|
||||
使用python3 syscap-check.py -h或python3 syscap-check.py --help查看用法:
|
||||
|
||||
```shell
|
||||
usage: syscap_check.py [-h] [-p PROJECT_PATH] -t {component_codec,component_sdk,sdk_codec}
|
||||
[-b [BUNDLES [BUNDLES ...]]]
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-p PROJECT_PATH, --project_path PROJECT_PATH
|
||||
root path of project. default: ./
|
||||
-t {component_codec,component_sdk,sdk_codec}, --check_target {component_codec,component_sdk,sdk_codec}
|
||||
the target to be compared
|
||||
-b [BUNDLES [BUNDLES ...]], --bundles [BUNDLES [BUNDLES ...]]
|
||||
this option will take effect only when the check_target is component_codec. allow multiple
|
||||
json file. default: all bundle.json file
|
||||
```
|
||||
|
||||
使用示例:
|
||||
|
||||
```shell
|
||||
# 检查所有部件的syscap字段与syscap_define.h中的arraySyscap一致性情况
|
||||
python3 syscap_check.py -p path_of_openarmony -t component_codec
|
||||
|
||||
# 检查指定的部件的bundle.json中的syscap字段与syscap_define.h中的arraySyscap一致性情况,注意,只要当--check_target为component_codec时,--bundles才生效
|
||||
python3 syscap_check.py -p path_of_openarmony -t component_codec -b path_of_component1/bundle.json path_of_component2/bundle.json
|
||||
|
||||
# 检查所有部件的syscap字段与*.d.ts中的“@syscap”属性集合的一致性情况
|
||||
python3 syscap_check.py -p path_of_openarmony -t component_sdk
|
||||
|
||||
# 检查*.d.ts中的“@syscap"属性集合与syscap_define.h中的arraSyscap的一致性情况
|
||||
python3 syscap_check.py -p path_of_openarmony -t sdk_codec
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Release Note
|
||||
v1.1.0 2022-6-17 添加转字符串格式以及比较功能。
|
||||
v1.0.0 2022-3-8 首版本,提供Windows/Linux/Mac平台的系统能力编解码。
|
||||
v1.0.0 2022-3-8 首版本,提供Windows/Linux/Mac平台的系统能力编解码。
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
prettytable==3.3.0
|
||||
Executable
+296
@@ -0,0 +1,296 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import argparse
|
||||
from prettytable import PrettyTable, ALL
|
||||
|
||||
table = PrettyTable()
|
||||
table.hrules = ALL
|
||||
|
||||
|
||||
def get_args():
|
||||
parser = argparse.ArgumentParser(add_help=True)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--project_path",
|
||||
default=r"./",
|
||||
type=str,
|
||||
help="root path of project. default: ./",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--check_target",
|
||||
type=str,
|
||||
choices=["component_codec", "component_sdk", "sdk_codec"],
|
||||
required=True,
|
||||
help="the target to be compared",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--bundles",
|
||||
nargs="*",
|
||||
type=str,
|
||||
help="this option will take effect only when the check_target is component_codec. allow multiple json file. default: all bundle.json file",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def list_to_multiline(l):
|
||||
return str(l).lstrip("[").rstrip("]").replace(", ", "\n")
|
||||
|
||||
|
||||
def read_value_from_json(filepath, key_hierarchy, result_dict):
|
||||
"""
|
||||
:param result_dict: result_dict
|
||||
:param key_hierarchy: key_hierarchy list
|
||||
:param filepath: fullpath of file
|
||||
:return: result_dict, {filepath:value_list}
|
||||
"""
|
||||
if os.path.exists(filepath) is False:
|
||||
print('error: file "{}" not exists.'.format(filepath))
|
||||
return result_dict
|
||||
if os.path.isfile(filepath) is False:
|
||||
print('error: "{}" is not a file.')
|
||||
return result_dict
|
||||
with open(filepath, "r") as f:
|
||||
data = json.load(f)
|
||||
for key in key_hierarchy:
|
||||
try:
|
||||
data = data[key]
|
||||
except KeyError:
|
||||
print(
|
||||
'warning: can\'t find the key:"{}" in file "{}"'.format(
|
||||
key, filepath
|
||||
)
|
||||
)
|
||||
return result_dict
|
||||
data = [x for x in data if len(x) != 0 and x.isspace() == False]
|
||||
if len(data) != 0:
|
||||
result_dict[filepath] = data
|
||||
return result_dict
|
||||
|
||||
|
||||
def collect_syscap_from_codec(filepath):
|
||||
arraySyscap_set = set()
|
||||
pattern = r'{"(.*)"'
|
||||
with open(filepath, "r") as f:
|
||||
for line in f:
|
||||
syscap = re.search(pattern, line.strip())
|
||||
if syscap is not None:
|
||||
arraySyscap_set.add(syscap.group(0).lstrip("{").strip('"'))
|
||||
return arraySyscap_set
|
||||
|
||||
|
||||
def collect_syscap_from_component(project_path, bundles=None):
|
||||
result_dict = dict()
|
||||
key_heirarchy = ["component", "syscap"]
|
||||
if bundles is None:
|
||||
subsystem_list = [
|
||||
x
|
||||
for x in os.listdir(project_path)
|
||||
if os.path.isdir(os.path.join(project_path, x)) and x != "out"
|
||||
]
|
||||
for ss in subsystem_list:
|
||||
output = os.popen(
|
||||
"find {} -name bundle.json".format(os.path.join(project_path, ss))
|
||||
)
|
||||
for line in output:
|
||||
try:
|
||||
read_value_from_json(line.strip(), key_heirarchy, result_dict)
|
||||
except Exception as e:
|
||||
print(e.with_traceback())
|
||||
else:
|
||||
for b in bundles:
|
||||
try:
|
||||
result_dict = read_value_from_json(b, key_heirarchy, result_dict)
|
||||
except Exception as e:
|
||||
print(e.with_traceback())
|
||||
result_set = set()
|
||||
for v in result_dict.values():
|
||||
result_set.update(v)
|
||||
return result_set, result_dict
|
||||
|
||||
|
||||
def collect_syscap_from_sdk(project_path):
|
||||
full_path = os.path.join(project_path, "interface", "sdk-js", "api")
|
||||
ts_list = [
|
||||
os.path.join(full_path, x) for x in os.listdir(full_path) if x.endswith(".d.ts")
|
||||
]
|
||||
syscap_dict = dict()
|
||||
pattern = r"\* *@syscap +(.*)"
|
||||
syscap_set = set()
|
||||
for ts in ts_list:
|
||||
with open(ts, "r") as f:
|
||||
sub_set = set()
|
||||
for line in f:
|
||||
syscap = re.search(pattern, line)
|
||||
if syscap is not None:
|
||||
ss = syscap.group(0).strip().lstrip("\* @syscap ").strip()
|
||||
sub_set.add(ss)
|
||||
syscap_dict[ts] = sub_set
|
||||
for v in syscap_dict.values():
|
||||
syscap_set.update(v)
|
||||
return syscap_set, syscap_dict
|
||||
|
||||
|
||||
def find_files_containes_value(value_set, file_values_dict):
|
||||
value_files_dict = dict()
|
||||
for v in value_set:
|
||||
filename_set = set()
|
||||
for file in file_values_dict.keys():
|
||||
if v in file_values_dict[file]:
|
||||
filename_set.add(file)
|
||||
if 0 != len(filename_set):
|
||||
value_files_dict[v] = filename_set
|
||||
return value_files_dict
|
||||
|
||||
|
||||
def check_component_and_codec(project_path, bundles=None):
|
||||
if bundles is not None and len(bundles) > 0:
|
||||
component_syscap_set, component_syscap_dict = collect_syscap_from_component(
|
||||
project_path, bundles
|
||||
)
|
||||
else:
|
||||
component_syscap_set, component_syscap_dict = collect_syscap_from_component(
|
||||
project_path
|
||||
)
|
||||
arraySyscap_set = collect_syscap_from_codec(
|
||||
os.path.join(
|
||||
project_path, "developtools", "syscap_codec", "include", "syscap_define.h"
|
||||
)
|
||||
)
|
||||
component_diff_array = component_syscap_set.difference(arraySyscap_set)
|
||||
value_files_dict = find_files_containes_value(
|
||||
component_diff_array, component_syscap_dict
|
||||
)
|
||||
array_diff_component = arraySyscap_set.difference(component_syscap_set)
|
||||
if 0 == len(component_diff_array) and 0 == len(array_diff_component):
|
||||
table.clear()
|
||||
table.field_names = ["Component and Codec are Consistent"]
|
||||
print(table)
|
||||
return
|
||||
if 0 != len(component_diff_array):
|
||||
table.field_names = ["Syscap Only in Component", "Files"]
|
||||
for syscap, files in value_files_dict.items():
|
||||
table.add_row([syscap, list_to_multiline(sorted(files))])
|
||||
elif 0 == len(component_diff_array):
|
||||
table.field_names = ["All Syscap in Component have been Covered by Codec"]
|
||||
print("\n")
|
||||
print(table)
|
||||
table.clear()
|
||||
if 0 != len(array_diff_component):
|
||||
table.field_names = ["SysCap Only in Codec"]
|
||||
table.add_row([list_to_multiline(sorted(list(array_diff_component)))])
|
||||
elif 0 == len(array_diff_component):
|
||||
table.field_names = ["All SysCap in Codec have been Covered by Component"]
|
||||
print("\n")
|
||||
print(table)
|
||||
|
||||
|
||||
def check_component_and_sdk(project_path):
|
||||
component_syscap_set, component_syscap_dict = collect_syscap_from_component(
|
||||
project_path
|
||||
)
|
||||
ts_syscap_set, ts_syscap_dict = collect_syscap_from_sdk(project_path)
|
||||
ts_diff_component = ts_syscap_set.difference(component_syscap_set)
|
||||
value_ts_dict = find_files_containes_value(ts_diff_component, ts_syscap_dict)
|
||||
component_diff_ts = component_syscap_set.difference(ts_syscap_set)
|
||||
value_component_dict = find_files_containes_value(
|
||||
component_diff_ts, component_syscap_dict
|
||||
)
|
||||
if 0 == len(ts_diff_component) and 0 == len(component_diff_ts):
|
||||
table.clear()
|
||||
table.field_names = ["SDK and Component are Consistent"]
|
||||
print(table)
|
||||
return
|
||||
table.clear()
|
||||
if 0 != len(component_diff_ts):
|
||||
table.field_names = ["SysCap Only in Component", "Files"]
|
||||
for syscap, files in value_component_dict.items():
|
||||
table.add_row([syscap, list_to_multiline(sorted(list(files)))])
|
||||
elif 0 == len(component_diff_ts):
|
||||
table.field_names = ["SysCap in Component have been Covered by SDK"]
|
||||
print("\n")
|
||||
print(table)
|
||||
table.clear()
|
||||
if 0 != len(ts_diff_component):
|
||||
table.field_names = ["SysCap Only in SDK", "Files"]
|
||||
for syscap, files in value_ts_dict.items():
|
||||
table.add_row([syscap, list_to_multiline(sorted(list(files)))])
|
||||
elif 0 == len(ts_diff_component):
|
||||
table.field_names = ["All SysCap in SDK have been Covered by Component"]
|
||||
print("\n")
|
||||
print(table)
|
||||
|
||||
|
||||
def check_sdk_and_codec(project_path):
|
||||
ts_syscap_set, ts_syscap_dict = collect_syscap_from_sdk(project_path)
|
||||
arraySyscap_set = collect_syscap_from_codec(
|
||||
os.path.join(
|
||||
project_path, "developtools", "syscap_codec", "include", "syscap_define.h"
|
||||
)
|
||||
)
|
||||
ts_diff_array = ts_syscap_set.difference(arraySyscap_set)
|
||||
value_ts_dict = find_files_containes_value(ts_diff_array, ts_syscap_dict)
|
||||
array_diff_ts = arraySyscap_set.difference(ts_syscap_set)
|
||||
if 0 == len(ts_diff_array) and 0 == len(array_diff_ts):
|
||||
table.clear()
|
||||
table.field_names = ["SDK and Codec are Consistent"]
|
||||
print(table)
|
||||
return
|
||||
table.clear()
|
||||
if 0 != len(ts_diff_array):
|
||||
table.field_names = ["SysCap Only in SDK", "Files"]
|
||||
for syscap, files in value_ts_dict.items():
|
||||
table.add_row([syscap, list_to_multiline(sorted(list(files)))])
|
||||
elif 0 == len(ts_diff_array):
|
||||
table.field_names = ["SysCap in SDK have been Covered by Codec"]
|
||||
print("\n")
|
||||
print(table)
|
||||
table.clear()
|
||||
if 0 != len(array_diff_ts):
|
||||
table.field_names = ["SysCap Only in Codec"]
|
||||
table.add_row([list_to_multiline(sorted(list(array_diff_ts)))])
|
||||
elif 0 == len(array_diff_ts):
|
||||
table.field_names = ["SysCap in Codec have been Covered by SDK"]
|
||||
print("\n")
|
||||
print(table)
|
||||
|
||||
|
||||
def main():
|
||||
args = get_args()
|
||||
project_path = args.project_path
|
||||
check_target = args.check_target
|
||||
bundles = args.bundles
|
||||
if "component_codec" == check_target:
|
||||
if bundles is None:
|
||||
check_component_and_codec(project_path)
|
||||
else:
|
||||
if 0 == len(bundles):
|
||||
print(r"error: '--bundles' parameter is specified, but has no value")
|
||||
else:
|
||||
check_component_and_codec(project_path, bundles)
|
||||
elif "component_sdk" == check_target:
|
||||
check_component_and_sdk(project_path)
|
||||
elif "sdk_codec" == check_target:
|
||||
check_sdk_and_codec(project_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user