15f9996aaSopenharmony_ci#!/usr/bin/env python 25f9996aaSopenharmony_ci# -*- coding: utf-8 -*- 35f9996aaSopenharmony_ci# Copyright (c) 2021 Huawei Device Co., Ltd. 45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License. 65f9996aaSopenharmony_ci# You may obtain a copy of the License at 75f9996aaSopenharmony_ci# 85f9996aaSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 95f9996aaSopenharmony_ci# 105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and 145f9996aaSopenharmony_ci# limitations under the License. 155f9996aaSopenharmony_ci 165f9996aaSopenharmony_ciimport argparse 175f9996aaSopenharmony_ciimport sys 185f9996aaSopenharmony_ciimport os 195f9996aaSopenharmony_ciimport subprocess 205f9996aaSopenharmony_ciimport fnmatch 215f9996aaSopenharmony_ciimport glob 225f9996aaSopenharmony_ciimport re 235f9996aaSopenharmony_ciimport errno 245f9996aaSopenharmony_ciimport codecs 255f9996aaSopenharmony_ci 265f9996aaSopenharmony_cisys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) 275f9996aaSopenharmony_cifrom scripts.util import build_utils # noqa: E402,E501 pylint: disable=E0401,C0413 285f9996aaSopenharmony_ci 295f9996aaSopenharmony_ciALL_NDK_TARGETS_TEMPLATE = ''' 305f9996aaSopenharmony_cigroup("all_ndk_targets") {{ 315f9996aaSopenharmony_ci deps = [ {} ] 325f9996aaSopenharmony_ci}} 335f9996aaSopenharmony_ci''' 345f9996aaSopenharmony_ci 355f9996aaSopenharmony_ciALL_NDK_TEMPLATES_NAMES = [ 365f9996aaSopenharmony_ci "ohos_ndk_headers", "ohos_ndk_library", 375f9996aaSopenharmony_ci "ohos_ndk_prebuilt_library", "ohos_ndk_copy" 385f9996aaSopenharmony_ci] 395f9996aaSopenharmony_ci 405f9996aaSopenharmony_ci 415f9996aaSopenharmony_cidef remove_comment(file: str): 425f9996aaSopenharmony_ci contents = [] 435f9996aaSopenharmony_ci with open(file, 'r') as in_file: 445f9996aaSopenharmony_ci for line in in_file: 455f9996aaSopenharmony_ci # Strip comments in gn file. 465f9996aaSopenharmony_ci # If someone uses # as part of a string, ignore it. 475f9996aaSopenharmony_ci if re.match(r'.*?("\S*#\S*")', line): 485f9996aaSopenharmony_ci pass 495f9996aaSopenharmony_ci else: 505f9996aaSopenharmony_ci line = re.sub(r'(#.*?)\n', '', line) 515f9996aaSopenharmony_ci contents.append(line) 525f9996aaSopenharmony_ci return contents 535f9996aaSopenharmony_ci 545f9996aaSopenharmony_ci 555f9996aaSopenharmony_cidef do_dos2unix(in_file: str, out_file: str): 565f9996aaSopenharmony_ci contents = '' 575f9996aaSopenharmony_ci with open(in_file, 'r+b') as fin: 585f9996aaSopenharmony_ci contents = fin.read() 595f9996aaSopenharmony_ci # Remove BOM header. 605f9996aaSopenharmony_ci if contents.startswith(codecs.BOM_UTF8): 615f9996aaSopenharmony_ci contents = contents[len(codecs.BOM_UTF8):] 625f9996aaSopenharmony_ci contents = re.sub(r'\r\n', '\n', contents.decode()) 635f9996aaSopenharmony_ci with open(out_file, 'w') as fout: 645f9996aaSopenharmony_ci fout.write(contents) 655f9996aaSopenharmony_ci 665f9996aaSopenharmony_ci 675f9996aaSopenharmony_cidef do_gn_format(gn_file: str, org_file: str): 685f9996aaSopenharmony_ci cmd = ['gn', 'format', gn_file] 695f9996aaSopenharmony_ci child = subprocess.Popen(cmd) 705f9996aaSopenharmony_ci child.communicate() 715f9996aaSopenharmony_ci if child.returncode: 725f9996aaSopenharmony_ci print( 735f9996aaSopenharmony_ci 'Error: Something is wrong with {}, please check file encoding or format' 745f9996aaSopenharmony_ci .format(org_file)) 755f9996aaSopenharmony_ci 765f9996aaSopenharmony_ci 775f9996aaSopenharmony_cidef get_ndk_targets(file: str, options): 785f9996aaSopenharmony_ci ndk_targets = [] 795f9996aaSopenharmony_ci with build_utils.temp_dir() as tmp: 805f9996aaSopenharmony_ci gn_file = os.path.join(tmp, os.path.basename(file)) 815f9996aaSopenharmony_ci do_dos2unix(file, gn_file) 825f9996aaSopenharmony_ci do_gn_format(gn_file, file) 835f9996aaSopenharmony_ci contents = remove_comment(gn_file) 845f9996aaSopenharmony_ci for template_name in ALL_NDK_TEMPLATES_NAMES: 855f9996aaSopenharmony_ci pattern = re.escape(template_name) + r"\(\"(.*)\"\)" 865f9996aaSopenharmony_ci targets = re.findall(pattern, ''.join(contents)) 875f9996aaSopenharmony_ci for target in targets: 885f9996aaSopenharmony_ci ndk_targets.append('\"//{}:{}\",'.format( 895f9996aaSopenharmony_ci os.path.relpath(os.path.dirname(file), options.root_dir), 905f9996aaSopenharmony_ci target)) 915f9996aaSopenharmony_ci return ndk_targets 925f9996aaSopenharmony_ci 935f9996aaSopenharmony_ci 945f9996aaSopenharmony_cidef main(): 955f9996aaSopenharmony_ci parser = argparse.ArgumentParser() 965f9996aaSopenharmony_ci parser.add_argument('--output', required=True) 975f9996aaSopenharmony_ci parser.add_argument('--root-dir', required=True) 985f9996aaSopenharmony_ci 995f9996aaSopenharmony_ci options = parser.parse_args() 1005f9996aaSopenharmony_ci 1015f9996aaSopenharmony_ci paths = glob.glob(os.path.join(options.root_dir, "*")) 1025f9996aaSopenharmony_ci dirs = [ 1035f9996aaSopenharmony_ci d for d in paths if os.path.isdir(d) 1045f9996aaSopenharmony_ci and not fnmatch.fnmatch(d, os.path.join(options.root_dir, ".repo")) 1055f9996aaSopenharmony_ci and not fnmatch.fnmatch(d, os.path.join(options.root_dir, "out")) 1065f9996aaSopenharmony_ci ] 1075f9996aaSopenharmony_ci 1085f9996aaSopenharmony_ci gn_list = [] 1095f9996aaSopenharmony_ci for d in dirs: 1105f9996aaSopenharmony_ci gn_list += glob.glob(os.path.join(d, "**/BUILD.gn"), recursive=True) 1115f9996aaSopenharmony_ci 1125f9996aaSopenharmony_ci ndk_targets = [] 1135f9996aaSopenharmony_ci for gn_file in gn_list: 1145f9996aaSopenharmony_ci # Skip dead link. 1155f9996aaSopenharmony_ci try: 1165f9996aaSopenharmony_ci os.stat(gn_file) 1175f9996aaSopenharmony_ci except OSError as err: 1185f9996aaSopenharmony_ci if err.errno == errno.ENOENT: 1195f9996aaSopenharmony_ci continue 1205f9996aaSopenharmony_ci else: 1215f9996aaSopenharmony_ci raise Exception("Error: failed to stat {}".format(gn_file)) 1225f9996aaSopenharmony_ci ndk_targets.extend(get_ndk_targets(gn_file, options)) 1235f9996aaSopenharmony_ci 1245f9996aaSopenharmony_ci ndk_contents = ALL_NDK_TARGETS_TEMPLATE.format('\n'.join(ndk_targets)) 1255f9996aaSopenharmony_ci 1265f9996aaSopenharmony_ci os.makedirs(os.path.dirname(options.output), exist_ok=True) 1275f9996aaSopenharmony_ci with open(options.output, 'w') as f: 1285f9996aaSopenharmony_ci f.write(ndk_contents) 1295f9996aaSopenharmony_ci 1305f9996aaSopenharmony_ci # Call gn format to make the output gn file prettier. 1315f9996aaSopenharmony_ci cmd = ['gn', 'format', options.output] 1325f9996aaSopenharmony_ci subprocess.check_output(cmd) 1335f9996aaSopenharmony_ci return 0 1345f9996aaSopenharmony_ci 1355f9996aaSopenharmony_ci 1365f9996aaSopenharmony_ciif __name__ == '__main__': 1375f9996aaSopenharmony_ci sys.exit(main()) 138