前言

本篇文章仅会介绍API9之后的Hvigor构建工具及其插件hvigor-ohos-plugin。且仅会介绍stage模型下的配置

1.鸿蒙使用Hvigor工具链对应用/服务进行打包,打包后的产物位于各自模块下的build文件夹中
2.打包后的产物包括一个.app文件和多个.hap文件

●.hap是可以直接运行在模拟器或真机设备中的软件包
●.app则是用于应用/服务上架到华为应用市场

3.任务流的执行是通过构建插件hvigor-ohos-plugin利用Hvigor的任务编排机制实现的

修改构建工具和构建插件版本

修改 hvigor 目录下的 hvigor-config.json5 文件

{
  "@ohos/hvigor": "1.6.0",
  "dependencies": {
        "@ohos/hvigor-ohos-plugin": "1.6.0"
  }
}

工程目录、配置文件、配置构建信息

无论是工程(App)级还是模块(Module)级,都提供以下三个文件

1.构建配置文件(build-profile.json5)
2.构建脚本文件(hvigorfile.ts)
3.依赖配置文件(oh-package.json5) 在这里插入图片描述

构建配置文件 build-profile.json5

构建配置文件,配置构建过程的一些参数

工程级 build-profile.json5

{
  "app": { 
    // 工程的签名信息,可包含多个签名信息
    "signingConfigs": [  
      {
        // 标识签名方案的名称
        "name": "default",  
        // 标识HarmonyOS应用
        "type": "HarmonyOS",  
        // 该方案的签名材料
        "material": {  
          // 调试或发布证书文件,格式为.cer
          "certpath": "D:\\SigningConfig\\debug_hos.cer",  
          // 密钥库密码,以密文形式呈现
          "storePassword": "******",
          // 密钥别名信息
          "keyAlias": "debugKey",  
          // 密钥密码,以密文形式呈现
          "keyPassword": "******",  
          // 调试或发布证书Profile文件,格式为.p7b
          "profile": "D:\\SigningConfig\\debug_hos.p7b",  
          // 密钥库signAlg参数
          "signAlg": "SHA256withECDSA",  
          // 密钥库文件,格式为.p12
          "storeFile": "D:\\SigningConfig\\debug_hos.p12" 
        }
      }
    ],
    // 指定HarmonyOS应用/服务编译时的SDK版本
    "compileSdkVersion": 9,  
    // 指定HarmonyOS应用/服务兼容的最低SDK版本
    "compatibleSdkVersion": 9,  
    // 定义构建的产品品类,如通用默认版、付费版、免费版等
    "products": [  
      {
        // 定义产品的名称,支持定制多product目标产物,具体请参考定制多目标构建产物
        "name": "default",  
        // 指定当前产品品类对应的签名信息,签名信息需要在signingConfigs中进行定义
        "signingConfig": "default",  
      }
    ]
  },
  "modules": [
    {
     // 模块名称
      "name": "entry",  
      // 标明模块根目录相对工程根目录的相对路径
      "srcPath": "./entry",  
      // 定义构建的APP产物,由product和各模块定义的targets共同定义
      "targets": [  
        {
           // target名称,由各个模块的build-profile.json5中的targets字段定义
          "name": "default",  
          "applyToProducts": [  
            // 表示将该模块下的“default” Target打包到“default” Product中
            "default"   
          ]
        }
      ]
    }
  ]
}

模块级 build-profile.json5

{
  // API类型,支持FA和Stage模型
  "apiType": 'stageMode',  
  // 是否在服务中心展示
  "showInServiceCenter": true,  
  "buildOption": {
    // 配置筛选har依赖.so资源文件的过滤规则
    "napiLibFilterOption": {
      // 按照.so文件的优先级顺序,打包最高优先级的.so文件
      "pickFirsts": [
        "**/1.so"
      ],
      // 按照.so文件的优先级顺序,打包最低优先级的.so 文件
      "pickLasts": [
        "**/2.so"
      ],
      // 排除的.so文件
      "excludes": [
        "**/3.so"
      ],
      // 允许当.so重名冲突时,使用高优先级的.so文件覆盖低优先级的.so文件
      "enableOverride": true
    },
    // cpp相关编译配置
    "externalNativeOptions": {
      // CMake配置文件,提供CMake构建脚本
      "path": "./src/main/cpp/CMakeLists.txt",  
      // 传递给CMake的可选编译参数
      "arguments": "", 
      // 用于设置本机的ABI编译环境
      "abiFilters": [  
        "armeabi-v7a",
        "arm64-v8a"
      ],
      // 设置C++编译器的可选参数
      "cppFlags": ""  
    },
  },
  // 定义的Target,开发者可以定制不同的Target,具体请参考定制多目标构建产物
  "targets": [  
    {
      "name": "default",
      "runtimeOS": "HarmonyOS",
    },
    {
      "name": "ohosTest",
    }    
  ]
}

