Hvigor 应用编译

研究目标

  1. 定位编译核心节点代码,利于自定义脚本辅助工程应用开发
  2. 加深对当前应用工程的目录结构使用的理解

预备知识

  1. 了解HarmonyOS应用开发
  2. 了解HarmonyOS应用的工程目录结构
  3. 了解HSP,HAR,HAP概念
  4. 见过hvigor和hvigor-ohos-plugin

试验环境

  1. MacBook Pro: Apple M1
  2. DevEco Studio 3.1.1 Release
  3. HarmonyOS SDK API 9
  4. hvigor版本: 2.4.2
  5. hvigor-ohos-plugin版本: 2.4.2

编译方式

HarmonyOS应用编译有两种方式:1. 通过DevEco Studio菜单 2. 通过脚本命令。

这两种方式最终都是通过启动 "@ohos/hvigor" 包中的index.js来完成操作的。

当前hvigor暂不支持全局命令行工具,依赖工程中的hvigorw工具。

命令运行时的参数:

  1. 官方在【'更新时间: 2024-03-30 10:25' "hvigor命令行"】 这篇文章中针对命令中的参数有所描述【文档对参数描述极少,不推荐】
  2. 通过运行 hvigorw 脚本,添加'--help'也可以看到相关参数的使用方法【推荐使用此种方式查看】

命令编译格式

./hvigorw [taskNames...] <options>

less 复制代码
Options:
  -v, --version                     查看hvigor版本号
  -e, --error                       输出错误日志
  -w, --warn                        输出警告日志
  -i, --info                        输出信息日志
  -d, --debug                       输出调试日志
  --stacktrace                      输出所有堆栈信息
  -p, --prop <value>                定义额外属性
  -m, --mode <string>               指定编译范围: project, module
  -s, --sync                        同步插件信息
  --enable-build-script-type-check  启用生成脚本hvigorfile.ts类型检查
  --no-parallel                     禁止并行编译
  --no-incremental                  禁止增量编译
  --no-daemon                       禁用守护进程
  --stop-daemon                     关闭当前工程的守护进程
  --stop-daemon-all                 关闭所有工程的守护进程
  --status-daemon                   展示工程中所有守护进程的状态
  -h, --help                        查看命令的使用方法
makefile 复制代码
Commands:
  version                           显示Hvigor版本号
  tasks                             显示所有模块任务
  taskTree                          以树状形式,显示所有模块任务

命令编译演示

首先进入到应用工程根目录下(通过DevEco 中的Terminal可以直接进入到根目录)

查看 hvigor 版本号

以下命令任意一个均可以

  1. sh hvigorw -v
  2. sh hvigorw --version
  3. sh hvigorw version

查看工程任务

sh hvigorw tasks

命令结果展示了HarmonyOS应用编译时,可以提供的服务类型.

任务分类

  1. Help tasks
  2. Other tasks
  3. hook tasks
  4. Sync tasks

hvigor将应用工程按照"应用","模块"划分方式来执行所有类型的任务分类。这一点从 "sh hvigorw tasks"和正常编译时的日志可以推测出来。

"sh hvigorw tasks"命令结果的结构如下

当前演示的应用工程共有3个模块:

  1. entry
  2. harlibrary
  3. hsplibrary
sql 复制代码
--------------------------------------------------------------------------
All tasks from hvigor node 'entry' <= 模块'entry'
--------------------------------------------------------------------------
Help tasks <= tasks和taskTree为任务名称,即"命令编译格式"中的taskName
-------------
tasks - Displays the tasks of the HvigorNode.
taskTree - Displays the task dag tree of the HvigorNode.

