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 optparse 17import subprocess 18import sys 19import shutil 20import os 21import tempfile 22from util import build_utils # noqa: E402 23 24 25def sign_hap(hapsigner, private_key_path, sign_algo, certificate_profile, 26 keystore_path, keystorepasswd, keyalias, certificate_file, 27 unsigned_hap_path, signed_hap_path): 28 cmd = ['java', '-jar', hapsigner, 'sign'] 29 cmd.extend(['-mode', 'localjks']) 30 cmd.extend(['-signAlg', sign_algo]) 31 cmd.extend(['-privatekey', private_key_path]) 32 cmd.extend(['-inputFile', unsigned_hap_path]) 33 cmd.extend(['-outputFile', signed_hap_path]) 34 cmd.extend(['-profile', certificate_profile]) 35 cmd.extend(['-keystore', keystore_path]) 36 cmd.extend(['-keystorepasswd', keystorepasswd]) 37 cmd.extend(['-keyaliaspasswd', keyalias]) 38 cmd.extend(['-certpath', certificate_file]) 39 cmd.extend(['-profileSigned', '1']) 40 child = subprocess.Popen(cmd, 41 stdout=subprocess.PIPE, 42 stderr=subprocess.PIPE) 43 stdout, stderr = child.communicate() 44 if child.returncode: 45 print(stdout.decode(), stderr.decode()) 46 raise Exception("Failed to sign hap") 47 48 49def create_hap(options, signed_hap): 50 with build_utils.temp_dir() as package_dir, tempfile.NamedTemporaryFile( 51 suffix='.hap') as output: 52 packing_cmd = ['java', '-jar', options.hap_packing_tool] 53 packing_cmd.extend( 54 ['--mode', 'hap', '--force', 'true', '--out-path', output.name]) 55 56 hap_profile_path = os.path.join(package_dir, 57 os.path.basename(options.hap_profile)) 58 shutil.copy(options.hap_profile, hap_profile_path) 59 packing_cmd.extend(['--json-path', hap_profile_path]) 60 61 if options.dso: 62 lib_path = os.path.join(package_dir, "lib") 63 os.mkdir(lib_path) 64 for dso in options.dso: 65 shutil.copy(dso, lib_path) 66 packing_cmd.extend(['--lib-path', lib_path]) 67 68 if options.packaged_resources: 69 build_utils.extract_all(options.packaged_resources, 70 package_dir, 71 no_clobber=False) 72 packing_cmd.extend( 73 ['--index-path', 74 os.path.join(package_dir, 'resources.index')]) 75 packing_cmd.extend( 76 ['--res-path', 77 os.path.join(package_dir, 'resources')]) 78 79 assets_dir = os.path.join(package_dir, 'assets') 80 if options.packaged_js_assets or options.assets: 81 packing_cmd.extend(['--assets-path', assets_dir]) 82 83 if options.packaged_js_assets: 84 build_utils.extract_all(options.packaged_js_assets, 85 package_dir, 86 no_clobber=False) 87 if options.assets: 88 if not os.path.exists(assets_dir): 89 os.mkdir(assets_dir) 90 for dire in options.assets: 91 shutil.copytree( 92 dire, 93 os.path.join(assets_dir, os.path.basename(dire))) 94 95 build_utils.check_output(packing_cmd) 96 97 sign_hap(options.hapsigner, options.private_key_path, 98 options.sign_algo, options.certificate_profile, 99 options.keystore_path, options.keystorepasswd, 100 options.keyalias, options.certificate_file, output.name, 101 signed_hap) 102 103 104def parse_args(args): 105 args = build_utils.expand_file_args(args) 106 107 parser = optparse.OptionParser() 108 build_utils.add_depfile_option(parser) 109 parser.add_option('--hap-path', help='path to output hap') 110 parser.add_option('--hapsigner', help='path to signer') 111 parser.add_option('--assets', help='path to assets') 112 parser.add_option('--dso', 113 action="append", 114 help='path to dynamic shared objects') 115 parser.add_option('--hap-profile', help='path to hap profile') 116 parser.add_option('--hap-packing-tool', help='path to hap packing tool') 117 parser.add_option('--private-key-path', help='path to private key') 118 parser.add_option('--sign-algo', help='signature algorithm') 119 parser.add_option('--certificate-profile', 120 help='path to certificate profile') 121 parser.add_option('--keyalias', help='keyalias') 122 parser.add_option('--keystore-path', help='path to keystore') 123 parser.add_option('--keystorepasswd', help='password of keystore') 124 parser.add_option('--certificate-file', help='path to certificate file') 125 parser.add_option('--packaged-resources', 126 help='path to packaged resources') 127 parser.add_option('--packaged-js-assets', 128 help='path to packaged js assets') 129 130 options, _ = parser.parse_args(args) 131 if options.assets: 132 options.assets = build_utils.parse_gn_list(options.assets) 133 return options 134 135 136def main(args): 137 options = parse_args(args) 138 139 inputs = [ 140 options.hap_profile, options.packaged_js_assets, 141 options.packaged_resources, options.certificate_file, 142 options.keystore_path, options.certificate_profile 143 ] 144 depfiles = [] 145 for dire in options.assets: 146 depfiles += (build_utils.get_all_files(dire)) 147 if options.dso: 148 depfiles.extend(options.dso) 149 150 build_utils.call_and_write_depfile_if_stale( 151 lambda: create_hap(options, options.hap_path), 152 options, 153 depfile_deps=depfiles, 154 input_paths=inputs + depfiles, 155 input_strings=[ 156 options.keystorepasswd, options.keyalias, options.sign_algo, 157 options.private_key_path 158 ], 159 output_paths=([options.hap_path]), 160 force=False, 161 add_pydeps=False) 162 163 164if __name__ == '__main__': 165 sys.exit(main(sys.argv[1:])) 166