依赖配置文件 oh-package.json5

应用/服务支持通过ohpm来安装、共享、分发代码,管理项目的依赖关系。oh-package.json5格式遵循标准的ohpm规范

工程级 oh-package.json5

{
  "name": "myapplication",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "",
  "author": "",
  "license": "",
  "dependencies": {},
  "devDependencies": {
    "@ohos/hypium": "1.0.6"
  }
}

模块级 oh-package.json5

{
  "name": "entry",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "index.ets",
  "author": "",
  "license": "",
  "dependencies": {},
}

oh-package.json5中配置ohpm包依赖

ohpm原生三方包

"dependencies": {
  // 包名:语义化版本
  "eslint": "^7.32.0",
  ... 
}

ohpm三方共享包

"dependencies": {
 "@ohos/lottie": "^2.0.0",
 ...
}

ohpm本地共享模块

"dependencies": {
 "library": "file:../library", 
 ...
}

依赖安装和同步

两种方式

1.在Terminal窗口执行ohpm install命令下载依赖包
2.单击编辑器窗口上方的 Sync Now 进行同步

依赖包会存储在工程或各模块的oh_modules目录下

怎么启动构建

1.通过单击或按钮,DevEco Studio会启动应用/服务的编译,并将编译后的HAP部署到设备中

2.通过DevEco Studio的 Build 菜单栏的编译选项进行构建,HAP的构建结果存放于各模块的“build”文件夹下,APP包的构建结果存放于工程的“build”文件夹下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

默认开启模块化编译模式

1.应用模块化编译是指 基于ESModule的Bundleless编译模式 ,使用原生ES Module规则构建源码。
2.Stage工程默认开启模块化编译,可有效缩短增量编译时间、减小编译后的包体积

开启AOT编译模式

AOT(Ahead Of Time)即提前编译,能够 在Host端(即运行DevEco Studio的电脑)将字节码提前编译成Target端(即运行应用的设备)可运行的机器码 ,这样字节码可以获得充分编译优化,放到Target端运行时可以获得加速

AOT编译模式

在模块级build-profile.json5文件中,buildOption内的aotCompileMode字段可以设置为以下值,对应不同的AOT模式。

在这里插入图片描述

使用type编译模式
json复制代码{
“apiType”: ‘stageMode’,
“buildOption”: {
“aotCompileMode”: “type”
},

}

使用partial编译模式

1.使用partial编译模式需要先使用type模式进行编译,获取到ap文件后,再进行partial模式编译
2.这种编译方式类似于Xcode的PGO文件,需要在相应场景下先运行一段时间,然后把ap文件从设备里取出来使用。一般使用较少,大家要了解的话点标题进入自己去看就行,挺简单的

DevEco编译Release版本的HAP

1.点击菜单栏 Run -> Edit Configurations 或者 Run App的下拉箭头

在这里插入图片描述
在这里插入图片描述

2.点击左上角 ➕ 或者 Command + N,在弹出的列表中选择 Hvigor
在这里插入图片描述

3.Name中填写名称,Application parameters配置以下参数

–mode module -p product=default assembleHap -p debuggable=false
在这里插入图片描述

4.在构建App的下拉列表中选择BuildRelease后,点击右边的在这里插入图片描述启动编译
在这里插入图片描述

HAP唯一性校验逻辑

1.HAP是 应用安装的基本单位,在DevEco Studio工程目录中,一个HAP对应一个Module。应用打包时,每个Module生成一个.hap文件
2.应用如果包含多个Module,在应用市场上架时,会将多个.hap文件打包成一个.app文件(称为Bundle),但 在云端分发和端侧安装时,仍然是以HAP为基本单位
3.为了能够正常分发和安装应用,需要 保证一个应用安装到设备时,Module的名称、Ability的名称不重复,并且只有一个Entry类型的Module与目标设备相对应

Module校验逻辑

校验目的:同一目标设备上Module唯一

1.校验Module的Name:如果多个Module的Name不同,则校验通过。如果Name相同,继续校验deviceType。
2.校验设备类型deviceType。如果deviceType不相交,则校验通过。如果deviceType相交,继续校验distroFilter

