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