15f9996aaSopenharmony_ci#!/usr/bin/env python3
25f9996aaSopenharmony_ci# -*- coding: utf-8 -*-
35f9996aaSopenharmony_ci"""
45f9996aaSopenharmony_ciCopyright (c) 2021 Huawei Device Co., Ltd.
55f9996aaSopenharmony_ciLicensed under the Apache License, Version 2.0 (the "License");
65f9996aaSopenharmony_ciyou may not use this file except in compliance with the License.
75f9996aaSopenharmony_ciYou may obtain a copy of the License at
85f9996aaSopenharmony_ci
95f9996aaSopenharmony_ci    http://www.apache.org/licenses/LICENSE-2.0
105f9996aaSopenharmony_ci
115f9996aaSopenharmony_ciUnless required by applicable law or agreed to in writing, software
125f9996aaSopenharmony_cidistributed under the License is distributed on an "AS IS" BASIS,
135f9996aaSopenharmony_ciWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145f9996aaSopenharmony_ciSee the License for the specific language governing permissions and
155f9996aaSopenharmony_cilimitations under the License.
165f9996aaSopenharmony_ci
175f9996aaSopenharmony_ci"""
185f9996aaSopenharmony_ci
195f9996aaSopenharmony_ciimport sys
205f9996aaSopenharmony_ciimport os
215f9996aaSopenharmony_ciimport argparse
225f9996aaSopenharmony_ciimport re
235f9996aaSopenharmony_ci
245f9996aaSopenharmony_cifrom graphviz import Digraph
255f9996aaSopenharmony_cifrom component_node import Node
265f9996aaSopenharmony_cifrom component_node import Module
275f9996aaSopenharmony_ci
285f9996aaSopenharmony_cifile_paths = []
295f9996aaSopenharmony_cimodule_dict = {}
305f9996aaSopenharmony_cicomponent_nodes = {}
315f9996aaSopenharmony_ci
325f9996aaSopenharmony_ci
335f9996aaSopenharmony_cidef draw_deps_pictrue_by_gn(output_path: str):
345f9996aaSopenharmony_ci    graph = Digraph('deps_graph')
355f9996aaSopenharmony_ci    for node_name in component_nodes:
365f9996aaSopenharmony_ci        graph.node(name=node_name, color='red')
375f9996aaSopenharmony_ci    for node_name in component_nodes:
385f9996aaSopenharmony_ci        deps = component_nodes[node_name].deps
395f9996aaSopenharmony_ci        external_deps = component_nodes[node_name].deps
405f9996aaSopenharmony_ci        all_deps = deps | external_deps
415f9996aaSopenharmony_ci        for dep_name in all_deps:
425f9996aaSopenharmony_ci            part_name = dep_name.split(':')[0]
435f9996aaSopenharmony_ci            module_name = dep_name.split(':')[-1]
445f9996aaSopenharmony_ci            if part_name in component_nodes:
455f9996aaSopenharmony_ci                graph.edge(node_name, part_name)
465f9996aaSopenharmony_ci            elif module_name in component_nodes:
475f9996aaSopenharmony_ci                graph.edge(node_name, module_name)
485f9996aaSopenharmony_ci    graph.render(filename=os.path.join(output_path, 'dep_graph'))
495f9996aaSopenharmony_ci
505f9996aaSopenharmony_ci
515f9996aaSopenharmony_cidef merge_module():
525f9996aaSopenharmony_ci    # create component nodes
535f9996aaSopenharmony_ci    for module_name in module_dict:
545f9996aaSopenharmony_ci        part_name = module_dict[module_name].part_name
555f9996aaSopenharmony_ci        if part_name in component_nodes:
565f9996aaSopenharmony_ci            component_nodes[part_name].add_module(module_dict[module_name])
575f9996aaSopenharmony_ci        else:
585f9996aaSopenharmony_ci            if part_name != '':
595f9996aaSopenharmony_ci                component_nodes[part_name] = Node(part_name)
605f9996aaSopenharmony_ci                component_nodes[part_name].add_module(module_dict[module_name])
615f9996aaSopenharmony_ci            elif module_name != '':
625f9996aaSopenharmony_ci                component_nodes[module_name] = Node(module_name)
635f9996aaSopenharmony_ci                component_nodes[module_name].add_module(module_dict[module_name])
645f9996aaSopenharmony_ci            else:
655f9996aaSopenharmony_ci                pass
665f9996aaSopenharmony_ci
675f9996aaSopenharmony_ci
685f9996aaSopenharmony_cidef read_build_gn_file(file_path: str):
695f9996aaSopenharmony_ci    with open(file_path, 'r') as file:
705f9996aaSopenharmony_ci        file_data = file.read()
715f9996aaSopenharmony_ci        pattern = re.compile(r'ohos_shared_library.*?\}', re.DOTALL)
725f9996aaSopenharmony_ci        results = pattern.findall(file_data)
735f9996aaSopenharmony_ci        for ohos_module_string in results:
745f9996aaSopenharmony_ci            module = Module.create_module_by_string(ohos_module_string, True)
755f9996aaSopenharmony_ci            module_dict[module.module_name] = module
765f9996aaSopenharmony_ci
775f9996aaSopenharmony_ci        pattern = re.compile(r'ohos_executable.*?\}', re.DOTALL)
785f9996aaSopenharmony_ci        results = pattern.findall(file_data)
795f9996aaSopenharmony_ci        for ohos_module_string in results:
805f9996aaSopenharmony_ci            module = Module.create_module_by_string(ohos_module_string, False)
815f9996aaSopenharmony_ci            module_dict[module.module_name] = module
825f9996aaSopenharmony_ci
835f9996aaSopenharmony_ci
845f9996aaSopenharmony_ci
855f9996aaSopenharmony_cidef _colletct_build_gn_path(root_path: str):
865f9996aaSopenharmony_ci    for file in os.listdir(root_path):
875f9996aaSopenharmony_ci        file_path = os.path.join(root_path, file)
885f9996aaSopenharmony_ci        if file == 'BUILD.gn':
895f9996aaSopenharmony_ci            file_paths.append(file_path)
905f9996aaSopenharmony_ci        if os.path.isdir(file_path):
915f9996aaSopenharmony_ci            _colletct_build_gn_path(file_path)
925f9996aaSopenharmony_ci
935f9996aaSopenharmony_ci
945f9996aaSopenharmony_cidef collect_build_gn_path(root_path: str):
955f9996aaSopenharmony_ci    for file in os.listdir(root_path):
965f9996aaSopenharmony_ci        file_path = os.path.join(root_path, file)
975f9996aaSopenharmony_ci        if file != 'out' and os.path.isdir(file_path):
985f9996aaSopenharmony_ci            _colletct_build_gn_path(file_path)
995f9996aaSopenharmony_ci
1005f9996aaSopenharmony_ci
1015f9996aaSopenharmony_cidef main(argv):
1025f9996aaSopenharmony_ci    parser = argparse.ArgumentParser()
1035f9996aaSopenharmony_ci    parser.add_argument('--root-path', required=True)
1045f9996aaSopenharmony_ci    parser.add_argument('--output', required=True)
1055f9996aaSopenharmony_ci    args = parser.parse_args(argv)
1065f9996aaSopenharmony_ci
1075f9996aaSopenharmony_ci    collect_build_gn_path(args.root_path)
1085f9996aaSopenharmony_ci    for gn_file in file_paths:
1095f9996aaSopenharmony_ci        read_build_gn_file(gn_file)
1105f9996aaSopenharmony_ci
1115f9996aaSopenharmony_ci    merge_module()
1125f9996aaSopenharmony_ci    draw_deps_pictrue_by_gn(args.output)
1135f9996aaSopenharmony_ci
1145f9996aaSopenharmony_ci
1155f9996aaSopenharmony_ciif __name__ == '__main__':
1165f9996aaSopenharmony_ci    sys.exit(main(sys.argv[1:]))
117