• 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 sys
17import argparse
18import os
19import json
20import copy
21
22sys.path.append(
23    os.path.dirname(os.path.dirname(os.path.dirname(
24        os.path.abspath(__file__)))))
25from scripts.util import build_utils  # noqa E402
26
27deps_metadta_cache = {}
28
29
30def get_all_deps(direct_deps):
31    if direct_deps == []:
32        return []
33    deps = copy.deepcopy(direct_deps)
34    all_deps = set()
35    all_deps.update(deps)
36    while len(deps) > 0:
37        dep = deps.pop(0)
38        if dep not in deps_metadta_cache:
39            with open(dep) as dep_fp:
40                deps_metadta_cache[dep] = json.load(dep_fp).get('root')
41        for n in deps_metadta_cache[dep].get('metadata_deps'):
42            if n not in all_deps:
43                deps.append(n)
44                all_deps.add(n)
45    return sorted(list(all_deps))
46
47
48def get_deps_metadata(deps):
49    return [deps_metadta_cache[d] for d in deps]
50
51
52def get_deps_of_type(deps_data, target_type):
53    return [d for d in deps_data if d['type'] == target_type]
54
55
56class Deps(object):
57    def __init__(self, direct_deps):
58        self.direct_deps = direct_deps
59        self.all_deps = get_all_deps(direct_deps)
60        self.all_deps_data = get_deps_metadata(self.all_deps)
61
62    def All(self, target_type):
63        return get_deps_of_type(self.all_deps_data, target_type)
64
65
66def write_meta_data(options, direct_deps):
67    meta_data = {
68        'root': {
69            'type': options.type,
70            'metadata_path': options.output,
71            'metadata_deps': direct_deps
72        }
73    }
74    root = meta_data['root']
75    if options.type == 'app_profile':
76        root[options.type] = options.app_profile
77        root['resources'] = options.resources
78    if options.type == 'js_assets':
79        root[options.type] = options.js_assets
80        if options.js_forms:
81            root['js_forms'] = options.js_forms
82        if options.testrunner:
83            root['testrunner'] = options.testrunner
84    if options.type == 'ets_assets':
85        root[options.type] = options.ets_assets
86    if options.type == 'assets':
87        root[options.type] = options.raw_assets
88    if options.type == 'unresolved_assets':
89        root[options.type] = options.unresolved_assets
90    if options.type == 'resources':
91        deps = Deps(direct_deps)
92        root[options.type] = options.resources
93        package_name = options.package_name
94        root['package_name'] = package_name if package_name else ""
95        for target_type in ['app_profile']:
96            for dep in deps.All(target_type):
97                if root.get(target_type):
98                    root.get(target_type).extend(dep[target_type])
99                    root.get('resources').extend(dep['resources'])
100                else:
101                    root[target_type] = dep[target_type]
102                    root['resources'] += dep['resources']
103    if options.type == 'hap' or options.type == 'resources':
104        hap_profile = options.hap_profile
105        root['hap_profile'] = hap_profile if hap_profile else ""
106
107    # Merge all metadata
108    if options.type == 'hap':
109        deps = Deps(direct_deps)
110        root['hap_path'] = options.hap_path
111        for target_type in ['js_assets', 'ets_assets', 'assets', 'resources']:
112            root[target_type] = []
113        if options.js_assets:
114            root['js_assets'] = options.js_assets
115        if options.ets_assets:
116            root['ets_assets'] = options.ets_assets
117        if options.raw_assets:
118            root['assets'] = options.raw_assets
119        if options.resources:
120            root['resources'] = options.resources
121        for target_type in ['js_assets', 'ets_assets', 'assets', 'resources', 'app_profile']:
122            for dep in deps.All(target_type):
123                if root.get(target_type):
124                    root.get(target_type).extend(dep[target_type])
125                    root.get('hap_profile').extend(dep['hap_profile'])
126                else:
127                    root[target_type] = dep[target_type]
128                    if dep.get('hap_profile'):
129                        root['hap_profile'] = dep['hap_profile']
130                    if dep.get('js_forms'):
131                        root['js_forms'] = dep['js_forms']
132                    if dep.get('testrunner'):
133                        root['testrunner'] = dep['testrunner']
134        target_type = 'unresolved_assets'
135        for dep in deps.All(target_type):
136            if options.js2abc:
137                if isinstance(dep[target_type], list):
138                    for ability_path in dep[target_type]:
139                        root.get('js_assets').append(ability_path)
140                else:
141                    root.get('js_assets').append(dep[target_type])
142            else:
143                if isinstance(dep[target_type], list):
144                    for ability_path in dep[target_type]:
145                        root.get('ets_assets').append(ability_path)
146                else:
147                    root.get('ets_assets').append(dep[target_type])
148    build_utils.write_json(meta_data, options.output, only_if_changed=True)
149
150
151# Collect assets entry according to config.json
152def load_assets(options, assets, assets_type):
153    pre_path = assets[0]
154    pre_path = pre_path.rstrip('/')
155    with open(options.hap_profile) as profile:
156        config = json.load(profile)
157
158        # In multi-ability cases, load the assets entry according to "srcPath" in config.json
159        if os.path.basename(pre_path) == 'js' or os.path.basename(pre_path) == 'ets':
160            assets = []
161            for ability in config['module']['abilities']:
162                if assets_type == 'js':
163                    if ability.__contains__('srcPath') and ability.get('srcLanguage') == assets_type:
164                        assets.append(os.path.join(pre_path, ability['srcPath']))
165
166                    # Load js form entry according to "jsComponentName" in config.json
167                    if ability.__contains__('forms'):
168                        for form in ability['forms']:
169                            if form.__contains__('jsComponentName'):
170                                options.js_forms.append(os.path.join(pre_path, form['jsComponentName']))
171                            else:
172                                raise Exception('"module.abilities.ability.forms.form.jsComponentName" is required')
173                else:
174                    if ability.__contains__('srcPath'):
175                        assets.append(os.path.join(pre_path, ability['srcPath']))
176        else:
177            pre_path = os.path.dirname(pre_path)
178
179        # Load testrunner entry
180        if config['module'].__contains__('testRunner') and assets_type == 'js':
181            options.testrunner.append(os.path.join(pre_path, config['module']['testRunner']['srcPath']))
182    if not assets:
183        assets.append(pre_path)
184    return assets
185
186
187def main():
188    parser = argparse.ArgumentParser()
189
190    parser.add_argument('--output',
191                        help='output meta data file',
192                        required=True)
193    parser.add_argument('--type', help='type of module', required=True)
194    parser.add_argument('--raw-assets', nargs='+', help='raw assets directory')
195    parser.add_argument('--js-assets', nargs='+', help='js assets directory')
196    parser.add_argument('--ets-assets', nargs='+', help='ets assets directory')
197    parser.add_argument('--resources', nargs='+', help='resources directory')
198    parser.add_argument('--hap-path', help='path to output hap')
199    parser.add_argument('--depfile', help='path to .d file')
200    parser.add_argument('--deps-metadata', nargs="+", help='metadata deps')
201    parser.add_argument('--package-name',
202                        help='package name for hap resources')
203    parser.add_argument('--hap-profile', help='path to hap profile')
204    parser.add_argument('--app-profile', help='path to app profile')
205    parser.add_argument('--unresolved-assets', nargs='+', help='unresolved assets directory')
206    parser.add_argument('--js2abc',
207                        action='store_true',
208                        default=False,
209                        help='whether to transform js to ark bytecode')
210    options = parser.parse_args()
211    direct_deps = options.deps_metadata if options.deps_metadata else []
212
213    # js forms entry list
214    options.js_forms = []
215
216    # testrunner entry list
217    options.testrunner = []
218
219    if options.hap_profile:
220        if options.js_assets:
221            options.js_assets = load_assets(options, options.js_assets, 'js')
222        if options.ets_assets:
223            options.ets_assets = load_assets(options, options.ets_assets, 'ets')
224        if options.unresolved_assets:
225            options.unresolved_assets = load_assets(options, options.unresolved_assets, 'unresolved')
226
227    possible_input_strings = [
228        options.type, options.raw_assets, options.js_assets, options.ets_assets, options.resources,
229        options.hap_path, options.hap_profile, options.package_name, options.app_profile
230    ]
231    input_strings = [x for x in possible_input_strings if x]
232
233    build_utils.call_and_write_depfile_if_stale(
234        lambda: write_meta_data(options, direct_deps),
235        options,
236        depfile_deps=direct_deps,
237        input_paths=direct_deps,
238        input_strings=input_strings,
239        output_paths=([options.output]),
240        force=False,
241        add_pydeps=False)
242
243
244if __name__ == '__main__':
245    sys.exit(main())
246