• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4#
5# Copyright (c) 2022 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19import subprocess
20import os
21import re
22from hb_internal.common.utils import OHOSException, read_json_file
23from hb.__main__ import find_top
24
25
26def add_options(parser):
27    group = parser.add_mutually_exclusive_group(required=True)
28    group.add_argument("--ls",
29                        action='store_true',
30                        default=False,
31                        help='lists all targets matching the given pattern for the given build directory, '
32                        'refer to gn ls. '
33                        'eg1: hb tool --ls '
34                        'eg2: hb tool --ls --all-toolchains')
35    group.add_argument('--desc',
36                        action='store_true',
37                        default=False,
38                        help='displays information about a given target or config, refer to gn desc, '
39                        'The --tree and --blame options are enabled by default. '
40                        'eg1: hb tool --desc init:innergroup '
41                        'eg2: hb tool --desc ai_engine:ai --all')
42    group.add_argument('--path',
43                        action='store_true',
44                        default=False,
45                        help='finds paths of dependencies between two targets, refer to gn path, '
46                        'The --all options are enabled by default. '
47                        'eg1: hb tool --path init:innergroup screenlock_mgr:screenlock_utils '
48                        'eg2: hb tool --path init:innergroup screenlock_mgr:screenlock_utils --public')
49    parser.add_argument('--out-path',
50                        nargs=1,
51                        help='specify the build directory, '
52                        'eg: hb tool --ls --out-path out/rk3568')
53
54
55class Tool():
56    def __init__(self, out_path=None):
57        self.cmd_list = []
58        self.gn_default = {'ls': [], 'desc': ['--tree', '--blame'], 'path': ['--all']}
59        if out_path:
60            self.out_path = out_path[0]
61        else:
62            self.out_path = read_json_file(os.path.join(find_top(), 'ohos_config.json'))['out_path']
63        if not os.path.isdir(self.out_path):
64            raise OHOSException(f"{self.out_path} doesn't exist.")
65
66    def register_target(self, component, module):
67        target_name = self.get_target_name(component, module)
68        if target_name:
69            self.cmd_list.append(target_name)
70        else:
71            raise OHOSException(f'The input {component}:{module} matches no targets, configs or files.')
72
73    def get_target_name(self, component, module):
74        root_path = os.path.join(self.out_path, "build_configs")
75        target_info = ""
76        module_list = []
77        for file in os.listdir(root_path):
78            if len(target_info):
79                break
80            file_path = os.path.join(root_path, file)
81            if not os.path.isdir(file_path):
82                continue
83            for component_name in os.listdir(file_path):
84                if os.path.isdir(os.path.join(file_path, component_name)) and component_name == component:
85                    target_info = self.read_gn_file(os.path.join(file_path, component_name, "BUILD.gn"))
86                    break
87        pattern = re.compile(r'(?<=module_list = )\[([^\[\]]*)\]')
88        results = pattern.findall(target_info)
89        for each_tuple in results:
90            module_list = each_tuple.replace('\n', '').replace(' ', '').replace('\"', '').split(',')
91        for target_path in module_list:
92            if target_path != '':
93                path, target = target_path.split(":")
94                if target == module:
95                    return target_path
96        return 0
97
98    def read_gn_file(self, input_file):
99        if not os.path.exists(input_file):
100            raise OHOSException("file '{}' doesn't exist.".format(input_file))
101        data = None
102        with open(input_file, 'r') as input_f:
103            data = input_f.read()
104        return data
105
106    def get_gn_path(self):
107        gn_path = ""
108        config_data = read_json_file(os.path.join(find_top(), 'build/prebuilts_download_config.json'))
109        copy_config_list = config_data[os.uname().sysname.lower()][os.uname().machine.lower()]['copy_config']
110        for config in copy_config_list:
111            if config['unzip_filename'] == 'gn':
112                gn_path = os.path.join(find_top(), config['unzip_dir'], 'gn')
113        return gn_path
114
115
116    def exec_gn_cmd(self, gn_cmd):
117        gn_path = self.get_gn_path()
118        for arg in self.gn_default.get(gn_cmd):
119            if arg not in self.cmd_list:
120                self.cmd_list.append(arg)
121        cmds = [gn_path, gn_cmd, self.out_path]
122        cmds.extend(self.cmd_list)
123        pipe = subprocess.Popen(
124            cmds,
125            stdout=subprocess.PIPE,
126            shell=False,
127            encoding='utf8'
128        )
129        while pipe.poll() is None:
130            out = pipe.stdout.readline()
131            if out != "":
132                print(out, end="")
133
134
135def exec_command(args):
136    tool = Tool(args[0].out_path)
137    gn_args = args[1]
138    if args[0].ls:
139        tool.cmd_list.extend(gn_args)
140        tool.exec_gn_cmd('ls')
141
142    if args[0].desc:
143        try:
144            component, module = gn_args[0].split(':')
145            tool.register_target(component, module)
146            gn_args.remove(gn_args[0])
147        except Exception:
148            raise OHOSException(f'Invalid desc args: {gn_args[0]} ,need <component:module>')
149        tool.cmd_list.extend(gn_args)
150        tool.exec_gn_cmd('desc')
151
152    if args[0].path:
153        try:
154            for i in range(2):
155                component, module = gn_args[0].split(':')
156                tool.register_target(component, module)
157                gn_args.remove(gn_args[0])
158        except Exception:
159            raise OHOSException('Invalid path args: need <component_one:module_one> <component_two:module_two>')
160        tool.cmd_list.extend(gn_args)
161        tool.exec_gn_cmd('path')
162