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 sys 175f9996aaSopenharmony_ciimport os 185f9996aaSopenharmony_ciimport argparse 195f9996aaSopenharmony_ci 205f9996aaSopenharmony_cisys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 215f9996aaSopenharmony_cifrom scripts.util.file_utils import read_json_file, read_file, write_file # noqa: E402 E501 225f9996aaSopenharmony_ci 235f9996aaSopenharmony_ci 245f9996aaSopenharmony_cidef _read_subninja_build(build_dir: str, subninja_build_file: str): 255f9996aaSopenharmony_ci subninja_build_file = os.path.join(build_dir, subninja_build_file) 265f9996aaSopenharmony_ci if not os.path.exists(subninja_build_file): 275f9996aaSopenharmony_ci raise Exception("file '{}' doesn't exist.".format(subninja_build_file)) 285f9996aaSopenharmony_ci subninja_build = read_file(subninja_build_file) 295f9996aaSopenharmony_ci if subninja_build is None: 305f9996aaSopenharmony_ci raise Exception("read file '{}' failed.".format(subninja_build_file)) 315f9996aaSopenharmony_ci support_lib_type = ['.a', '.so', ''] 325f9996aaSopenharmony_ci label_name = '' 335f9996aaSopenharmony_ci label_target = '' 345f9996aaSopenharmony_ci for _line in subninja_build: 355f9996aaSopenharmony_ci if _line.startswith('label_name = '): 365f9996aaSopenharmony_ci label_name = _line[len('label_name = '):] 375f9996aaSopenharmony_ci elif _line.startswith('build '): 385f9996aaSopenharmony_ci _build_info = _line.split(':')[0] 395f9996aaSopenharmony_ci build_label = _build_info.split(' ')[1] 405f9996aaSopenharmony_ci _, extension = os.path.splitext(build_label) 415f9996aaSopenharmony_ci if extension in support_lib_type: 425f9996aaSopenharmony_ci label_target = build_label 435f9996aaSopenharmony_ci 445f9996aaSopenharmony_ci if label_target != '': 455f9996aaSopenharmony_ci if label_name == '': 465f9996aaSopenharmony_ci target_filename = os.path.basename(label_target) 475f9996aaSopenharmony_ci label_name, _ = os.path.splitext(target_filename) 485f9996aaSopenharmony_ci return {label_name: label_target} 495f9996aaSopenharmony_ci return None 505f9996aaSopenharmony_ci 515f9996aaSopenharmony_ci 525f9996aaSopenharmony_cidef _parse_target_label(build_label_list: list, toolchain_name: str): 535f9996aaSopenharmony_ci phony_targets_dict = {} 545f9996aaSopenharmony_ci for build_label in build_label_list: 555f9996aaSopenharmony_ci target_filename = os.path.basename(build_label) 565f9996aaSopenharmony_ci label_name, _ = os.path.splitext(target_filename) 575f9996aaSopenharmony_ci if label_name: 585f9996aaSopenharmony_ci phony_targets_dict[label_name] = build_label 595f9996aaSopenharmony_ci start_index = len('{}/obj/'.format(toolchain_name)) 605f9996aaSopenharmony_ci _path = os.path.dirname(build_label)[start_index:] 615f9996aaSopenharmony_ci if _path: 625f9996aaSopenharmony_ci phony_targets_dict[_path] = build_label 635f9996aaSopenharmony_ci if label_name and _path: 645f9996aaSopenharmony_ci _label_path = '{}$:{}'.format(_path, label_name) 655f9996aaSopenharmony_ci phony_targets_dict[_label_path] = build_label 665f9996aaSopenharmony_ci return phony_targets_dict 675f9996aaSopenharmony_ci 685f9996aaSopenharmony_ci 695f9996aaSopenharmony_cidef _read_toolchain_ninja(build_dir: str, toolchain_ninja_file: str, toolchain_name: str): 705f9996aaSopenharmony_ci if not os.path.exists(toolchain_ninja_file): 715f9996aaSopenharmony_ci raise Exception( 725f9996aaSopenharmony_ci "file '{}' doesn't exist.".format(toolchain_ninja_file)) 735f9996aaSopenharmony_ci toolchain_ninja_rules = read_file(toolchain_ninja_file) 745f9996aaSopenharmony_ci if toolchain_ninja_rules is None: 755f9996aaSopenharmony_ci raise Exception("read file '{}' failed.".format(toolchain_ninja_file)) 765f9996aaSopenharmony_ci 775f9996aaSopenharmony_ci build_label_list = [] 785f9996aaSopenharmony_ci subninja_targets = {} 795f9996aaSopenharmony_ci for _ninja_rule in toolchain_ninja_rules: 805f9996aaSopenharmony_ci if _ninja_rule.startswith('build '): 815f9996aaSopenharmony_ci _tmp = _ninja_rule.split(':')[0] 825f9996aaSopenharmony_ci _label = _tmp[len('build '):] 835f9996aaSopenharmony_ci if not _label.endswith('.stamp'): 845f9996aaSopenharmony_ci continue 855f9996aaSopenharmony_ci build_label_list.append(_label) 865f9996aaSopenharmony_ci if _ninja_rule.startswith('subninja '): 875f9996aaSopenharmony_ci sbuninja_file = _ninja_rule[len('subninja '):] 885f9996aaSopenharmony_ci subninja_target_info = _read_subninja_build( 895f9996aaSopenharmony_ci build_dir, sbuninja_file) 905f9996aaSopenharmony_ci if subninja_target_info: 915f9996aaSopenharmony_ci subninja_targets.update(subninja_target_info) 925f9996aaSopenharmony_ci build_phony_targets = _parse_target_label(build_label_list, toolchain_name) 935f9996aaSopenharmony_ci build_phony_targets.update(subninja_targets) 945f9996aaSopenharmony_ci return build_phony_targets 955f9996aaSopenharmony_ci 965f9996aaSopenharmony_ci 975f9996aaSopenharmony_cidef _read_variants_toolchain_info(variants_toolchain_info_file: str): 985f9996aaSopenharmony_ci if not os.path.exists(variants_toolchain_info_file): 995f9996aaSopenharmony_ci raise Exception( 1005f9996aaSopenharmony_ci "file '{}' doesn't exist.".format(variants_toolchain_info_file)) 1015f9996aaSopenharmony_ci variants_toolchain_info = read_json_file(variants_toolchain_info_file) 1025f9996aaSopenharmony_ci if variants_toolchain_info is None: 1035f9996aaSopenharmony_ci raise Exception( 1045f9996aaSopenharmony_ci "read file '{}' failed.".format(variants_toolchain_info_file)) 1055f9996aaSopenharmony_ci platform_toolchain = variants_toolchain_info.get('platform_toolchain') 1065f9996aaSopenharmony_ci return platform_toolchain 1075f9996aaSopenharmony_ci 1085f9996aaSopenharmony_ci 1095f9996aaSopenharmony_cidef _read_build_ninja(build_ninja_file: str): 1105f9996aaSopenharmony_ci if not os.path.exists(build_ninja_file): 1115f9996aaSopenharmony_ci raise Exception("file '{}' doesn't exist.".format(build_ninja_file)) 1125f9996aaSopenharmony_ci ninja_targets = read_file(build_ninja_file) 1135f9996aaSopenharmony_ci if ninja_targets is None: 1145f9996aaSopenharmony_ci raise Exception("read file '{}' failed.".format(build_ninja_file)) 1155f9996aaSopenharmony_ci return ninja_targets 1165f9996aaSopenharmony_ci 1175f9996aaSopenharmony_ci 1185f9996aaSopenharmony_cidef generate_phony_targets(build_dir: str, toolchain_ninja_file: str, platform: str, 1195f9996aaSopenharmony_ci toolchain_name: str, default_targets_name: str): 1205f9996aaSopenharmony_ci build_phony_targets = _read_toolchain_ninja(build_dir, 1215f9996aaSopenharmony_ci toolchain_ninja_file, 1225f9996aaSopenharmony_ci toolchain_name) 1235f9996aaSopenharmony_ci targets_list = [] 1245f9996aaSopenharmony_ci for key, build_label in build_phony_targets.items(): 1255f9996aaSopenharmony_ci targets_list.append('build {}/{}: phony {}'.format( 1265f9996aaSopenharmony_ci platform, key, build_label)) 1275f9996aaSopenharmony_ci 1285f9996aaSopenharmony_ci _diff_targets = set(default_targets_name).difference( 1295f9996aaSopenharmony_ci set(build_phony_targets.keys())) 1305f9996aaSopenharmony_ci for _diff_target in _diff_targets: 1315f9996aaSopenharmony_ci targets_list.append('build {}/{}: phony {}'.format( 1325f9996aaSopenharmony_ci platform, _diff_target, _diff_target)) 1335f9996aaSopenharmony_ci build_file = os.path.join(os.path.dirname(toolchain_ninja_file), 1345f9996aaSopenharmony_ci '{}_build.ninja'.format(platform)) 1355f9996aaSopenharmony_ci write_file(build_file, '{}\n\n'.format('\n'.join(targets_list))) 1365f9996aaSopenharmony_ci return build_file 1375f9996aaSopenharmony_ci 1385f9996aaSopenharmony_ci 1395f9996aaSopenharmony_cidef _update_build_ninja(build_dir: str, include_files: str): 1405f9996aaSopenharmony_ci try: 1415f9996aaSopenharmony_ci ninja_build_file = os.path.join(build_dir, 'build.ninja') 1425f9996aaSopenharmony_ci if not os.path.exists(ninja_build_file): 1435f9996aaSopenharmony_ci raise Exception( 1445f9996aaSopenharmony_ci "file '{}' doesn't exist.".format(ninja_build_file)) 1455f9996aaSopenharmony_ci with open(ninja_build_file, 'a+') as _file: 1465f9996aaSopenharmony_ci data = [] 1475f9996aaSopenharmony_ci for line in _file.readlines(): 1485f9996aaSopenharmony_ci _line = line.rstrip('\n') 1495f9996aaSopenharmony_ci if _line.startswith('subninja '): 1505f9996aaSopenharmony_ci data.append(_line) 1515f9996aaSopenharmony_ci for include_file in include_files: 1525f9996aaSopenharmony_ci include_info = 'subninja {}'.format( 1535f9996aaSopenharmony_ci os.path.relpath(include_file, build_dir)) 1545f9996aaSopenharmony_ci if include_info in data: 1555f9996aaSopenharmony_ci continue 1565f9996aaSopenharmony_ci _file.write('{}\n'.format(include_info)) 1575f9996aaSopenharmony_ci _file.flush() 1585f9996aaSopenharmony_ci except: # noqa E722 1595f9996aaSopenharmony_ci raise 1605f9996aaSopenharmony_ci 1615f9996aaSopenharmony_ci 1625f9996aaSopenharmony_cidef update(build_dir: str, variants_toolchain_info_file: str): 1635f9996aaSopenharmony_ci variants_toolchain_info_file = os.path.join(build_dir, 1645f9996aaSopenharmony_ci variants_toolchain_info_file) 1655f9996aaSopenharmony_ci platform_toolchain = _read_variants_toolchain_info( 1665f9996aaSopenharmony_ci variants_toolchain_info_file) 1675f9996aaSopenharmony_ci 1685f9996aaSopenharmony_ci ninja_build_file = os.path.join(build_dir, 'build.ninja') 1695f9996aaSopenharmony_ci default_ninja_targets = _read_build_ninja(ninja_build_file) 1705f9996aaSopenharmony_ci default_targets_name = [] 1715f9996aaSopenharmony_ci for _ninja_target in default_ninja_targets: 1725f9996aaSopenharmony_ci if not _ninja_target.startswith('build '): 1735f9996aaSopenharmony_ci continue 1745f9996aaSopenharmony_ci _ninja_target = _ninja_target.split(': ')[0] 1755f9996aaSopenharmony_ci default_targets_name.append(_ninja_target[len('build '):]) 1765f9996aaSopenharmony_ci 1775f9996aaSopenharmony_ci include_files = [] 1785f9996aaSopenharmony_ci for platform, toolchain_label in platform_toolchain.items(): 1795f9996aaSopenharmony_ci if platform == 'phone': 1805f9996aaSopenharmony_ci continue 1815f9996aaSopenharmony_ci toolchain_name = toolchain_label.split(':')[1] 1825f9996aaSopenharmony_ci toolchain_ninja_file = os.path.join(build_dir, toolchain_name, 1835f9996aaSopenharmony_ci 'toolchain.ninja') 1845f9996aaSopenharmony_ci if not os.path.exists(toolchain_ninja_file): 1855f9996aaSopenharmony_ci continue 1865f9996aaSopenharmony_ci _build_file = generate_phony_targets(build_dir, toolchain_ninja_file, 1875f9996aaSopenharmony_ci platform, toolchain_name, 1885f9996aaSopenharmony_ci default_targets_name) 1895f9996aaSopenharmony_ci include_files.append(_build_file) 1905f9996aaSopenharmony_ci _update_build_ninja(build_dir, include_files) 1915f9996aaSopenharmony_ci 1925f9996aaSopenharmony_ci 1935f9996aaSopenharmony_cidef main(): 1945f9996aaSopenharmony_ci parser = argparse.ArgumentParser() 1955f9996aaSopenharmony_ci parser.add_argument('--source-root-dir', required=True) 1965f9996aaSopenharmony_ci parser.add_argument('--root-build-dir', required=True) 1975f9996aaSopenharmony_ci parser.add_argument('--variants-toolchain-info-file', required=True) 1985f9996aaSopenharmony_ci args = parser.parse_args() 1995f9996aaSopenharmony_ci 2005f9996aaSopenharmony_ci source_root_dir = args.source_root_dir 2015f9996aaSopenharmony_ci if not os.path.exists(os.path.join(source_root_dir, '.gn')): 2025f9996aaSopenharmony_ci print('source root dir incorrect.') 2035f9996aaSopenharmony_ci return 1 2045f9996aaSopenharmony_ci build_dir = os.path.join(source_root_dir, args.root_build_dir) 2055f9996aaSopenharmony_ci update(build_dir, args.variants_toolchain_info_file) 2065f9996aaSopenharmony_ci return 0 2075f9996aaSopenharmony_ci 2085f9996aaSopenharmony_ci 2095f9996aaSopenharmony_ciif __name__ == '__main__': 2105f9996aaSopenharmony_ci sys.exit(main()) 211