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