●deviceType不相交是指两个Module的deviceType中配置了完全不同的设备

//Module1和Module2配置了完全不同的设备,deviceType不相交。
//Module1
{
    "deviceType": ["TV", "tablet"]
}
//Module2
{
    "deviceType": ["car", "router"]
}

●deviceType相交是指两个Module的deviceType中包含了相同的设备

//Module1和Module2因为都包含“tablet”设备,导致deviceType相交。
//Module1
{
    "deviceType": ["TV", "tablet"]
}
//Module2
{
    "deviceType": ["car", "tablet"]
}

3.校验分发规则distroFilter。目前仅在API8的工程中校验。后面我们都会使用API9甚至10的版本,如果这块规则继续保留,咱们再回来看

Ability校验逻辑

校验目的:同一目标设备上Ability唯一

1.校验Ability的Name。如果多个Ability的Name不同,则校验通过。如果Name相同,继续校验Ability所属Module的deviceType。
2.校验Ability所属Module的deviceType。如果deviceType不相交,校验通过。如果deviceType相交,继续校验Ability所属Module的distroFilter

●两个Ability的Name相同,但其所属Module的deviceType不相交,校验通过

//Ability1和Ability2虽然名称相同,但由于其所属Module的deviceType不相交,所以可以区分两个Ability,校验通过。
//Ability1
{
    "module": {
        "name": "module_sample1",
        "deviceType": ["TV", "tablet"],
        "abilities": [
    {
        "name": "ability_sample"
    }
        ]
    }
}
//Ability2
{
     "module": {
        "name": "module_sample2",
        "deviceType": ["car", "router"],
        "abilities": [
    {
        "name": "ability_sample"
    }
        ]
    }
}

3.校验Ability所属Module的distroFilter。目前仅在API8的工程中校验。后面我们都会使用API9甚至10的版本,如果这块规则继续保留,咱们再回来看

Entry校验逻辑

校验目的:目标设备只有一个Entry类型的Module与之对应,Feature类型的Module经过deviceType及distroFilter指明的目标设备都需要存在Entry类型的Module

1.校验Feature类型的Module经过deviceType及distroFilter指明的目标设备都存在Entry类型的Module

例如,Bundle中存在一个Entry类型Module1,其支持设备为tablet和wearable,其分发规则为circle和rect形状的屏幕,同时存在一个Feature类型的Module2,通过分发规则可知,其可以分发到rect形状的tablet和wearable设备上,而rect形状的tablet和wearable设备上存在Entry类型的Module1,校验通过

//Entry类型Module1
{
    "module": {
        "name": "module_sample1",
        "type": "entry",
        "deviceType": ["tablet", "wearable"],
        "metadata": [
            {
                "name": "distroFilter_config",
                "resource": "$profile:distroFilter_config1"
            }
        ]
    }
}
//Module1的distroFilter,distroFilter_config1.json
{
    "screenShape":{
        "policy": "include",
        "value": ["circle", "rect"]
    }
}
//Feature类型Module2
{
     "module": {
        "name": "module_sample2",
        "type": "feature",
        "deviceType": ["tablet", "wearable"],
         "metadata": [
            {
                "name": "distroFilter_config",
                "resource": "$profile:distroFilter_config2"
            }
        ]
    }
}
//Module2的distroFilter,distroFilter_config2.json
{
    "screenShape":{
        "policy": "include",
        "value": ["rect"]
    }
}

2.校验目标设备只有一个Entry类型的Module与之对应

a. 校验Entry类型Module的deviceType。如果deviceType不相交,校验通过。如果deviceType相交,继续校验Entry类型Module的distroFilter
例如,同一个Bundle中存在两个Entry类型的Module,分别为Module1和Module2,两者的deviceType不相交,可以有效区分两个Module,校验通过。

//Entry类型Module1
{
    "module": {
        "name": "module_sample1",
        "type": "entry",
        "deviceType": ["tablet"]
    }
}
//Entry类型Module2
{
     "module": {
        name: "module_sample2",
        "type": "entry",
        "deviceType": ["wearable"]
    }
}

b. 校验Entry类型Module的distroFilter。如果distroFilter不相交,校验通过。如果distroFilter相交,校验失败,打包失败
同样的,这个等API10出来后看一下是否还支持,再做解析

构建混淆的闭源HAR

