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 argparse 185f9996aaSopenharmony_ciimport os 195f9996aaSopenharmony_ciimport shutil 205f9996aaSopenharmony_ciimport json 215f9996aaSopenharmony_cifrom interface_mgr import InterfaceMgr 225f9996aaSopenharmony_ci 235f9996aaSopenharmony_cisys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 245f9996aaSopenharmony_cifrom scripts.util.file_utils import read_json_file, write_file, write_json_file # noqa: E402 E501 255f9996aaSopenharmony_cifrom scripts.util import build_utils # noqa: E402 265f9996aaSopenharmony_ci 275f9996aaSopenharmony_ciSHARED_LIBRARY_BUILD_TEMPLATE = ''' 285f9996aaSopenharmony_ciconfig("%s_config") { 295f9996aaSopenharmony_ci include_dirs = [ "%s/include", ] 305f9996aaSopenharmony_ci} 315f9996aaSopenharmony_ciohos_prebuilt_shared_library("%s") { 325f9996aaSopenharmony_ci source = "%s" 335f9996aaSopenharmony_ci public_configs = [ ":%s_config" ] 345f9996aaSopenharmony_ci subsystem_name = "%s" 355f9996aaSopenharmony_ci part_name = "%s" 365f9996aaSopenharmony_ci install_enable = false 375f9996aaSopenharmony_ci} 385f9996aaSopenharmony_ci 395f9996aaSopenharmony_ci''' 405f9996aaSopenharmony_ciJAR_BUILD_TEMPLATE = ''' 415f9996aaSopenharmony_cijava_prebuilt("%s") { 425f9996aaSopenharmony_ci jar_path = "%s" 435f9996aaSopenharmony_ci''' 445f9996aaSopenharmony_ciMAPLE_BUILD_TEMPLATE = ''' 455f9996aaSopenharmony_ciohos_maple_java_prebuilt("%s") { 465f9996aaSopenharmony_ci mplt = %s 475f9996aaSopenharmony_ci jar_path = "%s" 485f9996aaSopenharmony_ci''' 495f9996aaSopenharmony_ci 505f9996aaSopenharmony_ci 515f9996aaSopenharmony_ci# check sdk header file signature, 525f9996aaSopenharmony_ci# skip check if file dir not exist 535f9996aaSopenharmony_cidef check_header_files(checkfile_dir: str, subsystem_sdk_dir: str, subsystem_name: str, 545f9996aaSopenharmony_ci module_name: str, interface_mgr): 555f9996aaSopenharmony_ci if checkfile_dir is None or not os.path.exists(checkfile_dir): 565f9996aaSopenharmony_ci return 575f9996aaSopenharmony_ci interface_mgr.check(checkfile_dir, subsystem_sdk_dir, subsystem_name, 585f9996aaSopenharmony_ci module_name) 595f9996aaSopenharmony_ci 605f9996aaSopenharmony_ci 615f9996aaSopenharmony_cidef get_build_config_from_label(label: str, current_toolchain_dir: str) -> str: 625f9996aaSopenharmony_ci build_config = label.replace('//', 'gen/').replace(':', '/') 635f9996aaSopenharmony_ci bc_file = '{}/{}.build_config'.format(current_toolchain_dir, build_config) 645f9996aaSopenharmony_ci return bc_file 655f9996aaSopenharmony_ci 665f9996aaSopenharmony_ci 675f9996aaSopenharmony_cidef add_dynamic_deps(output: str, build_config: str) -> str: 685f9996aaSopenharmony_ci external_deps = build_utils.expand_file_args( 695f9996aaSopenharmony_ci ['@FileArg({}:deps_info:external_deps)'.format(build_config)]) 705f9996aaSopenharmony_ci if external_deps[0] != '[ ]': 715f9996aaSopenharmony_ci output += "external_deps = " + external_deps[0] 725f9996aaSopenharmony_ci output += "}" 735f9996aaSopenharmony_ci return output 745f9996aaSopenharmony_ci 755f9996aaSopenharmony_ci 765f9996aaSopenharmony_ci# Copy the SDK module to the sdk output directory, 775f9996aaSopenharmony_ci# and generate the prebuilt template to BUILD.gn file. 785f9996aaSopenharmony_cidef gen_build_file(input_file: str, sdk_out_dir: str, generate_sig: bool, 795f9996aaSopenharmony_ci signature_file_check_dir: str): 805f9996aaSopenharmony_ci data = read_json_file(input_file) 815f9996aaSopenharmony_ci if data is None: 825f9996aaSopenharmony_ci raise Exception( 835f9996aaSopenharmony_ci "sdk interface description info error, file [{}] does not exist.". 845f9996aaSopenharmony_ci format(input_file)) 855f9996aaSopenharmony_ci 865f9996aaSopenharmony_ci build_file_content = 'import("//build/ohos.gni")\n' 875f9996aaSopenharmony_ci sdk_info = {} 885f9996aaSopenharmony_ci # interface check 895f9996aaSopenharmony_ci interface_mgr = InterfaceMgr() 905f9996aaSopenharmony_ci for module_desc in data: 915f9996aaSopenharmony_ci subsystem_name = module_desc.get('subsystem_name') 925f9996aaSopenharmony_ci part_name = module_desc.get('part_name') 935f9996aaSopenharmony_ci origin_name = module_desc.get('origin_name') 945f9996aaSopenharmony_ci module_type = module_desc.get('type') 955f9996aaSopenharmony_ci module_name = module_desc.get('name') 965f9996aaSopenharmony_ci module_info_file = module_desc.get('source_info') 975f9996aaSopenharmony_ci _current_toolchain_dir = module_desc.get('current_toolchain_dir') 985f9996aaSopenharmony_ci 995f9996aaSopenharmony_ci # read module_info.json file, get module source path 1005f9996aaSopenharmony_ci source_data = read_json_file(module_info_file) 1015f9996aaSopenharmony_ci if not source_data: 1025f9996aaSopenharmony_ci print("read module [{}] info file failed, filename [{}].".format( 1035f9996aaSopenharmony_ci module_name, module_info_file)) 1045f9996aaSopenharmony_ci continue 1055f9996aaSopenharmony_ci 1065f9996aaSopenharmony_ci # copy lib file 1075f9996aaSopenharmony_ci source = source_data.get('source') 1085f9996aaSopenharmony_ci if module_type == 'jar': 1095f9996aaSopenharmony_ci source = source_data.get('alternative_source') 1105f9996aaSopenharmony_ci 1115f9996aaSopenharmony_ci # check sdk type consistency 1125f9996aaSopenharmony_ci suffix = module_type 1135f9996aaSopenharmony_ci if module_type == "none": 1145f9996aaSopenharmony_ci continue 1155f9996aaSopenharmony_ci # Don't check suffix for maple sdk. 1165f9996aaSopenharmony_ci if module_type == "maple": 1175f9996aaSopenharmony_ci pass 1185f9996aaSopenharmony_ci elif not source.endswith(suffix): 1195f9996aaSopenharmony_ci raise Exception( 1205f9996aaSopenharmony_ci "sdk module [{}] type configuration is inconsistent.".format( 1215f9996aaSopenharmony_ci module_name)) 1225f9996aaSopenharmony_ci 1235f9996aaSopenharmony_ci module_sdk_out_dir = os.path.join(sdk_out_dir, module_name) 1245f9996aaSopenharmony_ci if not os.path.exists(module_sdk_out_dir): 1255f9996aaSopenharmony_ci os.makedirs(module_sdk_out_dir, exist_ok=True) 1265f9996aaSopenharmony_ci if module_type == "maple": 1275f9996aaSopenharmony_ci pass 1285f9996aaSopenharmony_ci else: 1295f9996aaSopenharmony_ci shutil.copy(source, module_sdk_out_dir) 1305f9996aaSopenharmony_ci 1315f9996aaSopenharmony_ci # copy headers file 1325f9996aaSopenharmony_ci header_base = module_desc.get('header_base') 1335f9996aaSopenharmony_ci if not header_base: 1345f9996aaSopenharmony_ci raise Exception("{}: header_base config error.".format( 1355f9996aaSopenharmony_ci module_desc.get('label'))) 1365f9996aaSopenharmony_ci 1375f9996aaSopenharmony_ci header_files = module_desc.get('header_files') 1385f9996aaSopenharmony_ci # copy to sdk/{subsystem_name}/{module_name}/include/ 1395f9996aaSopenharmony_ci for header_file in header_files: 1405f9996aaSopenharmony_ci rel_h_file = os.path.join(header_base, header_file) 1415f9996aaSopenharmony_ci 1425f9996aaSopenharmony_ci header_file_dest = os.path.join(module_sdk_out_dir, 'include', 1435f9996aaSopenharmony_ci header_file) 1445f9996aaSopenharmony_ci header_file_dest_dir = os.path.dirname(header_file_dest) 1455f9996aaSopenharmony_ci if not os.path.exists(header_file_dest_dir): 1465f9996aaSopenharmony_ci os.makedirs(header_file_dest_dir, exist_ok=True) 1475f9996aaSopenharmony_ci 1485f9996aaSopenharmony_ci shutil.copy(rel_h_file, header_file_dest) 1495f9996aaSopenharmony_ci 1505f9996aaSopenharmony_ci # generate or check header files 1515f9996aaSopenharmony_ci if module_type == 'so' and generate_sig is False: 1525f9996aaSopenharmony_ci check_header_files(signature_file_check_dir, sdk_out_dir, 1535f9996aaSopenharmony_ci origin_name, module_name, interface_mgr) 1545f9996aaSopenharmony_ci 1555f9996aaSopenharmony_ci # gen build file 1565f9996aaSopenharmony_ci lib_file = os.path.join(module_name, os.path.basename(source)) 1575f9996aaSopenharmony_ci if module_type == 'so': 1585f9996aaSopenharmony_ci build_file_content += SHARED_LIBRARY_BUILD_TEMPLATE % ( 1595f9996aaSopenharmony_ci module_name, module_name, module_name, lib_file, module_name, 1605f9996aaSopenharmony_ci subsystem_name, part_name) 1615f9996aaSopenharmony_ci elif module_type == 'jar': 1625f9996aaSopenharmony_ci bc = get_build_config_from_label(source_data.get("label"), 1635f9996aaSopenharmony_ci _current_toolchain_dir) 1645f9996aaSopenharmony_ci build_file_content += JAR_BUILD_TEMPLATE % (module_name, lib_file) 1655f9996aaSopenharmony_ci build_file_content = add_dynamic_deps(build_file_content, bc) 1665f9996aaSopenharmony_ci elif module_type == 'maple': 1675f9996aaSopenharmony_ci bc = get_build_config_from_label(source_data.get("label"), 1685f9996aaSopenharmony_ci _current_toolchain_dir) 1695f9996aaSopenharmony_ci bc_mplts = build_utils.expand_file_args( 1705f9996aaSopenharmony_ci ['@FileArg({}:outputs:output_mplt)'.format(bc)]) 1715f9996aaSopenharmony_ci bc_mplts = build_utils.parse_and_flatten_gn_lists(bc_mplts) 1725f9996aaSopenharmony_ci sdk_mplts = [] 1735f9996aaSopenharmony_ci base_dir = os.path.basename(module_sdk_out_dir) 1745f9996aaSopenharmony_ci for mplt in bc_mplts: 1755f9996aaSopenharmony_ci shutil.copy(mplt, module_sdk_out_dir) 1765f9996aaSopenharmony_ci sdk_mplts.append(os.path.join(base_dir, 1775f9996aaSopenharmony_ci os.path.basename(mplt))) 1785f9996aaSopenharmony_ci 1795f9996aaSopenharmony_ci bc_jar_path = build_utils.expand_file_args( 1805f9996aaSopenharmony_ci ["@FileArg({}:deps_info:unprocessed_jar_path)".format(bc)]) 1815f9996aaSopenharmony_ci bc_jar_path = build_utils.parse_and_flatten_gn_lists(bc_jar_path) 1825f9996aaSopenharmony_ci sdk_jar_path = [] 1835f9996aaSopenharmony_ci for jar in bc_jar_path: 1845f9996aaSopenharmony_ci shutil.copy(jar, module_sdk_out_dir) 1855f9996aaSopenharmony_ci sdk_jar_path.append( 1865f9996aaSopenharmony_ci os.path.join(base_dir, os.path.basename(jar))) 1875f9996aaSopenharmony_ci build_file_content += MAPLE_BUILD_TEMPLATE % ( 1885f9996aaSopenharmony_ci module_name, json.dumps(sdk_mplts, sort_keys=True, 1895f9996aaSopenharmony_ci indent=2), sdk_jar_path[0]) 1905f9996aaSopenharmony_ci build_file_content = add_dynamic_deps(build_file_content, bc) 1915f9996aaSopenharmony_ci elif module_type == 'rlib': 1925f9996aaSopenharmony_ci pass 1935f9996aaSopenharmony_ci else: 1945f9996aaSopenharmony_ci raise Exception( 1955f9996aaSopenharmony_ci 'The type of sdk module configuration is not supported.') 1965f9996aaSopenharmony_ci 1975f9996aaSopenharmony_ci module_info = { 1985f9996aaSopenharmony_ci 'source': lib_file, 1995f9996aaSopenharmony_ci 'label': module_desc.get('label'), 2005f9996aaSopenharmony_ci 'type': module_type 2015f9996aaSopenharmony_ci } 2025f9996aaSopenharmony_ci sdk_info[module_name] = module_info 2035f9996aaSopenharmony_ci return build_file_content, sdk_info 2045f9996aaSopenharmony_ci 2055f9996aaSopenharmony_ci 2065f9996aaSopenharmony_cidef generate_sdk(input_file: str, sdk_out_dir: str, output_build_file: str, sdk_info_file: str, 2075f9996aaSopenharmony_ci generate_sig: str, signature_file_check_dir: str, 2085f9996aaSopenharmony_ci signature_file_gen_dir: str): 2095f9996aaSopenharmony_ci build_file_content, sdk_info = gen_build_file(input_file, sdk_out_dir, 2105f9996aaSopenharmony_ci generate_sig, 2115f9996aaSopenharmony_ci signature_file_check_dir) 2125f9996aaSopenharmony_ci # write file, build gn file 2135f9996aaSopenharmony_ci write_file(output_build_file, build_file_content) 2145f9996aaSopenharmony_ci # sdk info return 2155f9996aaSopenharmony_ci write_json_file(sdk_info_file, sdk_info) 2165f9996aaSopenharmony_ci 2175f9996aaSopenharmony_ci # gen signature file 2185f9996aaSopenharmony_ci if generate_sig is True: 2195f9996aaSopenharmony_ci interface_mgr = InterfaceMgr() 2205f9996aaSopenharmony_ci interface_mgr.gen_sig_file_by_subsystem(sdk_out_dir, 2215f9996aaSopenharmony_ci signature_file_gen_dir) 2225f9996aaSopenharmony_ci 2235f9996aaSopenharmony_ci 2245f9996aaSopenharmony_cidef main(): 2255f9996aaSopenharmony_ci parser = argparse.ArgumentParser() 2265f9996aaSopenharmony_ci parser.add_argument('--input-file', help='', required=True) 2275f9996aaSopenharmony_ci parser.add_argument('--sdk-out-dir', help='', required=True) 2285f9996aaSopenharmony_ci parser.add_argument('--output-build-file', help='', required=True) 2295f9996aaSopenharmony_ci parser.add_argument('--sdk-info-file', help='', required=True) 2305f9996aaSopenharmony_ci parser.add_argument('--generate-sig', 2315f9996aaSopenharmony_ci dest='generate_sig', 2325f9996aaSopenharmony_ci action='store_true') 2335f9996aaSopenharmony_ci parser.set_defaults(generate_sig=False) 2345f9996aaSopenharmony_ci parser.add_argument('--signature-file-check-dir', help='', required=False) 2355f9996aaSopenharmony_ci parser.add_argument('--signature-file-gen-dir', help='', required=False) 2365f9996aaSopenharmony_ci args = parser.parse_args() 2375f9996aaSopenharmony_ci 2385f9996aaSopenharmony_ci generate_sdk(args.input_file, args.sdk_out_dir, args.output_build_file, 2395f9996aaSopenharmony_ci args.sdk_info_file, args.generate_sig, 2405f9996aaSopenharmony_ci args.signature_file_check_dir, args.signature_file_gen_dir) 2415f9996aaSopenharmony_ci return 0 2425f9996aaSopenharmony_ci 2435f9996aaSopenharmony_ci 2445f9996aaSopenharmony_ciif __name__ == '__main__': 2455f9996aaSopenharmony_ci sys.exit(main()) 246