OpenHarmony DevEco Studio使用指南-定制多目标构建产物

丶龙八夷
发布于 2023-4-4 14:06
浏览
0收藏

通常情况下,应用厂商会根据不同的部署环境,不同的目标人群,不同的运行环境等,将同一个应用定制为不同的版本,如国内版、国际版、普通版、VIP版、免费版、付费版等。针对以上场景,DevEco Studio支持通过少量的代码差异化配置处理,在编译构建过程中实现一个应用构建出不同的目标产物版本,从而实现源代码、资源文件等的高效复用。

在了解OpenHarmony应用的多目标构建产物如何定制前,先了解product和target的概念:

  • 一个OpenHarmony工程由一个或多个模块组成,工程的构建产物为APP包,APP包用于应用/服务发布上架应用市场。由于不同的业务场景,需要定制不同的应用包,因此引入product概念。一个工程可以定义多个product,每个product对应一个定制化应用包,通过配置可以实现一个工程构建出多个不同的应用包。
  • 工程内的每一个Entry/Feature模块,对应的构建产物为HAP,HAP是应用/服务可以独立运行在设备中的形态。由于在不同的业务场景中,同一个模块可能需要定制不同的功能或资源,因此引入target的概念。一个模块可以定义多个target,每个target对应一个定制的HAP,通过配置可以实现一个模块构建出不同的HAP。

定制HAP多目标构建产物

每一个Entry/Feature模块均支持定制不同的target,通过在模块中的build-profile.json5文件中实现差异化定制,当前支持设备类型(deviceType)、源码集(source)、资源(resource)、C++依赖的.so(buildOption)的定制。同时,每一个Entry/Feature模块也支持定制不同的分发规则distroFilter,用于定义HAP对应的细分设备规格的分发策略。

定义目标产物target

每一个target对应一个定制的HAP,因此,在定制HAP多目标构建产物前,应提前规划好需要定制的target名称。例如,以ArkTS Stage模型为例,定义一个免费版和付费版,示例如下:

说明

如果是FA工程,Feature模块定制的Target,必须是Entry模块定义的Target的子集。

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

在定义OpenHarmony应用/服务的target时,默认的target名称default不能修改。按照上述target的定义,在编译构建时,会同时打包生成default、free和pay 3个不同的HAP。

定义产物的deviceType

每一个target均可以指定支持的设备类型deviceType,也可以不定义。如果不定义,则该target默认支持config.json或module.json5中定义的设备类型。

同时,在定义每个target的deviceType时,支持的设备类型必须在config.json或module.json5中已经定义。例如,在上述定义的3各target中,分别定义default默认支持所有设备类型,free和pay版本只支持tablet设备。

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

定义产物的source源码集

对于source源码集的定制,由于Stage模型和FA模型的差异,Stage模型支持对pages源码目录的page页面进行定制,FA模型则支持对Ability源码目录下的page页面进行定制。

  • 例如,Stage模型中的工程,在模块的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",
      "source": {  //定义Stage模型中默认版target的pages源码文件
        "pages": [
          "pages/index"
        ]
      }
    },
    {
      "name": "free",
      "config": {
        "deviceType": [
          "tablet"
        ]
      },
      "source": {  //定义Stage模型中免费版target的pages源码文件
        "pages": [
          "pages/index",
          "pages/page1"
        ]
      }
    },
    {
      "name": "pay",
      "config": {
        "deviceType": [
          "tablet"
        ]
      },
      "source": {  //定义Stage模型中付费版target的pages源码文件
        "pages": [
          "pages/index",
          "pages/page2"
        ]
      }
    }
  ]
}
  • 例如,FA模型中的工程,在模块的MainAbility中定义了index.ets、page1.ets和page2.ets,其中:default使用了index.ets页面;free使用了index.ets和page1.ets页面;pay使用了index.ets和page2.ets页面。

{
  "apiType": 'faMode',
  "buildOption": {
  },
  "targets": [
    {
      "name": "default",
      "source": {  //定义FA模型中默认版target的pages源码文件
        "abilities": [
          {
            "name": ".MainAbility",
            "pages": [
              "pages/index"
            ]
          }
        ],
      }
    },
    {
      "name": "free",
      "config": {
        "deviceType": [
          "tablet"
        ]
      },
      "source": {  //定义FA模型中免费版target的pages源码文件
        "abilities": [
          {
            "name": ".MainAbility",
            "pages": [
              "pages/index",
              "pages/page1"
            ]
          }
        ],
      }
    },
    {
      "name": "pay",
      "config": {
        "deviceType": [
          "tablet"
        ]
      },
      "source": {  //定义FA模型中付费版target的pages源码文件
        "abilities": [
          {
            "name": ".MainAbility",
            "pages": [
              "pages/index",
              "pages/page2"
            ]
          }
        ],
      }
    }
  ]
}

定义产物的资源