1.新建一个Module,选择静态库模板
在这里插入图片描述

  1. 进行开发代码,目录结构存储参照如下
  library  // HAR根目录
  ├─libs  // 存放用户自定义引用的Native库,一般为.so文件
  └─src
  │   └─main
  │     ├─cpp
  │     │  ├─types  // 定义Native API对外暴露的接口  
  │     │  │  └─liblibrary  
  │     │  │      ├─index.d.ts
  │     │  │      └─oh-package.json5 
  │     │  ├─CMakeLists.txt  // CMake配置文件  
  │     │  └─hello.cpp  // C++源码文件
  │     └─ets  // ArkTS源码目录
  │     │  └─components
  │     │     └─mainpage
  │     │         └─MainPage.ets
  │     ├─resources  // 资源目录,用于存放资源文件,如图片、多媒体、字符串等  
  │     └─module.json5  // 模块配置文件,包含当前HAR的配置信息  
  ├─build-profile.json5  // Hvigor编译构建所需的配置文件,包含编译选项
  ├─hvigorfile.ts  // Hvigor构建脚本文件,包含构建当前模块的插件、自定义任务等
  ├─index.ets  // HAR的入口文件,一般作为出口定义HAR对外提供的函数、组件等   
  └─oh-package.json5  // HAR的描述文件,定义HAR的基本信息、依赖项等

3.定义导出文件入口

在oh-package.json5中 “main”字段定义导出文件入口。若不设置“main”字段,默认以当前目录下index.ets为入口文件,依据.ets>.ts>.js的顺序依次检索

{
  "name": "myhar",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "index.ets",
  "author": "",
  "license": "Apache-2.0",
  "dependencies": {}
}

以将ets/components/mainpage/MainPage.ets文件设置为入口文件为例

{
  ...
  "main": "./src/main/ets/components/mainpage/MainPage.ets",
  ...
}

4.在当前HAR模块的build-profile.json5中,将artifactType字段值设置为obfuscation

{
  // 只有stageMode才支持代码混淆
  "apiType": "stageMode",
  "buildOption": {
    // 进行代码混淆
    'artifactType': "obfuscation"
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS"
    }
  ]
}

5.若部分工程源文件无需构建到HAR包中,可在module目录下新建 .ohpmignore文件,用于配置打包时要忽略的文件,支持正则表达式写法。将无需打包进HAR包的文件/文件夹名称写入 .ohpmignore文件中。DevEco Studio构建时将过滤掉 .ohpmignore文件中所包含的文件目录
在这里插入图片描述

  1. 选中HAR模块的根目录,点击 Build > Make Module ''启动构建。
    在这里插入图片描述

构建完成后,build目录下生成闭源HAR包产物
在这里插入图片描述

如需将闭源包转换为开源包,请将模块级build-profile.json5中“artifactType”字段值改为“original”或直接删除(缺省为original),再次触发编译

{
  "apiType": 'stageMode',
  "buildOption": {
    "artifactType": "original", // original表示不使用混淆模式
    ...
  },
  ...
}

一次构建多个产物

多工程构建配置

多工程开发能力支持将大型应用拆分为多个模块,每个模块对应一个单独工程
在每个工程分别编译生成HAP后,需统一打包生成一个APP,用于上架应用市场

1.分别在每个工程的build-profile.json5配置文件中,设置multiProjects字段值为true

{
  "app": {
    ...
    "multiProjects": true,
  }
}

2.使用如下命令,将多个HAP进行打包

●hap-list:多个HAP文件名称,如“1.hap”和“2.hap”,用逗号隔开;
●out-path:生成的APP名称,如“final.app”

java -jar app_packing_tool.jar --mode multiApp --hap-list 1.hap,2.hap --out-path final.app

单工程构建不同的目标产物

product概念

1.一个HarmonyOS工程由一个或多个模块组成,工程的构建产物为APP包,APP包用于应用/服务发布上架应用市场
2.一个工程可以定义多个product,每个product对应一个定制化应用包,通过配置可以实现一个工程构建出多个不同的应用包

target概念

1.工程内的每一个Entry/Feature模块,对应的构建产物为HAP,HAP是应用/服务可以独立运行在设备中的形态。
2.一个模块可以定义多个target,每个target对应一个定制的HAP,通过配置可以实现一个模块构建出不同的HAP

配置HAP多target构建产物

1.每一个Entry/Feature模块均支持定制不同的target,通过模块中的 build-profile.json5 文件实现差异化定制
2.当前支持 设备类型(deviceType)、源码集(source)、资源(resource)、C++依赖的.so(buildOption) 的定制

