鸿蒙应用开发-初见:Hvigor

前言

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

  1. 鸿蒙使用Hvigor工具链对应用或服务进行打包,打包后的产物位于各自模块下的build文件夹中
  2. 打包后的产物包括一个.app文件和多个.hap文件
  • .hap是可以直接运行在模拟器或真机设备中的软件包
  • .app则是用于应用/服务上架到华为应用市场
  1. 任务流的执行是通过构建插件hvigor-ohos-plugin利用Hvigor的任务编排机制实现的

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

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

json 复制代码
{
  "@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

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

模块级 build-profile.json5

json 复制代码
{
  "apiType": 'stageMode',  //API类型,支持FA和Stage模型
  "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": {
      "path": "./src/main/cpp/CMakeLists.txt",  //CMake配置文件,提供CMake构建脚本
      "arguments": "",  //传递给CMake的可选编译参数
      "abiFilters": [  //用于设置本机的ABI编译环境
        "armeabi-v7a",
        "arm64-v8a"
      ],
      "cppFlags": ""  //设置C++编译器的可选参数
    },
  },
  "targets": [  //定义的Target,开发者可以定制不同的Target,具体请参考定制多目标构建产物
    {
      "name": "default",
      "runtimeOS": "HarmonyOS",
    },
    {
      "name": "ohosTest",
    }    
  ]
}

依赖配置文件 oh-package.json5🌟🌟🌟

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

工程级 oh-package.json5

json 复制代码
{
  "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

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

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

ohpm原生三方包

json 复制代码
"dependencies": {
  // 包名:语义化版本
  "eslint": "^7.32.0",
  ... 
}

ohpm三方共享包

json 复制代码
"dependencies": {
 "@ohos/lottie": "^2.0.0",
 ...
}

ohpm本地共享模块

json 复制代码
"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模式。

取值 不同的AOT编译模式
type 默认模式,仅编译类型信息到字节码文件,编译速度最快。
partial 使用记录高频操作信息的ap文件(Arkcompiler Profile)进行部分编译,编译速度较快。

使用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的下拉箭头
  1. 点击左上角 ➕ 或者 Command + N,在弹出的列表中选择 Hvigor
  2. Name中填写名称,Application parameters配置以下参数

--mode module -p product=default assembleHap -p debuggable=false

  1. 在构建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中配置了完全不同的设备
json 复制代码
//Module1和Module2配置了完全不同的设备,deviceType不相交。
//Module1
{
    "deviceType": ["TV", "tablet"]
}
//Module2
{
    "deviceType": ["car", "router"]
}
  • deviceType相交是指两个Module的deviceType中包含了相同的设备
json 复制代码
//Module1和Module2因为都包含"tablet"设备,导致deviceType相交。
//Module1
{
    "deviceType": ["TV", "tablet"]
}
//Module2
{
    "deviceType": ["car", "tablet"]
}
  1. 校验分发规则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不相交,校验通过
json 复制代码
//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"
    }
        ]
    }
}
  1. 校验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,校验通过

json 复制代码
//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"]
    }
}
  1. 校验目标设备只有一个Entry类型的Module与之对应

a. 校验Entry类型Module的deviceType。如果deviceType不相交,校验通过。如果deviceType相交,继续校验Entry类型Module的distroFilter

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

json 复制代码
//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,选择静态库模板

2. 进行开发代码,目录结构存储参照如下

tree 复制代码
  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的基本信息、依赖项等
  1. 定义导出文件入口

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

json 复制代码
{
  "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文件设置为入口文件为例

json 复制代码
{
  ...
  "main": "./src/main/ets/components/mainpage/MainPage.ets",
  ...
}
  1. 在当前HAR模块的build-profile.json5中,将artifactType字段值设置为obfuscation
json 复制代码
{
  // 只有stageMode才支持代码混淆
  "apiType": "stageMode",
  "buildOption": {
    // 进行代码混淆
    'artifactType': "obfuscation"
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS"
    }
  ]
}
  1. 若部分工程源文件无需构建到HAR包中,可在module目录下新建 .ohpmignore 文件,用于配置打包时要忽略的文件,支持正则表达式写法。将无需打包进HAR包的文件/文件夹名称写入 .ohpmignore 文件中。DevEco Studio构建时将过滤掉 .ohpmignore文件中所包含的文件目录

6. 选中HAR模块的根目录,点击 Build > Make Module '<module-name>'启动构建。

构建完成后,build目录下生成闭源HAR包产物

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

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

一次构建多个产物🌟🌟🌟🌟🌟

多工程构建配置

多工程开发能力支持将大型应用拆分为多个模块,每个模块对应一个单独工程

在每个工程分别编译生成HAP后,需统一打包生成一个APP,用于上架应用市场

  1. 分别在每个工程的build-profile.json5配置文件中,设置multiProjects字段值为true
json 复制代码
{
  "app": {
    ...
    "multiProjects": true,
  }
}
  1. 使用如下命令,将多个HAP进行打包
  • hap-list:多个HAP文件名称,如"1.hap"和"2.hap",用逗号隔开;
  • out-path:生成的APP名称,如"final.app"
