DevEco Studio 配置构建:HarmonyOS Next 多目标产物定制
介绍在 DevEco Studio 中配置 HarmonyOS Next 应用的多目标构建产物。内容包括定制 HAP 包名、设备类型、分发规则、预加载分包、源码集(pages/sourceRoots)、资源文件、图标标签及 C++ 依赖。同时讲解了如何构建指定 Target 的产物以及如何在 IDE 中调试运行特定 Target。

介绍在 DevEco Studio 中配置 HarmonyOS Next 应用的多目标构建产物。内容包括定制 HAP 包名、设备类型、分发规则、预加载分包、源码集(pages/sourceRoots)、资源文件、图标标签及 C++ 依赖。同时讲解了如何构建指定 Target 的产物以及如何在 IDE 中调试运行特定 Target。

每一个 Entry/Feature 模块均支持定制不同的 target,通过在模块中的 build-profile.json5 文件中实现差异化定制,当前支持 HAP 包名、设备类型 (deviceType)、源码集 (source)、资源 (resource)、buildOption 配置项 (如 C++ 依赖的.so、混淆配置、abi 类型、cppFlags 等)、分发规则 (distributionFilter) 的定制。
每一个 target 对应一个定制的 HAP,因此,在定制 HAP 多目标构建产物前,应提前规划好需要定制的 target 名称。例如,以 ArkTS Stage 模型为例,定义一个免费版和付费版,模块级 build-profile.json5 文件示例如下:
{
"apiType": "stageMode",
"buildOption": {},
"targets": [
{
"name": "default"
},
{
"name": "free"
},
{
"name": "pay"
}
]
}
按照上述 target 的定义,在编译构建时,会同时打包生成 default、free 和 pay 三个不同的 HAP。
每一个 target 均可以指定产物命名。
{
"apiType": "stageMode",
"buildOption": {},
"targets": [
{
"name": "default",
"output": {
"artifactName": "customizedTargetOutputName-1.0.0"
}
},
{
"name": "free",
"output": {
"artifactName": "customizedTargetOutputName1-1.0.0"
}
},
{
"name": "pay",
"output": {
"artifactName": "customizedTargetOutputName2-1.0.0"
}
}
]
}
如果已配置签名,target 产物对应的 HAP 包名为开发者定制的名称;如果未配置签名,target 产物对应的 HAP 包名为开发者定制的名称 +unsigned。
每一个 target 均可以指定支持的设备类型 deviceType,也可以不定义。如果不定义,则该 target 默认支持 config.json 或 module.json5 中定义的设备类型。
同时,在定义每个 target 的 deviceType 时,支持的设备类型必须在 config.json 或 module.json5 中已经定义。例如,在上述定义的 3 个 target 中,分别定义 default 默认支持所有设备类型,free 和 pay 版本只支持 phone 设备。
{
"apiType": "stageMode",
"buildOption": {},
"targets": [
{
"name": "default"
},
{
"name": "free",
"config": {
"deviceType": ["phone"]
}
},
{
"name": "pay",
"config": {
"deviceType": ["phone"]
}
}
]
}
在未定义 target 的分发规则 distributionFilter 时,以 module 配置 distroFilter/distributionFilter 分发规则为准。
针对多 target 存在相同设备类型 deviceType 的场景,相同设备类型的 target 需要指定分发规则 distributionFilter。
如果是 FA 工程,请将 distributionFilter 字段替换为 distroFilter。
{
"apiType": "stageMode",
"buildOption": {},
"targets": [
{
"name": "default"
},
{
"name": "free",
"config": {
"distributionFilter": {
"screenShape": {
"policy": "include",
"value": ["circle"]
}
}
}
},
{
"name": "pay",
"config": {
"distributionFilter": {
"screenShape": {
"policy": "include",
"value": ["rect"]
}
}
}
}
]
}
对于元服务,每一个 target 均可以指定 preloads 的分包,也可以不定义。如果不定义,则以 module.json5 中的配置为准。
{
"apiType": "stageMode",
"showInServiceCenter": true,
"buildOption": {},
"targets": [
{
"name": "default"
},
{
"name": "free"
},
{
"name": "pay",
"config": {
"atomicService": {
"preloads": [
{
"moduleName": "preloadSharedLibrary"
}
]
}
}
}
]
}
对于 source 源码集的定制,由于 Stage 模型和 FA 模型的差异,Stage 模型支持对 pages 源码目录的 page 页面进行定制,FA 模型则支持对 Ability 源码目录下的 page 页面进行定制。
{
"apiType": "stageMode",
"buildOption": {},
"targets": [
{
"name": "default",
"source": {
"pages": ["pages/Index"]
}
},
{
"name": "free",
"config": {
"deviceType": ["phone"]
},
"source": {
"pages": ["pages/Index", "pages/Page1"]
}
},
{
"name": "pay",
"config": {
"deviceType": ["phone"]
},
"source": {
"pages": ["pages/Index", "pages/Page2"]
}
}
]
}
{
"apiType": "faMode",
"buildOption": {},
"targets": [
{
"name": "default",
"source": {
"abilities": [
{
"name": ".MainAbility",
"pages": ["pages/index"]
}
]
}
},
{
"name": "free",
"config": {
"deviceType": ["phone"]
},
"source": {
"abilities": [
{
"name": ".MainAbility",
"pages": ["pages/index", "pages/page1"]
}
]
}
},
{
"name": "pay",
"config": {
"deviceType": ["phone"]
},
"source": {
"abilities": [
{
"name": ".MainAbility",
"pages": ["pages/index", "pages/page2"]
}
]
}
}
]
}
在模块的主代码空间 (src/main) 下,承载着开发者编写的公共代码。如果开发者需要实现不同 target 之间的差异化逻辑,可以使用差异化代码空间 (sourceRoots)。配合差异化代码空间的能力,可以在主代码空间中代码不变的情况下,针对不同的 target,编译对应的代码到最终产物中。
概念说明
例如以下工程目录:
entry |--src |----main |------ets |--------code |----------test.ets |----target |------util |--------util.ets |--index.ets
规格限制
编译时模块 target 的选择优先级说明
在模块编译的过程中,该模块使用的 sourceRoots 由当前模块编译时的 target 来决定。当前模块编译时选择 target 的优先级则为:命令行显式指定 > 直接引用方 target > default。
如以下示例:hap -> hsp -> har(->表示依赖)
其中 hap 和 hsp 存在三个 target:default、custom、static,而 har 存在两个 target:default、static。
示例
1. 在 entry 模块的 build-profile.json5 中添加 sourceRoots:
{
"apiType": "stageMode",
"buildOption": {},
"targets": [
{
"name": "default",
"source": {
"sourceRoots": ["./src/default"]
}
},
{
"name": "custom",
"source": {
"sourceRoots": ["./src/custom"]
}
}
]
}
2. 在 src 目录下新增 default/Test.ets 和 custom/Test.ets,新增后的模块目录结构:
entry |--src |--main |--ets |--pages |--Index.ets |--default |--Test.ets |--custom |--Test.ets
3. 在 default/Test.ets 中写入代码:
export const getName = () => "default"
4. 在 custom/Test.ets 中写入代码:
export const getName = () => "custom"
5. 修改 src/main/ets/pages/Index.ets 的代码:
import { getName } from 'entry/Test';
@Entry
@Component
struct Index {
@State message: string = getName();
build() {
RelativeContainer() {
Text(this.message)
}
.height('100%')
.width('100%')
}
}
6. 在工程级的 build-profile.json5 中配置 targets:
{
"app": {
"signingConfigs": [],
"products": [
{
"name": "default",
"signingConfig": "default",
"compatibleSdkVersion": "5.0.2(14)",
"runtimeOS": "HarmonyOS"
},
{
"name": "custom",
"signingConfig": "default",
"compatibleSdkVersion": "5.0.2(14)",
"runtimeOS": "HarmonyOS"
}
],
"buildModeSet": [
{
"name": "debug"
},
{
"name": "release"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": ["default"]
},
{
"name": "custom",
"applyToProducts": ["default"]
}
]
}
]
}
7. Sync 完成后,选择 entry 的 target 为 default,点击 Run,界面展示 default;选择 entry 的 target 为 custom,点击 Run,则界面展示 custom。
每个 target 使用的资源文件可能存在差异,在开发过程中,开发者可以将每个 target 所使用的资源存放在不同的资源目录下。其中,ArkTS 工程支持对 main 目录下的资源文件目录 (resource) 进行定制;JS 工程支持对 main 目录下的资源文件目录 (resource) 及 Ability 下的资源文件目录 (res) 进行定制。如下为 ArkTS 工程的资源文件目录定制示例:
{
"apiType": "stageMode",
"buildOption": {},
"targets": [
{
"name": "default",
"source": {
"pages": ["pages/Index"]
},
"resource": {
"directories": ["./src/main/resources_default"]
}
},
{
"name": "free",
"config": {
"deviceType": ["phone"]
},
"source": {
"pages": ["pages/Index", "pages/Page1"]
},
"resource": {
"directories": ["./src/main/resources_default", "./src/main/resources_free"]
}
},
{
"name": "pay",
"config": {
"deviceType": ["phone"]
},
"source": {
"pages": ["pages/Index", "pages/Page2"]
},
"resource": {
"directories": ["./src/main/resources_default", "./src/main/resources_pay"]
}
}
]
}
请注意,如果 target 引用的多个资源文件目录下,存在同名的资源,则在构建打包过程中,将按照配置的资源文件目录顺序进行选择。例如,上述付费版 target 引用的资源中,resource_default 和 resource_pay 中存在同名的资源文件,则 resource_default 中的资源会被打包到 HAP 中。
针对每一个的 target 的 ability,均可以定制不同的 icon、label 和 launchType。如果不定义,则该 target 采用 module.json5 中 module.abilities 配置的 icon、label,launchType 默认为"singleton"。示例如下所示:
{
"apiType": "stageMode",
"buildOption": {},
"targets": [
{
"name": "default",
"source": {
"abilities": [
{
"name": "EntryAbility",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"launchType": "singleton"
}
]
}
},
{
"name": "free",
"source": {
"abilities": [
{
"name": "EntryAbility",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"launchType": "multiton"
}
]
}
}
]
}
在 C++ 工程中,可以对每个 target 依赖的.so 文件进行定制。例如某模块依赖了 function1.so、function2.so 和 function3.so 三个文件,其中 target 为 default 的产物依赖了 function1.so 和 function2.so;其中 target 为 vip 的产物依赖了 function1.so 和 function3.so,则示例代码如下所示:
{
"apiType": "stageMode",
"buildOption": {
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": [],
"abiFilters": ["arm64-v8a", "x86_64"],
"cppFlags": ""
}
},
"targets": [
{
"name": "default",
"config": {
"buildOption": {
"nativeLib": {
"filter": {
"pickFirsts": ["**/function1.so"],
"excludes": ["**/function3.so"],
"enableOverride": true
}
}
}
}
},
{
"name": "vip",
"config": {
"buildOption": {
"nativeLib": {
"filter": {
"pickFirsts": ["**/function1.so"],
"excludes": ["**/function2.so"],
"enableOverride": true
}
}
}
}
}
]
}
每个 target 对应一个 HAP,每个 product 对应一个 APP 包,在编译构建时,如果存在多 product 或多 target 时,您可以指定编译具体的包。
在 DevEco Studio 右上角工具栏,指定需要打包的 Product 及 Target,然后单击 Apply 保存。例如选择"ProductA"中,entry 模块对应的"free" Target。
然后执行编译构建 APP/HAP 的任务:
如果您想将某个模块下的指定 target 打包生成 HAP,可以在工程目录中,单击模块名,然后再单击 Build > Make Module'模块名',此时 DevEco Studio 将构建生成模块下指定 target 对应的包。例如,按照上述配置,此时 DevEco Studio 将构建生成 entry 模块下 free 的 HAP,不会生成 default 的 HAP。
使用 DevEco Studio 调试或运行应用/元服务时,每个模块只能选择其中的一个 target 运行,可以通过单击右上角的工具栏图标,指定需要调试或运行的 Product 下对应的 Module Target,然后单击 Apply 保存。
说明
在选择需要调试或运行的 target 时,需要注意选择该 target 所属的 Product,否则将找不到可调试和运行的 target。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online