定义多target产物的targets

1.每一个target对应一个定制的HAP,在定制HAP多目标构建产物前,应提前规划好需要定制的target名称。可以通过targets字段完成
2.Har模块只有默认配置的default Target,不支持定制其它Target

1.在定义HarmonyOS应用/服务的target时,需要通过runtimeOS字段标识该Target是一个可运行在HarmonyOS设备上的HAP
2.如果未定义该字段,或该字段取值为OpenHarmony,则表示该Target是一个运行在OpenHarmony设备上的HAP,不能运行在HarmonyOS设备上

下面文件定义了default、free和pay 3个target,在编译构建时,会同时打出三个包

{
  "apiType": 'stageMode',
  "buildOption": {  
  },
  // 定义不同的target
  "targets": [  
    {
      // 默认target名称default
      "name": "default",  
      "runtimeOS": "HarmonyOS",
    },
    {
      // 免费版target名称
      "name": "free",  
      "runtimeOS": "HarmonyOS"
    },
    {
      // 付费版target名称
      "name": "pay", 
      "runtimeOS": "HarmonyOS",
    }
  ]
}

定义target产物的deviceType

1.每一个target均可以指定支持的设备类型deviceType
2.也可以不定义。如果不定义,则该target默认支持module.json5中定义的设备类型
3.在定义每个target的deviceType时,支持的设备类型必须在module.json5中已经定义

{
  "apiType": 'stageMode',
  "buildOption": {
  },
  "targets": [
    {
     // 未定义deviceType,默认支持config.json或module.json5中定义的设备类型
      "name": "default",  
      "runtimeOS": "HarmonyOS",
    },
    {
      "name": "free",
      "runtimeOS": "HarmonyOS",
      "config": {
        // 定义free支持的设备类型为phone
        "deviceType": [  
          "phone"
        ]
      }
    },
    {
      "name": "pay",
      "runtimeOS": "HarmonyOS",
      "config": {
          // 定义pay支持的设备类型为phone
        "deviceType": [  
          "phone"
        ]
      }
    }
  ]
}

定义target产物的source源码集

Stage模型支持对pages源码目录的page页面进行定制

如下,在模块的pages目录下分别定义了index.ets、page1.ets和page2.ets三个页面。其中default使用了index.ets页面;free使用了index.ets和page1.ets页面;pay使用了index.ets和page2.ets页面

{
  "apiType": 'stageMode',
  "buildOption": {
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS",
      // 定义Stage模型中默认版target的pages源码文件
      "source": {  
        "pages": [
          "pages/index"
        ]
      }
    },
    {
      "name": "free",
      "runtimeOS": "HarmonyOS",
      "config": {
        "deviceType": [
          "phone"
        ]
      },
      "source": {  
        // 定义Stage模型中免费版target的pages源码文件
        "pages": [
          "pages/index",
          "pages/page1"
        ]
      }
    },
    {
      "name": "pay",
      "runtimeOS": "HarmonyOS",
      "config": {
        "deviceType": [
          "phone"
        ]
      },
      "source": {  
        // 定义Stage模型中付费版target的pages源码文件
        "pages": [
          "pages/index",
          "pages/page2"
        ]
      }
    }
  ]
}

定义target产物的资源resource

1.将每个target所使用的资源存放在不同的资源目录下以作区分
2.ArkTS工程支持对main目录下的资源文件目录(resource)进行定制
3.如果target引用的多个资源文件目录下,存在同名的资源,则在构建打包过程中,将按照配置的资源文件目录顺序进行选择,也就是说优先选择前面定义的

{
  "apiType": 'stageMode',
  "buildOption": {
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS",
      "source": {
        "pages": [
          "pages/index"
        ]
      },
      "resource": {  
        // 定义默认版target使用的资源文件目录
        "directories": [
          "./src/main/resources_default"
        ]
      }
    },
    {
      "name": "free",
      "runtimeOS": "HarmonyOS",
      "config": {
        "deviceType": [
          "phone"
        ]
      },
      "source": {  
        "pages": [
          "pages/index",
          "pages/page1"
        ]
      },
      "resource": {  
        // 定义免费版target使用的资源文件目录
        "directories": [
          "./src/main/resources_default",
          "./src/main/resources_free"
        ]
      }
    },
    {
      "name": "pay",
      "runtimeOS": "HarmonyOS",
      "config": {
        "deviceType": [
          "phone"
        ]
      },
      "source": {  
        "pages": [
          "pages/index",
          "pages/page2"
        ]
      },
      "resource": {  
        // 定义付费版target使用的资源文件目录
        "directories": [
          "./src/main/resources_default",
          "./src/main/resources_pay"
        ]
      }
    }
  ]
}

