• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3
2"""
3Copyright (c) 2021 Huawei Device Co., Ltd.
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15
16"""
17import json
18import argparse
19import os
20
21SUBSYS_LIST = "subsystems"
22SUBSYS = "subsystem"
23COMPONENT_LIST = "components"
24COMPONENT = "component"
25FEATRUES = "features"
26FEATRUE = "feature"
27NONE_FEATURES = []
28TYPE = "type"
29VALUE = "value"
30PROPERTY = "property"
31KCONF_PREFIX = "CONFIG_"
32
33
34def read_full_component(path):
35    data = {}
36    with open(path, "rb") as f:
37        data = json.load(f)
38    component_subsys_dict = {}
39    for item in data.get(SUBSYS_LIST):
40        subsys_name = item.get(SUBSYS)
41        for component in item.get(COMPONENT_LIST):
42            component_name = component.get(COMPONENT)
43            component_subsys_dict[component_name] = subsys_name
44    return component_subsys_dict
45
46
47def read_deps_info(path):
48    data = {}
49    with open(path, "rb") as f:
50        data = json.load(f)
51    return data
52
53
54def merge(component_subsys_dict, component_deps_dict, subsys_conf):
55    config_component_list = []
56    for _, components in subsys_conf.items():
57        for component, _ in components.items():
58            config_component_list.append(component)
59
60    for component_name in config_component_list:
61        deps = component_deps_dict.get(component_name)
62        if deps is not None:
63            for dep in deps:
64                if dep in config_component_list:
65                    continue
66                else:
67                    subsys_name = component_subsys_dict.get(dep)
68                    if subsys_name is None:
69                        continue
70                    if subsys_conf.get(subsys_name) is None:
71                        subsys_conf[subsys_name] = {dep: NONE_FEATURES}
72                    else:
73                        subsys_conf[subsys_name][dep] = NONE_FEATURES
74                    config_component_list.append(dep)
75
76
77def is_valid_line(line):
78    return line.startswith(KCONF_PREFIX)
79
80
81def handle_config_feature(items, arr, line):
82    items[TYPE] = FEATRUE
83    items[SUBSYS] = arr[1]
84    items[COMPONENT] = arr[2].split("=")[0]
85    features = line.split("=", 1)[1].strip("\"")
86    if features == "":
87        items[FEATRUES] = NONE_FEATURES
88    else:
89        items[FEATRUES] = features.split(",")
90
91
92def handle_config_component(items, arr, line):
93    items[TYPE] = COMPONENT
94    items[SUBSYS] = arr[0].split("_", 1)[1]
95    items[COMPONENT] = arr[1].split("=")[0]
96    items[VALUE] = line.split("=", 1)[1]
97
98
99def handle_config_property(items, arr, line):
100    items[PROPERTY] = arr[1].split("=")[0]
101    items[TYPE] = PROPERTY
102    items[VALUE] = line.split("=", 1)[1].strip("\"")
103
104
105def read_line_item(line):
106    line = line.strip()
107    items = {
108        TYPE: None,
109        SUBSYS: None,
110        FEATRUES: None,
111        COMPONENT: None,
112        PROPERTY: None,
113        VALUE: None
114    }
115    arr = line.split("$$")
116    if arr[0] == "CONFIG_feature":
117        handle_config_feature(items, arr, line)
118    elif arr[0] == "CONFIG_property":
119        handle_config_property(items, arr, line)
120    else:
121        handle_config_component(items, arr, line)
122    return items
123
124
125def read(kconf):
126    result, subsys_conf = {}, {}
127    with open(kconf, "r") as f:
128        for line in f.readlines():
129            if not is_valid_line(line):
130                continue
131            items = read_line_item(line)
132            subsys = items.get(SUBSYS)
133            component = items.get(COMPONENT)
134            conf_type = items.get(TYPE)
135            features = items.get(FEATRUES)
136            if conf_type == PROPERTY:
137                if len(items.get(VALUE)) > 0:
138                    result[items.get(PROPERTY)] = items.get(VALUE)
139            elif conf_type == FEATRUE or conf_type == COMPONENT:
140                if subsys_conf.get(subsys) is None:
141                    subsys_conf[subsys] = {}
142                subsys_conf.get(subsys)[component] = features
143
144    result[SUBSYS_LIST] = subsys_conf
145    return result
146
147
148def generate_config_with_full_deps(deps_path, base_product_path, config_path, out):
149    kconf = read(config_path)
150    subsys_conf = kconf.get(SUBSYS_LIST)
151    component_subsys_dict = read_full_component(base_product_path)
152    component_deps_dict = read_deps_info(deps_path)
153    merge(component_subsys_dict, component_deps_dict, subsys_conf)
154    subsystems_list = []
155    for subsys, components in subsys_conf.items():
156        temp = {SUBSYS: subsys, COMPONENT_LIST: []}
157        for component, features in components.items():
158            component_element = {COMPONENT: component, FEATRUES: features}
159            temp.get(COMPONENT_LIST).append(component_element)
160        subsystems_list.append(temp)
161    result = kconf
162    result[SUBSYS_LIST] = subsystems_list
163    with open(out, "w") as f:
164        f.write(json.dumps(result, indent=2))
165    print("output file in: ", os.path.abspath(out))
166
167
168def main():
169    intro = 'Genenrate newly kconfig input file.\n\
170        For exmaple: python3 parse_kconf.py --deps={$repo}/out/{your_product}/part_deps_info/part_deps_info.json \n\
171        or           python3 parse_kconf.py --base_product={$repo}/productdefine/common/base/base_product.json \
172--out=./product.json --deps={$repo}/out/{your_product}/part_deps_info/part_deps_info.json --config=./.config'
173    parser = argparse.ArgumentParser(
174        formatter_class=argparse.RawDescriptionHelpFormatter,
175        description=intro)
176    parser.add_argument('--deps', type=str, required=True, default="",
177                        help='Must Requried! Depencencies info after gn building')
178    parser.add_argument('--base_product', type=str, default="./../../../productdefine/common/base/base_product.json",
179                        help='base_product.json file')
180    parser.add_argument('--config', type=str, default="./.config",
181                        help='config file which is generated by kconfig operation, default is .config')
182    parser.add_argument('--out', type=str, default="./product.json",
183                        help="define output file path and name, like './product.json'")
184    args = parser.parse_args()
185    print("read deps fle: ", os.path.abspath(args.deps))
186    print("read kconfig fle: ", os.path.abspath(args.config))
187    print("read base_product fle: ", os.path.abspath(args.base_product))
188
189    generate_config_with_full_deps(args.deps, args.base_product, args.config, args.out)
190
191
192if __name__ == "__main__":
193    main()
194