css 复制代码
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,在编译构建时,会同时打出三个包

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

定义target产物的deviceType

  1. 每一个target均可以指定支持的设备类型deviceType
  2. 也可以不定义。如果不定义,则该target默认支持module.json5中定义的设备类型
  3. 在定义每个target的deviceType时,支持的设备类型必须在module.json5中已经定义
json 复制代码
{
  "apiType": 'stageMode',
  "buildOption": {
  },
  "targets": [
    {
      "name": "default",  //未定义deviceType,默认支持config.json或module.json5中定义的设备类型
      "runtimeOS": "HarmonyOS",
    },
    {
      "name": "free",
      "runtimeOS": "HarmonyOS",
      "config": {
        "deviceType": [  //定义free支持的设备类型为phone
          "phone"
        ]
      }
    },
    {
      "name": "pay",
      "runtimeOS": "HarmonyOS",
      "config": {
        "deviceType": [  //定义pay支持的设备类型为phone
          "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页面

json 复制代码
{
  "apiType": 'stageMode',
  "buildOption": {
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS",
      "source": {  //定义Stage模型中默认版target的pages源码文件
        "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引用的多个资源文件目录下,存在同名的资源,则在构建打包过程中,将按照配置的资源文件目录顺序进行选择,也就是说优先选择前面定义的
json 复制代码
{
  "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使用的资源文件目录,该功能在API 9及以上版本的工程中生效
        "directories": [
          "./src/main/resources_default",
          "./src/main/resources_pay"
        ]
      }
    }
  ]
}

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

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

定义target产物的distroFilter

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

配置APP多product构建产物

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

定义多project产物的products

  1. 每一个product对应一个定制的APP包,因此,在定制APP多目标构建产物前,应提前规划好需要定制的product名称
  2. 在定制product时,必须存在"default"的product,否则编译时会出现错误
json 复制代码
  "app": {
    "signingConfigs": [],
    "compileSdkVersion": 9,
    "compatibleSdkVersion": 9,
    "products": [
      {
        "name": "default",  //默认的product,不可更改名称
      },
      {
        "name": "productA",  //定制的productA
      }, 
      {
        "name": "productB",  //定制的productB
      }
    ]
  }

定义product产物的bundleName信息

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

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

定义product的签名配置信息

  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签名文件与签名界面配置的签名文件保持一致即可

json 复制代码
"app": {
    "signingConfigs": [],
    "compileSdkVersion": 9,
    "compatibleSdkVersion": 9,
    "products": [
      {
        "name": "default",
        "bundleName": "com.example00.com",
        "signingConfig": "default"  //定义default的签名文件信息
      },
      {
        "name": "productA",
        "bundleName": "com.example01.com",
        "signingConfig": "productA"  //定义productA的签名文件信息
      },
      {
        "name": "productB",
        "bundleName": "com.example02.com",
        "signingConfig": "productB"  //定义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中

json 复制代码
{
  "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": [
        {
          "name": "default",  //将default target打包到default APP中
          "applyToProducts": [
            "default"
          ]
        },
        {
          "name": "free",  //将free target打包到productA APP中
          "applyToProducts": [
            "productA"
          ]
        },
        {
          "name": "pay",  //将pay target打包到productB APP中
          "applyToProducts": [
            "productB"
          ]
        }
      ]
    }
  ]
}

构建定义的product产物

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

  1. 单击右上角的图标,指定需要打包的ProductTarget ,然后单击Apply保存。例如选择"ProductA"中,entry模块对应的"free"Target。
  • Product:选择需要构建的APP包。
  • Product Info:该APP包的BundleName和SigningConfig信息。
  • Target Select:选择各个模块的Target,该Target需要包含在定义的Product中才能选择,如果未包含则显示"No Target to apply"
  1. 执行编译构建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 > Ma ke 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

单工程多目标构建总结

资料

相关推荐
Android技术栈5 小时前
鸿蒙开发(NEXT/API 12)【管理应用与Wear Engine服务的连接状态】手机侧应用开发
服务器·harmonyos·鸿蒙·鸿蒙系统·openharmony
baobao熊17 小时前
【HarmonyOS】时间处理Dayjs
华为·harmonyos
zhongcx1 天前
鸿蒙应用示例:DevEco Testing 工具的常用功能及使用场景
harmonyos
@海~涛1 天前
鸿蒙OpenHarmony
华为·harmonyos
zhongcx1 天前
鸿蒙应用示例:镂空效果实现教程
harmonyos
训山1 天前
【11】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-模块化语法与自定义组件
笔记·学习·华为·harmonyos·鸿蒙系统
helloxmg1 天前
鸿蒙harmonyos next flutter混合开发之开发package
flutter·华为·harmonyos
zhongcx2 天前
鸿蒙应用示例:ArkTS UI框架中的文本缩进技巧
harmonyos
东林知识库2 天前
鸿蒙NEXT开发-自定义构建函数(基于最新api12稳定版)
华为·harmonyos
裴云飞2 天前
鸿蒙性能优化之布局优化
性能优化·harmonyos