每个target使用的资源文件可能存在差异,在开发过程中,开发者可以将每个target所使用的资源存放在不同的资源目录下。其中,ArkTS工程支持对main目录下的资源文件目录(resource)进行定制;JS工程支持对main目录下的资源文件目录(resource)及Ability下的资源文件目录(res)进行定制。如下为ArkTS工程的资源文件目录定制示例:

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

请注意,如果target引用的多个资源文件目录下,存在同名的资源,则在构建打包过程中,将按照配置的资源文件目录顺序进行选择。例如,上述付费版target引用的资源中,resource_default和resource_pay中存在同名的资源文件,则resource_default中的资源会被打包到HAP中。

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

在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": [
        "armeabi-v7a",
        "arm64-v8a"
      ],
      "cppFlags": "",
    }
  },
  "targets": [  //定义不用的target
    {
      "name": "default",  
      "config": {
        "buildOption": {
          "napiLibFilterOption": {
            //按照.so文件的优先级顺序,打包最高优先级的function1.so文件
            "pickFirsts": [
              "**/function1.so"
            ],
            //排除不打包的function3.so文件
            "excludes": [
              "**/function3.so"
            ],
            //允许当.so中资源重名冲突时,使用高优先级的.so文件覆盖低优先级的.so文件
            "enableOverride": true
          }
        }
      }
    },
    {
      "name": "vip",  
      "config": {
        "buildOption": {
          "napiLibFilterOption": {
            //按照.so文件的优先级顺序,打包最高优先级的function1.so文件
            "pickFirsts": [
              "**/function1.so"
            ],
            //排除不打包的function2.so文件
            "excludes": [
              "**/function2.so"
            ],
            //允许当.so中资源重名冲突时,使用高优先级的.so文件覆盖低优先级的.so文件
            "enableOverride": true
          }
        }
      }
    }
  ]
}

定义产物的distroFilter

distroFilter可配置的分发策略维度包括API Version、屏幕形状、屏幕分辨率、屏幕像素密度、国家地区码。在进行应用分发时,通过deviceType与这几个属性的匹配关系,唯一确定一个用于分发到设备的HAP。

不同应用模型的distroFilter配置方式并不相同:

配置APP多目标构建产物

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

定义目标产物product

每一个product对应一个定制的APP包,因此,在定制APP多目标构建产物前,应提前规划好需要定制的product名称。例如,定义productA和productB。

说明

在定制product时,必须存在“default”的product,否则编译时会出现错误。

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

说明

在定制product时,必须存在“default”的product,否则编译时会出现错误。

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

定义product的bundleName信息

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

"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的签名配置信息

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

通常情况下,您首先需要在签名配置界面或工程的build-profile.json5文件中配置签名信息。例如在File > Project Structure > Project > Signing Configs界面,分别配置default、product_A和product_B的签名信息,如下图所示:

OpenHarmony DevEco Studio使用指南-定制多目标构建产物-鸿蒙开发者社区

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

说明

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

"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

开发者可以选择需要将定义的target分别打包到哪一个product中,每个product可以指定一个或多个target,同时每个target也可以打包到不同的product中。例如,前面定义了default、free和pay三个target,现需要将default target打包到default product中;将default和free target打包到productA中;将default和pay target打包到productB中,对应的示例代码如下所示:

{
  "app": {
    "signingConfigs": [
      {
        "name": "productB",
        "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": "product_A",
        "bundleName": "com.example01.com",
        "signingConfig": "productA"
      },
      {
        "name": "product_B",
        "bundleName": "com.example02.com",
        "signingConfig": "productB"
      }
    ]
  },
  "modules": [
    {
      "name": "entry",
      "srcPath": "./entry",
      "targets": [
        {
          "name": "default",  //将default target分别打包到default、productA和productB APP中
          "applyToProducts": [
            "default",
            "productA",
            "productB"
          ]
        },
        {
          "name": "free",  //将free target打包到productA APP中
          "applyToProducts": [
            "productA"
          ]
        },
        {
          "name": "pay",  //将pay target打包到productB APP中
          "applyToProducts": [
            "productB"
          ]
        }
      ]
    }
  ]
}

构建定义的目标产物

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

单击右上角的

OpenHarmony DevEco Studio使用指南-定制多目标构建产物-鸿蒙开发者社区

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

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

OpenHarmony DevEco Studio使用指南-定制多目标构建产物-鸿蒙开发者社区

然后执行编译构建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。

OpenHarmony DevEco Studio使用指南-定制多目标构建产物-鸿蒙开发者社区

调试和运行指定的Target

使用DevEco Studio调试或运行应用/服务时,每个模块只能选择其中的一个target运行,可以通过单击右上角的

OpenHarmony DevEco Studio使用指南-定制多目标构建产物-鸿蒙开发者社区

图标,指定需要调试或运行的Product下对应的Module Target,然后单击Apply保存。

说明

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

OpenHarmony DevEco Studio使用指南-定制多目标构建产物-鸿蒙开发者社区



文章转载自:​​https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/ohos-customized-multi-targets-and-products-0000001384472236-V3​

分类
已于2023-4-4 14:06:57修改
收藏
回复
举报
回复
    相关推荐