• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (c) 2021 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
16import argparse
17import sys
18import os
19import subprocess
20import fnmatch
21import glob
22import re
23import errno
24import codecs
25
26sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
27from scripts.util import build_utils  # noqa: E402,E501 pylint: disable=E0401,C0413
28
29ALL_NDK_TARGETS_TEMPLATE = '''
30group("all_ndk_targets") {{
31 deps = [ {} ]
32}}
33'''
34
35ALL_NDK_TEMPLATES_NAMES = [
36    "ohos_ndk_headers", "ohos_ndk_library",
37    "ohos_ndk_prebuilt_library", "ohos_ndk_copy"
38]
39
40
41def remove_comment(file):
42    contents = []
43    with open(file, 'r') as in_file:
44        for line in in_file:
45            # Strip comments in gn file.
46            # If someone uses # as part of a string, ignore it.
47            if re.match(r'.*?("\S*#\S*")', line):
48                pass
49            else:
50                line = re.sub(r'(#.*?)\n', '', line)
51            contents.append(line)
52    return contents
53
54
55def do_dos2unix(in_file, out_file):
56    contents = ''
57    with open(in_file, 'r+b') as fin:
58        contents = fin.read()
59    # Remove BOM header.
60    if contents.startswith(codecs.BOM_UTF8):
61        contents = contents[len(codecs.BOM_UTF8):]
62    contents = re.sub(r'\r\n', '\n', contents.decode())
63    with open(out_file, 'w') as fout:
64        fout.write(contents)
65
66
67def do_gn_format(gn_file, org_file):
68    cmd = ['gn', 'format', gn_file]
69    child = subprocess.Popen(cmd)
70    child.communicate()
71    if child.returncode:
72        print(
73            'Error: Something is wrong with {}, please check file encoding or format'
74            .format(org_file))
75
76
77def get_ndk_targets(file, options):
78    ndk_targets = []
79    with build_utils.temp_dir() as tmp:
80        gn_file = os.path.join(tmp, os.path.basename(file))
81        do_dos2unix(file, gn_file)
82        do_gn_format(gn_file, file)
83        contents = remove_comment(gn_file)
84        for template_name in ALL_NDK_TEMPLATES_NAMES:
85            pattern = re.escape(template_name) + r"\(\"(.*)\"\)"
86            targets = re.findall(pattern, ''.join(contents))
87            for target in targets:
88                ndk_targets.append('\"//{}:{}\",'.format(
89                    os.path.relpath(os.path.dirname(file), options.root_dir),
90                    target))
91    return ndk_targets
92
93
94def main():
95    parser = argparse.ArgumentParser()
96    parser.add_argument('--output', required=True)
97    parser.add_argument('--root-dir', required=True)
98
99    options = parser.parse_args()
100
101    paths = glob.glob(os.path.join(options.root_dir, "*"))
102    dirs = [
103        d for d in paths if os.path.isdir(d)
104        and not fnmatch.fnmatch(d, os.path.join(options.root_dir, ".repo"))
105        and not fnmatch.fnmatch(d, os.path.join(options.root_dir, "out"))
106    ]
107
108    gn_list = []
109    for d in dirs:
110        gn_list += glob.glob(os.path.join(d, "**/BUILD.gn"), recursive=True)
111
112    ndk_targets = []
113    for gn_file in gn_list:
114        # Skip dead link.
115        try:
116            os.stat(gn_file)
117        except OSError as err:
118            if err.errno == errno.ENOENT:
119                continue
120            else:
121                raise Exception("Error: failed to stat {}".format(gn_file))
122        ndk_targets.extend(get_ndk_targets(gn_file, options))
123
124    ndk_contents = ALL_NDK_TARGETS_TEMPLATE.format('\n'.join(ndk_targets))
125
126    os.makedirs(os.path.dirname(options.output), exist_ok=True)
127    with open(options.output, 'w') as f:
128        f.write(ndk_contents)
129
130    # Call gn format to make the output gn file prettier.
131    cmd = ['gn', 'format', options.output]
132    subprocess.check_output(cmd)
133    return 0
134
135
136if __name__ == '__main__':
137    sys.exit(main())
138