• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright (c) 2022 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16# This file contains some Classes for gn's BUILD.gn
17
18import os
19import logging
20import re
21import ast
22import json
23import collections
24from typing import *
25if __name__ == '__main__':
26    from basic_tool import BasicTool
27else:
28    from pkgs.basic_tool import BasicTool
29
30
31class GnCommonTool:
32    """
33    处理BUILD.gn文件的通用方法
34    """
35
36    @classmethod
37    def _find_gn_variable_list(cls, content: str) -> List:
38        """
39        获取s中${xxx}或$xxx形式的gn变量
40        :param content: 待查找的字符串
41        :param sep: 分隔符,使用本分隔符将内容进行分隔然后逐一查找
42        :return: 变量名及其符号,eg:${abc}、$abc
43        :FIXME 没有对a = 'a' b = a中的b这种形式进行处理
44        """
45        result = list()
46        splited = content.split(os.sep)
47        patern = re.compile(r"\${.*?}")
48        for item in splited:
49            m = re.findall(patern, item)
50            result.extend(m)
51            if len(m) == 0 and "$" in item:
52                item = item.strip('"')
53                result.append(item[item.index("$"):])
54        return result
55
56    @classmethod
57    def is_gn_variable(cls, target: str, quote_processed: bool = False):
58        """
59        判断target是否是gn中的变量:
60        规则:如果是quote_processed is False,则没有引号均认为是变量,有引号的情况下,如果是"$xxx"或${xx}的模式,则认为xxx是变量;
61        如果quote_processed is True,则只要$开头就认为是变量
62        b = "xxx"
63        c = b
64        c = "${b}"
65        "$p"
66        :param target: 要进行判断的字符串对象
67        :param quote_processed: 引号是否已经去除
68        :return: target是否为gn中的变量
69        """
70        target = target.strip()
71        if quote_processed:
72            return target.startswith("$")
73        if target.startswith('"') and target.endswith('"'):
74            target = target.strip('"')
75            if target.startswith("${") and target.endswith("}"):
76                return True
77            elif target.startswith("$"):
78                return True
79            return False
80        else:
81            return True
82
83    @classmethod
84    def contains_gn_variable(cls, s: str, quote_processed: bool = False):
85        """
86        判断字符串s中是否包含gn变量
87        """
88        return cls.is_gn_variable(s, quote_processed) or ("$" in s)
89
90    # 给__find_variables_in_gn用的,减少io
91    __var_val_mem_dict = collections.defaultdict(str)
92
93    @classmethod
94    def find_variables_in_gn(cls, var_name_tuple: tuple, path: str, stop_tail: str = "home", use_cache: bool = False) -> \
95            List[str]:
96        """
97        同时查找多个gn变量的值
98        var_name_tuple:变量名的tuple,变量名应是未经过处理后的,如:
99        xxx
100        "${xxx}"
101        "$xxx"
102        :param var_name_tuple: 待查找的变量名的列表
103        :param path: 变量名所在文件的路径
104        :param stop_tail: 当path以stop_tail结尾时,停止查找
105        :param use_cache: 是否使用缓存
106        :return: 变量值的列表
107        """
108        if os.path.isfile(path):
109            path, _ = os.path.split(path)
110        var_val_dict = collections.defaultdict(str)
111        not_found_count = len(var_name_tuple)
112        if use_cache:
113            for var in var_name_tuple:
114                val = GnCommonTool.__var_val_mem_dict[var]
115                if val:
116                    not_found_count -= 1
117                var_val_dict[var] = val
118        while (stop_tail in path) and not_found_count:
119            for v in var_name_tuple:
120                pv = v.strip('"').lstrip("${").rstrip('}')
121                # 先直接grep出pv *= *\".*?\"的
122                # 然后排除含有$符的
123                # 再取第一个
124                # 最后只取引号内的
125                cmd = fr"grep -Ern '{pv} *= *\".*?\"' --include=*.gn* {path} | grep -Ev '\$' " \
126                      r"| head -n 1 | grep -E '\".*\"' -wo"
127                output = BasicTool.execute(cmd, lambda x: x.strip().strip('"'))
128                # backup:end
129                if not output:
130                    continue
131                not_found_count -= 1
132                var_val_dict[v] = output
133                GnCommonTool.__var_val_mem_dict[v] = output
134            path, _ = os.path.split(path)
135        return list(var_val_dict.values())
136
137    @classmethod
138    def replace_gn_variables(cls, s: str, gn_path: str, stop_tail: str) -> str:
139        """
140        替换字符串中的gn变量名为其值,注意,没有对s是否真的包含gn变量进行验证
141        :param s: 待替换的字符串
142        :param gn_path: 字符串所在的gn文件
143        :param stop_tail: 当变量查找到stop_tail目录时停止
144        :return: 将变量替换为其值的字符串
145        """
146        variable_list = GnCommonTool._find_gn_variable_list(s)
147        if len(variable_list) == 0:
148            return s
149        value_list = GnCommonTool.find_variables_in_gn(
150            tuple(variable_list), path=gn_path, stop_tail=stop_tail)
151        for k, v in dict(zip(variable_list, value_list)).items():
152            s = s.replace(k, v)
153        return s
154
155    @classmethod
156    def find_values_of_variable(cls, var_name: str, path: str, stop_tail: str = "home") -> list:
157        """
158        查找变量的值,如果有多个可能值,全部返回
159        :param var_name: 变量名
160        :param path: 变量名所在的文件
161        :param stop_tail: 当变量查找到stop_tail目录时停止
162        :return: 该变量的可能值
163        """
164        if os.path.isfile(path):
165            path, _ = os.path.split(path)
166        result = list()
167        v = var_name.strip('"').lstrip("${").rstrip('}')
168        while stop_tail in path:
169            cmd = fr"grep -Ern '^( *){v} *= *\".*?\"' --include=*.gn* {path}"
170            output = os.popen(cmd).readlines()
171            path = os.path.split(path)[0]
172            if not output:
173                continue
174            for line in output:
175                line = line.split('=')[-1].strip().strip('"')
176                if len(line) == 0:
177                    continue
178                result.append(line)
179            break
180        return result
181
182
183class GnVariableParser:
184    @classmethod
185    def string_parser(cls, var: str, content: str) -> str:
186        """
187        解析值为字符串的变量,没有对引号进行去除,如果是a = b这种b为变量的,则无法匹配
188        :param content: 要进行解析的内容
189        :param var: 变量名
190        :return: 变量值[str]
191        """
192        result = BasicTool.re_group_1(
193            content, r"{} *= *[\n]?(\".*?\")".format(var), flags=re.S | re.M)
194        return result
195
196    @classmethod
197    def list_parser(cls, var: str, content: str) -> List[str]:
198        """
199        解析值为列表的变量,list的元素必须全为数字或字符串,且没有对引号进行去除,如果是a = b这种b为变量的,则无法匹配
200        :param var: 变量名
201        :param content: 要进行
202        :return: 变量值[List]
203        """
204        result = BasicTool.re_group_1(
205            content, r"{} *= *(\[.*?\])".format(var), flags=re.S | re.M)
206        result = ast.literal_eval(result.strip())
207        return result
208
209
210if __name__ == '__main__':
211    cc = \
212        """
213        target("shared_library", "mmp"){
214            xxx
215        }
216
217        ohos_shared_library("pinauthservice") {
218          sources = [
219            "//base/useriam/pin_auth/services/modules/driver/src/pin_auth_driver_hdi.cpp",
220            "//base/useriam/pin_auth/services/modules/driver/src/pin_auth_interface_adapter.cpp",
221            "//base/useriam/pin_auth/services/modules/executors/src/pin_auth_executor_callback_hdi.cpp",
222            "//base/useriam/pin_auth/services/modules/executors/src/pin_auth_executor_hdi.cpp",
223            "//base/useriam/pin_auth/services/modules/inputters/src/i_inputer_data_impl.cpp",
224            "//base/useriam/pin_auth/services/modules/inputters/src/pin_auth_manager.cpp",
225            "//base/useriam/pin_auth/services/sa/src/pin_auth_service.cpp",
226          ]
227
228          configs = [
229            ":pin_auth_services_config",
230            "//base/useriam/user_auth_framework/common:iam_log_config",
231            "//base/useriam/user_auth_framework/common:iam_utils_config",
232          ]
233
234          deps = [
235            "//base/useriam/pin_auth/frameworks:pinauth_ipc",
236            "//third_party/openssl:libcrypto_shared",
237          ]
238
239          external_deps = [
240            "access_token:libaccesstoken_sdk",
241            "c_utils:utils",
242            "drivers_interface_pin_auth:libpin_auth_proxy_1.0",
243            "hisysevent_native:libhisysevent",
244            "hiviewdfx_hilog_native:libhilog",
245            "ipc:ipc_core",
246            "safwk:system_ability_fwk",
247            "user_auth_framework:userauth_executors",
248          ]
249          t = [
250          1,
251          2,
252          3
253          ]
254          tt = [
255          aaa,
256          bbb,
257          ccc
258          ]
259          remove_configs = [ "//build/config/compiler:no_exceptions" ]
260
261          subsystem_name = "useriam"
262          part_name = "pin_auth"
263        }"""
264    s = """
265updater_usb_init_cfg_path = "//base/startup/init/services/etc/init.usb.cfg"
266updater_init_usb_configfs_path_cfg =
267    "//drivers/peripheral/usb/cfg/init.usb.configfs.cfg"
268updater_faultloggerd_cfg =
269"//base/hiviewdfx/faultloggerd/services/config/faultloggerd.cfg"
270updater_hilog_cfg = "//base/hiviewdfx/hilog/services/hilogd/etc/hilogd.cfg"
271
272ohos_prebuilt_etc("updater_hilog.cfg") {
273source = "${updater_hilog_cfg}"
274install_images = [ "updater" ]
275part_name = "updater"
276}
277"""
278    s = "\"${updater_faultloggerd_cfg}\""
279    print(GnCommonTool.contains_gn_variable(s))
280    ...
281