• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2025 Huawei Device Co., Ltd.
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18import json
19import os
20import logging
21from pathlib import Path
22from typing import Union, Any, Dict
23from vmb.helpers import create_file, copy_file, load_json
24from vmb.tool import ToolBase
25from vmb.unit import BenchUnit
26
27here = os.path.realpath(os.path.dirname(__file__))
28certs = Path(here).parent.parent.joinpath('resources', 'hap-sign')
29log = logging.getLogger('vmb')
30
31hvigor_config = {
32    "modelVersion": "5.0.0",
33    "dependencies": {},
34    "execution": {},
35    "logging": {
36        "level": "info"
37    },
38    "debugging": {},
39    "nodeOptions": {}
40}
41
42build_config: Dict = {
43    "app": {
44        "signingConfigs": [],
45        "products": [
46          {
47            "name": "default",
48            "compileSdkVersion": 12,
49            "compatibleSdkVersion": 12,
50            "targetSdkVersion": 12,
51            "runtimeOS": "OpenHarmony",
52          }
53        ],
54        "buildModeSet": [
55          {
56            "name": "debug",
57          }
58        ]
59    },
60    "modules": [
61        {
62          "name": "entry",
63          "srcPath": "./entry",
64          "targets": [
65            {
66              "name": "default",
67              "applyToProducts": [
68                "default"
69              ]
70            }
71          ]
72        }
73    ]
74}
75
76build_config_module = {
77    "apiType": "stageMode",
78    "buildOption": {},
79    "targets": [{"name": "default"}]
80}
81
82oh_package = {
83    "modelVersion": "5.0.0",
84    "description": "blah",
85    "dependencies": {},
86    "devDeppendencies": {}
87}
88
89HVIGORFILE_TS = """
90import { appTasks } from '@ohos/hvigor-ohos-plugin';
91export default {
92    system: appTasks, plugins: []
93}
94"""
95
96MODULE_HVIGORFILE_TS = """
97import { hapTasks } from '@ohos/hvigor-ohos-plugin';
98export default {
99    system: hapTasks, plugins: []
100}
101"""
102
103app = {
104    "app": {
105        "bundleName": "com.example.hellopanda",
106        "vendor": "example",
107        "versionCode": 1000,
108        "versionName": "1.0.0",
109        "icon": "$media:app_icon",
110        "label": "$string:app_name"
111    }
112}
113
114app_string = {
115    "string": [{"name": "app_name", "value": "HelloPanda"}]
116}
117
118color = {
119    "color": [{
120        "name": "start_window_background",
121        "value": "#FFFFFF"
122    }]
123}
124
125string = {
126    "string": [
127        {"name": "module_desc", "value": "module description"},
128        {"name": "EntryAbility_desc", "value": "description"},
129        {"name": "EntryAbility_label", "value": "arkUiDemo"}
130    ]
131}
132
133main_pages = {
134    "src": ["pages/Index"]
135}
136
137
138class Tool(ToolBase):
139
140    app_name = 'com.example.hellopanda'
141    mod_name = 'entry'
142
143    def __init__(self, *args) -> None:
144        super().__init__(*args)
145        self.ohos_sdk = self.ensure_dir_env('OHOS_BASE_SDK_HOME')
146        self.hvigorw = ToolBase.get_cmd_path('hvigorw', 'HVIGORW')
147        self.signing_config = os.environ.get('HAP_SIGNING_CONFIG', '')
148        self.resource_dir = Path(here).parent.parent.joinpath('resources', 'hap')
149
150    @property
151    def name(self) -> str:
152        return 'Build HAP package (hvigorw)'
153
154    @staticmethod
155    def emit_config(content: Any, path: Union[str, Path]) -> None:
156        p = Path(path)
157        p.parent.mkdir(parents=True, exist_ok=True)
158        with create_file(p) as f:
159            f.write(json.dumps(content, indent=4))
160
161    def exec(self, bu: BenchUnit) -> None:
162        if self.signing_config:
163            try:
164                build_config['app']['signingConfigs'] = [{
165                    "name": "default",
166                    "material": load_json(self.signing_config)}]
167                build_config['app']['products'][0]['signingConfig'] = 'default'
168            except KeyError as e:
169                raise RuntimeError('Corrupted build config') from e
170        Tool.emit_config(build_config, bu.path.joinpath('build-profile.json5'))
171        Tool.emit_config(oh_package, bu.path.joinpath('oh-package.json5'))
172        Tool.emit_config(oh_package, bu.path.joinpath(self.mod_name, 'oh-package.json5'))
173        Tool.emit_config(hvigor_config, bu.path.joinpath('hvigor', 'hvigor-config.json5'))
174        Tool.emit_config(build_config_module, bu.path.joinpath(self.mod_name, 'build-profile.json5'))
175        Tool.emit_config(app, bu.path.joinpath('AppScope', 'app.json5'))
176        Tool.emit_config(app_string, bu.path.joinpath(
177            'AppScope', 'resources', 'base', 'element', 'string.json'))
178        Tool.emit_config(color, bu.path.joinpath(
179            self.mod_name, 'src', 'main', 'resources', 'base', 'element', 'color.json'))
180        Tool.emit_config(string, bu.path.joinpath(
181            self.mod_name, 'src', 'main', 'resources', 'en_US', 'element', 'string.json'))
182        Tool.emit_config(string, bu.path.joinpath(
183            self.mod_name, 'src', 'main', 'resources', 'base', 'element', 'string.json'))
184        Tool.emit_config(main_pages, bu.path.joinpath(
185            self.mod_name, 'src', 'main', 'resources', 'base', 'profile', 'main_pages.json'))
186        # to do: links instead of files?
187        with create_file(bu.path.joinpath('hvigorfile.ts')) as f:
188            f.write(HVIGORFILE_TS)
189        with create_file(bu.path.joinpath(self.mod_name, 'hvigorfile.ts')) as f:
190            f.write(MODULE_HVIGORFILE_TS)
191        # icon.png
192        icon_src = self.resource_dir.joinpath('icon.png')
193        icon = bu.path.joinpath('entry', 'src', 'main', 'resources', 'base', 'media', 'icon.png')
194        icon_app = bu.path.joinpath('AppScope', 'resources', 'base', 'media', 'app_icon.png')
195        copy_file(icon_src, icon)
196        copy_file(icon_src, icon_app)
197        # Index.ets
198        index_ets_src = self.resource_dir.joinpath('Index.ets')
199        index_ets = bu.path.joinpath('entry', 'src', 'main', 'ets', 'pages', 'Index.ets')
200        copy_file(index_ets_src, index_ets)
201        self.sh.run(f'{self.hvigorw} -d --mode module -p module={self.mod_name}@default '
202                    '-p product=default -p debuggable=true --no-daemon assembleHap',
203                    cwd=str(bu.path))
204        hap = bu.path.joinpath(self.mod_name,
205                               f'build/default/outputs/default/{self.mod_name}-default-signed.hap')
206        self.ensure_file(hap)
207        self.hdc.install(hap, self.app_name)
208