Other tasks <= clean,default@PreBuild, ...为任务名称,即"命令编译格式"中的taskName
-------------
clean
PreviewBuild
buildHotReloadResource
HotReloadBuild
default@PreBuild
default@MergeProfile - Merge app config manifest files.
default@BuildNativeWithCmake - Compile cpp source with Cmake.
default@BuildNativeWithNinja - Compile cpp source with Ninja.
default@MakePackInfo - Generate module pack.info.
default@ProcessLibs
default@GenerateMetadata
default@ProcessProfile - Process app config manifest file
default@ProcessResource
default@GenerateLoaderJson - Generate loader.json.
default@CompileResource - Compile project resource.
default@CompileArkTS - Compile ArkTS components for rich device in Stage Mode.
default@CompileJS - Compile ArkTS or JS components using Node.js for rich device in Stage Mode.
default@PackageHap - Build the Hap package.
default@SignHap
default@PreviewHookCompileResource
default@ReplacePreviewerPage
default@PreviewUpdateAssets - Update main_pages.json and module.json before PreviewBuild.
default@PreviewArkTS
default@HotReloadArkTS

hook tasks
-------------
compileNative
assembleHap
buildPreviewerResource

Sync tasks
-------------
init

> hvigor Finished :entry:tasks... after 1 ms 
--------------------------------------------------------------------------
All tasks from hvigor node 'harlibrary' <= 模块'harlibrary'
--------------------------------------------------------------------------
Help tasks
-------------
tasks - Displays the tasks of the HvigorNode.
taskTree - Displays the task dag tree of the HvigorNode.

Other tasks
-------------
clean
PreviewBuild
default@PreBuild
default@BuildNativeWithCmake - Compile cpp source with Cmake.
default@BuildNativeWithNinja - Compile cpp source with Ninja.
default@MergeProfile - Merge app config manifest files.
default@ProcessProfile - Process app config manifest file
default@ProcessResource
default@ProcessLibs
default@CompileResource - Compile project resource.
default@PackageHar - Build the har package.
default@GenerateLoaderJson - Generate loader.json.
default@PreviewHookCompileResource
default@PreviewUpdateAssets - Update main_pages.json and module.json before PreviewBuild.
default@PreviewArkTS

hook tasks
-------------
compileNative
assembleHar
buildPreviewerResource

Sync tasks
-------------
init

> hvigor Finished :harlibrary:tasks... after 1 ms 
--------------------------------------------------------------------------
All tasks from hvigor node 'hsplibrary' <= 模块'hsplibrary'
--------------------------------------------------------------------------
Help tasks
-------------
tasks - Displays the tasks of the HvigorNode.
taskTree - Displays the task dag tree of the HvigorNode.

Other tasks
-------------
clean
buildHotReloadResource
PreviewBuild
HotReloadBuild
default@PreBuild
default@MergeProfile - Merge app config manifest files.
default@BuildNativeWithCmake - Compile cpp source with Cmake.
default@BuildNativeWithNinja - Compile cpp source with Ninja.
default@MakePackInfo - Generate module pack.info.
default@ProcessLibs
default@GenerateMetadata
default@ProcessProfile - Process app config manifest file
default@ProcessResource
default@GenerateLoaderJson - Generate loader.json.
default@CompileResource - Compile project resource.
default@CompileArkTS - Compile ArkTS components for rich device in Stage Mode.
default@CompileJS - Compile ArkTS or JS components using Node.js for rich device in Stage Mode.
default@PackageHsp - Build the Hsp package.
default@PrepareSharedHarResource
default@SignHsp
default@PackageSharedHar
default@PreviewHookCompileResource
default@ReplacePreviewerPage
default@PreviewUpdateAssets - Update main_pages.json and module.json before PreviewBuild.
default@PreviewArkTS
default@HotReloadArkTS

hook tasks
-------------
compileNative
assembleHsp
buildPreviewerResource

Sync tasks
-------------
init

> hvigor Finished :hsplibrary:tasks... after 1 ms 
--------------------------------------------------------------------------
All tasks from hvigor node 'HarmonyLearn' <= 应用'hsplibrary'
--------------------------------------------------------------------------
Help tasks
-------------
tasks - Displays the tasks of the HvigorNode.
taskTree - Displays the task dag tree of the HvigorNode.