定义target产物C++工程依赖的.so文件

这部分有C++经验的去看吧。因为我们一般都是ets开发,这部分涉及的少

定义target产物的distroFilter

目前只有API8的工程支持这些,先略过

配置APP多product构建产物

APP用于应用/服务上架发布,针对不同的应用场景,可以在app.json定制不同的product,每个product中支持对bundleName、签名信息以及包含的target进行定制

定义多project产物的products

1.每一个product对应一个定制的APP包,因此,在定制APP多目标构建产物前,应提前规划好需要定制的product名称
2.在定制product时,必须存在“default”的product,否则编译时会出现错误


  "app": {
    "signingConfigs": [],
    "compileSdkVersion": 9,
    "compatibleSdkVersion": 9,
    "products": [
      {
        // 默认的product,不可更改名称
        "name": "default",  
      },
      {
        // 定制的productA
        "name": "productA",  
      }, 
      {
        // 定制的productB
        "name": "productB",  
      }
    ]
  }

定义product产物的bundleName

针对每个定义的product,均可以定制不同的bundleName,如果product未定义bundleName,则采用工程默认的bundleName

"app": {
    "signingConfigs": [],
    "compileSdkVersion": 9,
    "compatibleSdkVersion": 9,
    "products": [
      {
        "name": "default",
        // 定义default的bundleName信息
        "bundleName": "com.example00.com"  
      },
      {
        "name": "productA",
        // 定义productA的bundleName信息
        "bundleName": "com.example01.com"  
      },
      {
        "name": "productB",
        // 定义productB的bundleName信息
        "bundleName": "com.example02.com"  
      }
    ]
  }

定义product的signingConfig

1.针对每个定义的product,均可以定制不同的signingConfig签名文件,如果product未定义signingConfig,则构建生成未签名的APP包

2.通常情况下,您首先需要在签名配置界面或工程的build-profile.json5文件中配置签名信息

例如在File > Project Structure > Project > Signing Configs界面,分别配置default、product_A和product_B的签名信息
在这里插入图片描述

签名信息配置完成后,再添加各个product对应的签名文件,示例如下所示

您也可以提前在product中定义签名文件信息,然后在签名界面对每个product进行签名,确保配置的product签名文件与签名界面配置的签名文件保持一致即可

"app": {
    "signingConfigs": [],
    "compileSdkVersion": 9,
    "compatibleSdkVersion": 9,
    "products": [
      {
        "name": "default",
        "bundleName": "com.example00.com",
        // 定义default的签名文件信息
        "signingConfig": "default"  
      },
      {
        "name": "productA",
        "bundleName": "com.example01.com",
        // 定义productA的签名文件信息
        "signingConfig": "productA"  
      },
      {
        "name": "productB",
        "bundleName": "com.example02.com",
        // 定义productB的签名文件信息
        "signingConfig": "productB"  
      }
    ]
  }

定义product产物包含的target

1.开发者可以选择将定义的target打包到哪一个product中
2.每个product可以指定一个或多个target
3.每个target也可以打包到不同的product中,但是同一个module的不同target不能打包到同一个product中

例如,前面定义了default、free和pay三个target,现需要将default target打包到default product中;将free target打包到productA中;将pay target打包到productB中

{
  "app": {
    "signingConfigs": [
      {
        "name": "productB",
        "type": "HarmonyOS",
        "material": {
          "storePassword": "000000190F49B79861A613EF0D4F24A6F9D52A7EB18CBDC590F8A7D48244508D0B3896E8D0B9DC7F17",
          "certpath": "D:/key/Release/myApplication_release.cer",
          "keyAlias": "myApplication",
          "keyPassword": "00000019111E2366391063DFB79F132A48D666374E1D2FA8E2744EF62E9DDC44245F443F5738FEF242",
          "profile": "D:/key/Release/myApplication_release Provision.p7b",
          "signAlg": "SHA256withECDSA",
          "storeFile": "D:/key/Release/myApplication_release.p12"
        }
      }
    ],
    "compileSdkVersion": 9,
    "compatibleSdkVersion": 9,
    "products": [
      {
        "name": "default",
        "bundleName": "com.example00.com",
        "signingConfig": "default"
      },
      {
        "name": "productA",
        "bundleName": "com.example01.com",
        "signingConfig": "productA"
      },
      {
        "name": "productB",
        "bundleName": "com.example02.com",
        "signingConfig": "productB"
      }
    ]
  },
  "modules": [
    {
      "name": "entry",
      "srcPath": "./entry",
      "targets": [
        {
          // 将default target打包到default APP中
          "name": "default",  
          "applyToProducts": [
            "default"
          ]
        },
        {
          // 将free target打包到productA APP中
          "name": "free",  
          "applyToProducts": [
            "productA"
          ]
        },
        {
          // 将pay target打包到productB APP中
          "name": "pay",  
          "applyToProducts": [
            "productB"
          ]
        }
      ]
    }
  ]
}

