• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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