Other tasks
-------------
PreBuildApp
MakeProjectPackInfo - Generate project pack.info.
GeneratePackRes - Build the 'pack.res' file
PackageApp - Build the app package.
SignApp
clean

hook tasks
-------------
assembleApp

Sync tasks
-------------
init

> hvigor Finished ::tasks... after 1 ms 
> hvigor BUILD SUCCESSFUL in 150 ms 

正常的编译日志

PreBuildApp是任务名称,红色部分是模块名称,蓝色部分是任务名称

编译整个应用

sh hvigorw assembleApp -m project

命令执行完成后,最终会在根目录下生成一个build文件夹

编译hap模块

hap模块,即module.json5 文件中的type, 要么是entry, 要么是feature.

按照官方定义的特征就是:包含Ability的模块

sh hvigorw assembleHap -m module

命令执行完成后,仅仅在每个模块下生成一个build文件夹

编译Release版本

这里用到了 -p 参数,指的是自定义属性

debuggable是属性,true是属性值。

sh hvigorw assembleHap -m module -p debuggable=false

如下两张图,左图是Debug版本,右图是Release版本,即debuggable=false

编译输出Hvigor日志

sh hvigorw assembleHap -i -d -w -e

命令运行时的日志如下图,明显和我们平时编译时看到的日志形式不一样

如下这张图是sh hvigorw assembleHap命令执行时的日志,正常开发过程中的样子

输出hvigor日志,对于分析 hvigor 和 hvigor-ohos-plugin 有一定的帮助-From harvey

菜单编译

操作路径

  1. Build -> "Build Hap(s)/APP(s)" -> Build Hap(s)
  2. Build -> "Build Hap(s)/APP(s)" -> Build App(s)

编译时,在控制台"Run"栏中,可以在第一行看到编译命令,精简一下就是:

arduino 复制代码
xxx/node xxx/hvigor.js --mode module -p product=default assembleHap

编译时效果

xxx/node:其完整路径是已安装的node文件路径

xxx/hvigor.js:是处于工程缓存目录下,应用只要编译一次,其缓存目录以后是不会发生变化的

在DevEco Studio中配置应用编译参数

编译脚本

应用工程编译脚本

  • 每个模块都有一个hvigorfile.ts, 这是编译模块任务的脚本

编译hap

javascript 复制代码
export { hapTasks } from '@ohos/hvigor-ohos-plugin';

编译har

javascript 复制代码
export { harTasks } from '@ohos/hvigor-ohos-plugin';

编译hsp

ini 复制代码
module.exports = require('@ohos/hvigor-ohos-plugin').hspTasks
  • 根目录下的hvigorfile.ts, 这是编译应用任务的脚本

编译APP

javascript 复制代码
export { appTasks } from '@ohos/hvigor-ohos-plugin';
  • 根目录下的hvigor文件夹

hvigor-config.json5: 配置 hvigor 和 hvigor-ohos-plugin

hvigor-wrapper.js: 采用hvigorw / hvigorw.bat脚本编译时的启动脚本

脚本启动流程

工程根目录下的higorw脚本,通过shell命令加载 hvigor/hvigor-wrapper.js文件,hvigor-wrapper.js文件接收shell脚本传递过来的参数,启动.hvigor/.../hvigor.js编译入口文件,至此整个启动已完成。

如果需要在编译前插入js脚本,完全可以在higorw脚本中,使用"exec"命令先执行自己的js脚本。(From harvey)

hvigor-wrapper.js 文件中的部分内容

1.初始化工程目录

这些目录,在/Users/xxx/.hvigor

2.生成应用工程缓存名称,即 用户路径下/.hvigor/project_cache/xxx

生成规则:对工程完整路径进行md5加密

3.接收参数,hvigor-wrapper.js文件

4.启动hvigor.js

hvigor和hvigor-ohos-plugin概况

hvigor.js是一切编译任务启动的入口