构建定义的product产物

每个target对应一个HAP,每个product对应一个APP包,在编译构建时,如果存在多product或多target时,您可以指定编译具体的包

1.单击右上角的图标,指定需要打包的Product及Target,然后单击Apply保存。例如选择“ProductA”中,entry模块对应的“free”Target。

●Product:选择需要构建的APP包。
●Product Info:该APP包的BundleName和SigningConfig信息。
●Target Select:选择各个模块的Target,该Target需要包含在定义的Product中才能选择,如果未包含则显示“No Target to apply”
在这里插入图片描述

2.执行编译构建APP/HAP的任务:

●单击菜单栏的Build > Build Hap(s)/APP(s) > Build APP(s) ,构建指定的Product对应的APP

●例如,按照上述设置,此时DevEco Studio将构建生成ProductA的APP包。default和ProductB的APP均不会生成。

●单击菜单栏的Build > Build Hap(s)/APP(s) > Build Hap(s) ,构建指定Product下的所有Target对应发的HAP。

例如,按照上述配置,此时DevEco Studio将构建生成entry模块下default和free的HAP。

●如果您想将某个模块下的指定target打包生成HAP,可以在工程目录中,单击模块名,然后再单击Build > Make Module ‘模块名 ’,此时DevEco Studio将构建生成模块下指定target对应的包。

例如,按照上述配置,此时DevEco Studio将构建生成entry模块下free的HAP,不会生成default的HAP。
在这里插入图片描述

调试和运行指定的Target

1.使用DevEco Studio调试或运行应用/服务时,每个模块只能选择其中的一个target运行
2.可以通过单击右上角的图标,指定需要调试或运行的Product下对应的Module Target,然后单击Apply保存

在选择需要调试或运行的target时,需要注意选择该target所属的Product,否则将找不到可调试和运行的target

在这里插入图片描述

单工程多目标构建总结

工程下多product

{
  "app": {
    // 工程的签名信息,可包含多个签名信息
    "signingConfigs": [],
    // 指定HarmonyOS应用/服务编译时的SDK版本
    "compileSdkVersion": 9,
    // 指定HarmonyOS应用/服务兼容的最低SDK版本
    "compatibleSdkVersion": 9,
    // 定义构建的产品品类,如通用默认版、付费版、免费版等
    "products": [
      {
        // 定义产品的名称,支持定制多product目标产物,具体请参考定制多目标构建产物
        "name": "default",
        // 定义default的bundleName信息
        "bundleName": "com.unravel.business",
        // 指定当前产品品类对应的签名信息,签名信息需要在signingConfigs中进行定义
        "signingConfig": "default"
      },
      {
        "name": "productA",
        // 定义productA的bundleName信息
        "bundleName": "com.unravel.businessA",
        "signingConfig": "default"
      },
      {
        "name": "productB",
        // 定义productB的bundleName信息
        "bundleName": "com.unravel.businessB",
      }
    ]
  },
  "modules": [
    {
      // 模块名称
      "name": "entry",
      // 标明模块根目录相对工程根目录的相对路径
      "srcPath": "./entry",
      // 定义构建的APP产物,由product和各模块定义的targets共同定义
      "targets": [
        {
          // target名称,由各个模块的build-profile.json5中的targets字段定义
          "name": "default",
          "applyToProducts": [
            // 表示将该模块下的“default” Target打包到“default” Product中
            "default"
          ]
        },
        {
          // 将free target打包到productA APP中
          "name": "free",
          "applyToProducts": [
            "productA"
          ]
        },
        {
          // 将pay target打包到productB APP中
          "name": "pay",
          "applyToProducts": [
            "productB"
          ]
        }
      ]
    },
    {
      "name": "MyHar",
      "srcPath": "./MyHar"
    },
    {
      "name": "MyHSP",
      "srcPath": "./MyHSP",
      "targets": [
        {
          "name": "default",
          "applyToProducts": [
            "default"
          ]
        }
      ]
    },
    {
      "name": "MyFeatureAbility",
      "srcPath": "./MyFeatureAbility",
      "targets": [
        {
          "name": "default",
          "applyToProducts": [
            "default"
          ]
        }
      ]
    },
    {
      "name": "MyGridFeatureAbility",
      "srcPath": "./MyGridFeatureAbility",
      "targets": [
        {
          "name": "default",
          "applyToProducts": [
            "default"
          ]
        }
      ]
    }
  ]
}

