195 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/python3
 | |
| # -*- coding: utf-8 -*-
 | |
| """
 | |
| Copyright (c) 2021 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 json
 | |
| import argparse
 | |
| import os
 | |
| 
 | |
| SUBSYS_LIST = "subsystems"
 | |
| SUBSYS = "subsystem"
 | |
| COMPONENT_LIST = "components"
 | |
| COMPONENT = "component"
 | |
| FEATRUES = "features"
 | |
| FEATRUE = "feature"
 | |
| NONE_FEATURES = []
 | |
| TYPE = "type"
 | |
| VALUE = "value"
 | |
| PROPERTY = "property"
 | |
| KCONF_PREFIX = "CONFIG_"
 | |
| 
 | |
| 
 | |
| def read_full_component(path):
 | |
|     data = {}
 | |
|     with open(path, "rb") as f:
 | |
|         data = json.load(f)
 | |
|     component_subsys_dict = {}
 | |
|     for item in data.get(SUBSYS_LIST):
 | |
|         subsys_name = item.get(SUBSYS)
 | |
|         for component in item.get(COMPONENT_LIST):
 | |
|             component_name = component.get(COMPONENT)
 | |
|             component_subsys_dict[component_name] = subsys_name
 | |
|     return component_subsys_dict
 | |
| 
 | |
| 
 | |
| def read_deps_info(path):
 | |
|     data = {}
 | |
|     with open(path, "rb") as f:
 | |
|         data = json.load(f)
 | |
|     return data
 | |
| 
 | |
| 
 | |
| def merge(component_subsys_dict, component_deps_dict, subsys_conf):
 | |
|     config_component_list = []
 | |
|     for _, components in subsys_conf.items():
 | |
|         for component, _ in components.items():
 | |
|             config_component_list.append(component)
 | |
| 
 | |
|     for component_name in config_component_list:
 | |
|         deps = component_deps_dict.get(component_name)
 | |
|         if deps is not None:
 | |
|             for dep in deps:
 | |
|                 if dep in config_component_list:
 | |
|                     continue
 | |
|                 else:
 | |
|                     subsys_name = component_subsys_dict.get(dep)
 | |
|                     if subsys_name is None:
 | |
|                         continue
 | |
|                     if subsys_conf.get(subsys_name) is None:
 | |
|                         subsys_conf[subsys_name] = {dep: NONE_FEATURES}
 | |
|                     else:
 | |
|                         subsys_conf[subsys_name][dep] = NONE_FEATURES
 | |
|                     config_component_list.append(dep)
 | |
| 
 | |
| 
 | |
| def is_valid_line(line):
 | |
|     return line.startswith(KCONF_PREFIX)
 | |
| 
 | |
| 
 | |
| def handle_config_feature(items, arr, line):
 | |
|     items[TYPE] = FEATRUE
 | |
|     items[SUBSYS] = arr[1]
 | |
|     items[COMPONENT] = arr[2].split("=")[0]
 | |
|     features = line.split("=", 1)[1].strip("\"")
 | |
|     if features == "":
 | |
|         items[FEATRUES] = NONE_FEATURES
 | |
|     else:
 | |
|         items[FEATRUES] = features.split(",")
 | |
| 
 | |
| 
 | |
| def handle_config_component(items, arr, line):
 | |
|     items[TYPE] = COMPONENT
 | |
|     items[SUBSYS] = arr[0].split("_", 1)[1]
 | |
|     items[COMPONENT] = arr[1].split("=")[0]
 | |
|     items[VALUE] = line.split("=", 1)[1]
 | |
| 
 | |
| 
 | |
| def handle_config_property(items, arr, line):
 | |
|     items[PROPERTY] = arr[1].split("=")[0]
 | |
|     items[TYPE] = PROPERTY
 | |
|     items[VALUE] = line.split("=", 1)[1].strip("\"")
 | |
| 
 | |
| 
 | |
| def read_line_item(line):
 | |
|     line = line.strip()
 | |
|     items = {
 | |
|         TYPE: None,
 | |
|         SUBSYS: None,
 | |
|         FEATRUES: None,
 | |
|         COMPONENT: None,
 | |
|         PROPERTY: None,
 | |
|         VALUE: None
 | |
|     }
 | |
|     arr = line.split("$$")
 | |
|     if arr[0] == "CONFIG_feature":
 | |
|         handle_config_feature(items, arr, line)
 | |
|     elif arr[0] == "CONFIG_property":
 | |
|         handle_config_property(items, arr, line)
 | |
|     else:
 | |
|         handle_config_component(items, arr, line)
 | |
|     return items
 | |
| 
 | |
| 
 | |
| def read(kconf):
 | |
|     result, subsys_conf = {}, {}
 | |
|     with open(kconf, "r") as f:
 | |
|         for line in f.readlines():
 | |
|             if not is_valid_line(line):
 | |
|                 continue
 | |
|             items = read_line_item(line)
 | |
|             subsys = items.get(SUBSYS)
 | |
|             component = items.get(COMPONENT)
 | |
|             conf_type = items.get(TYPE)
 | |
|             features = items.get(FEATRUES)
 | |
|             if conf_type == PROPERTY:
 | |
|                 if len(items.get(VALUE)) > 0:
 | |
|                     result[items.get(PROPERTY)] = items.get(VALUE)
 | |
|             elif conf_type == FEATRUE or conf_type == COMPONENT:
 | |
|                 if subsys_conf.get(subsys) is None:
 | |
|                     subsys_conf[subsys] = {}
 | |
|                 subsys_conf.get(subsys)[component] = features
 | |
| 
 | |
|     result[SUBSYS_LIST] = subsys_conf
 | |
|     return result
 | |
| 
 | |
| 
 | |
| def generate_config_with_full_deps(deps_path, base_product_path, config_path, out):
 | |
|     kconf = read(config_path)
 | |
|     subsys_conf = kconf.get(SUBSYS_LIST)
 | |
|     component_subsys_dict = read_full_component(base_product_path)
 | |
|     component_deps_dict = read_deps_info(deps_path)
 | |
|     merge(component_subsys_dict, component_deps_dict, subsys_conf)
 | |
|     subsystems_list = []
 | |
|     for subsys, components in subsys_conf.items():
 | |
|         temp = {SUBSYS: subsys, COMPONENT_LIST: []}
 | |
|         for component, features in components.items():
 | |
|             component_element = {COMPONENT: component, FEATRUES: features}
 | |
|             temp.get(COMPONENT_LIST).append(component_element)
 | |
|         subsystems_list.append(temp)
 | |
|     result = kconf
 | |
|     result[SUBSYS_LIST] = subsystems_list
 | |
|     with open(out, "w") as f:
 | |
|         f.write(json.dumps(result, indent=2))
 | |
|     print("output file in: ", os.path.abspath(out))
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     intro = 'Genenrate newly kconfig input file.\n\
 | |
|         For example: python3 parse_kconf.py --deps={$repo}/out/{your_product}/part_deps_info/part_deps_info.json \n\
 | |
|         or           python3 parse_kconf.py --base_product={$repo}/productdefine/common/base/base_product.json \
 | |
| --out=./product.json --deps={$repo}/out/{your_product}/part_deps_info/part_deps_info.json --config=./.config'
 | |
|     parser = argparse.ArgumentParser(
 | |
|         formatter_class=argparse.RawDescriptionHelpFormatter,
 | |
|         description=intro)
 | |
|     parser.add_argument('--deps', type=str, required=True, default="",
 | |
|                         help='Must Required! Depencencies info after gn building')
 | |
|     parser.add_argument('--base_product', type=str, default="./../../../productdefine/common/base/base_product.json",
 | |
|                         help='base_product.json file')
 | |
|     parser.add_argument('--config', type=str, default="./.config",
 | |
|                         help='config file which is generated by kconfig operation, default is .config')
 | |
|     parser.add_argument('--out', type=str, default="./product.json",
 | |
|                         help="define output file path and name, like './product.json'")
 | |
|     args = parser.parse_args()
 | |
|     print("read deps file: ", os.path.abspath(args.deps))
 | |
|     print("read kconfig file: ", os.path.abspath(args.config))
 | |
|     print("read base_product file: ", os.path.abspath(args.base_product))
 | |
| 
 | |
|     generate_config_with_full_deps(args.deps, args.base_product, args.config, args.out)
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()
 |