ini 复制代码
Object.defineProperty(exports, "__esModule", { value: true });
const init_project_workspace_js_1 = require("../src/cli/wrapper/init-project-workspace.js");
const prepare_node_path_js_1 = require("../src/cli/wrapper/prepare-node-path.js")from harvey_fly;
const cli_js_1 = require("../src/cli/main/cli.js");
const cliOptions = (0, cli_js_1.parseCommand)();
//1. 初始化工程, 
(0, init_project_workspace_js_1.initProjectWorkSpace)();
//2. 初始化节点任务
(0, prepare_node_path_js_1.initNodePath)();
//3. 启动编译
(0, cli_js_1.startHvigorBuild)(cliOptions);

为了方便后续梳理,针对.hvigor文件夹中的如下两个包做个简单的类图

xxx是自己电脑的账户名 /Users/harvey/.hvigor/project_caches/46ba120c223ec60d2326a333bd18143a/workspace/node_modules/.pnpm/@ohos+hvigor-ohos-plugin@2.4.2_@ohos+hvigor@2.4.2/node_modules/@ohos

/Users/harvey/.hvigor/project_caches/46ba120c223ec60d2326a333bd18143a/workspace/node_modules/.pnpm/@ohos+hvigor-ohos-plugin@2.4.2_@ohos+hvigor@2.4.2/node_modules/@ohos/hvigor-ohos-plugin

图中,白色背景为@ohos包中的内容,绿色背景为hvigor-ohos-plugin包中的内容。如下这张图不包含FA模式

.hvigor内部编译流程

从应用开发角度看,整个应用编译流程是比较清晰和简单的:1. 配置信息 2.启动任务通道

整体编译过程中,通过DevEco Studio打开应用工程可知,有两个插件依赖:1. @hvigor 2. @hvigor-ohos-plugin。 有一个应用工程入口脚本:hvigor-wrapper.js。有多个模块任务脚本:hvigorfile.ts。这些文件之间的关系是如何处理的?看下图

通过上边这个流程可以确认的是,hvigorfile.ts文件就是HarmonyOS留给应用开发者的自定义脚本入口,仅仅是如何克服在 hvigor2.4.2 编译系统中的使用问题而已。不过这点也没有多大的担心,在HarmonyOS Next中,应该已支持自定义编译脚本了。

在"开始执行pipeline"时,前期的配置信息阶段,会实例化一个ProjectImpl对象, 里边包含了关键的任务信息,hvigor将其称之为_taskContainer

"开始执行pipeline"完成后,真正的任务执行调度是通过TaskExecutor中的setInterval循环触发的。

结尾

如果还想继续深入了解hvigor编译应用流程,可以按照你所了解到的hap/har/hsp/app概念,沿着一个任务慢慢的研究。

注意:守护进程启动过程中,所产生的日志,都在 "xxx/.hvigor/daemon/log/2.4.2/"文件夹中,每启动一次工程会生成两个命名为 "daemon-进程号.log" 的文件,一个代表刚启动的主进程,一个代表守护进程。

祝好运!

相关推荐
踏雪Vernon5 小时前
[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式
linux·docker·容器·harmonyos
Andy醒9 小时前
HarmonyOS . 沉浸状态栏使用
harmonyos·鸿蒙
yuwinter9 小时前
鸿蒙HarmonyOS学习笔记(2)
笔记·学习·harmonyos
jikuaidi6yuan11 小时前
鸿蒙系统(HarmonyOS)分布式任务调度
分布式·华为·harmonyos
SameX18 小时前
HarmonyOS Next 安全生态构建与展望
前端·harmonyos
SameX18 小时前
HarmonyOS Next 打造智能家居安全系统实战
harmonyos
Random_index1 天前
#Uniapp篇:支持纯血鸿蒙&发布&适配&UIUI
uni-app·harmonyos
鸿蒙自习室1 天前
鸿蒙多线程开发——线程间数据通信对象02
ui·harmonyos·鸿蒙
SuperHeroWu71 天前
【HarmonyOS】鸿蒙应用接入微博分享
华为·harmonyos·鸿蒙·微博·微博分享·微博sdk集成·sdk集成