定义有哪些product

一个工程可以通过build-profile.json中的products字段定义至少一个product,默认定义的product为default。且必须有一个为default的product

定义每一个product

1.工程下的单个product通过对bundleName、签名信息以及包含的target进行定制
2.创建工程时默认定义的product为default

每一个product对应一个定制的APP包

1.bundleName: 必须是唯一的,默认继承app.json中的bundleName
2.signingConfig: 需要先在signingConfigs字段中配置签名的信息有哪些,然后指定其中一个。如果未定义,会构建未签名的包
3.target:通过在modules.targets中每个target下面定义applyToProducts指定安装到的product。

Module下多target

{
  // API类型,支持FA和Stage模型
  "apiType": 'stageMode',
  // 是否在服务中心展示
  "showInServiceCenter": true,
  "buildOption": {
    "sourceOption": {
      "workers": [
        './src/main/ets/workers/Worker.ts'
      ]
    }
  },
  // 定义的Target,开发者可以定制不同的Target,具体请参考定制多目标构建产物
  "targets": [
    {
      "name": "default",
      //默认target名称default
      "runtimeOS": "HarmonyOS",
    },
    {
      "name": "free",
      //免费版target名称
      "runtimeOS": "HarmonyOS",
      "config": {
        // 定义free支持的设备类型为phone
        "deviceType": [
          "phone",
          "tablet"
        ],
      },
      // 定义Stage模型中默认版target的pages源码文件
      source: {
        pages: [
          "pages/BusinessCardPage",
          "pages/DetailPage",
          "pages/Index"
        ]
      },
      // 定义默认版target使用的资源文件目录
      "resource": {
        // 定义默认版target使用的资源文件目录
        "directories": [
          "./src/main/resources"
        ]
      }
    },
    {
      "name": "pay",
      //付费版target名称
      "runtimeOS": "HarmonyOS",
      "config": {
        // 定义free支持的设备类型为phone
        "deviceType": [
          "phone"
        ]
      }
    },
    {
      "name": "ohosTest",
    }
  ]
}

定义有哪些target

一个Module可以通过build-profile.json5中的targets字段定义至少一个target,定义target的时候需要定义runtimeOS表示是运行于HarmonyOS还是OpenHarmony。

定义每一个target

1.Module下的单个target通过设备类型(deviceType)、源码集(source)、资源(resource)、C++依赖的.so(buildOption)定制
2.创建工程时默认定义的target为default

每一个target对应一个定制的HAP

1.deviceType:必须是module.json5中deviceTypes定义的子集,默认继承所有
2.source:其中的pages字段,必须是module.json5中pages定义的子集,默认继承所有
3.resource: 其中的directories字段指定资源目录的路径,每个target所使用的资源存放在不同的资源目录下,资源中有相同名称时按照配置顺序依次取

来个图

在这里插入图片描述

写在最后

有很多小伙伴不知道该从哪里开始学习鸿蒙开发技术?也不知道鸿蒙开发的知识点重点掌握的又有哪些?自学时频繁踩坑,导致浪费大量时间。结果还是一知半解。所以有一份实用的鸿蒙(HarmonyOS NEXT)全栈开发资料用来跟着学习是非常有必要的。

获取这份完整版高清学习路线,请点击→[鸿蒙全栈开发学习资料]

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了

最新鸿蒙全栈开发学习线路在这里插入图片描述

鸿蒙HarmonyOS开发教学视频

在这里插入图片描述
在这里插入图片描述

大厂面试真题

在这里插入图片描述

在这里插入图片描述

鸿蒙OpenHarmony源码剖析

在这里插入图片描述

这份资料能帮住各位小伙伴理清自己的学习思路,更加快捷有效的掌握鸿蒙开发的各种知识。有需要的小伙伴自行领取,,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→[鸿蒙全栈开发学习资料]

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