Autolinking
Autolinking简单的说就是通过在RN前端工程中执行:
npm install <library-with-native-dependencies> --save
之后会在自动发现native端的代码或模块,然后安装依赖并编译。关于Autolinking的更多介绍可以查阅下面的文档:
在RNOH项目中,为了实现 Autolinking 功能,需要依赖RNOH框架、RN三方库以及RNOH项目一起配合。下文会分3种角色来讲述各自所负责的内容或需适配的工作,您可根据自己的角色来选择阅读对应的章节。
另外,您也可以通过运行 AutolinkingSample 来体验整个过程。
RNOH框架(框架维护者)
在这个功能上,RNOH框架主要是向开发者提供一个 @rnoh/hvigor-plugin 的 hvigor 插件(它位于RNOH前端工程 node_modules/@react-native-oh/react-native-harmony-cli/harmony 目录下),这个插件会通过调用 @react-native-oh/react-native-harmony-cli 中的 link-harmony 命令完成 har 包的安装、so的链接以及Package注册等手动链接所需执行的操作。
link-harmony 命令的参数
link-harmony 命令可单独执行,以下是 link-harmony 命令的参数:
-
--harmony-project-path <path>: 指定
harmony工程的相对路径,默认为./harmony; -
--node-modules-path <path>: 指定
node_modules的相对路径,默认为./node_modules; -
--cmake-autolink-path-relative-to-harmony <path>: 指定
autolinking.cmake生成的位置,autolinking.cmake会生成在harmony工程中,默认为./entry/src/main/cpp/autolinking.cmake; -
--cpp-rnoh-packages-factory-path-relative-to-harmony <path>: 指定
RNOHPackagesFactory.h生成的位置,RNOHPackagesFactory.h会生成在harmony工程中,默认为./entry/src/main/cpp/RNOHPackagesFactory.h; -
--ets-rnoh-packages-factory-path-relative-to-harmony <path>: 指定
RNOHPackagesFactory.ets生成的位置,RNOHPackagesFactory.ets会生成在harmony工程中,默认为./entry/src/main/ets/RNOHPackagesFactory.ets; -
--oh-package-path-relative-to-harmony <path>: 指定
oh-package.json5的位置,link-harmony命令会修改该文件以安装三方库的har包,默认为./oh-package.json5; -
--exclude-npm-packages [string...]: 指定不执行
Autolinking的三方库列表。默认情况下link-harmony命令会尝试链接所有的三方库,但某些情况下可能会因三方库配置错误而导致链接后编译报错,此时可通过这个参数将该包排除。这个参数不可以和--included-npm-packages一起使用; -
--include-npm-packages [string...]: 指定需要执行
Autolinking的三方库列表。默认情况下link-harmony命令会尝试链接所有的三方库。这个参数不可以和--excluded-npm-packages一起使用。
RN三方库(库开发者)
对于RN三方库的开发者,如果期望 link-harmony 命令能自动链接自己的三方库,会涉及到少量适配工作的。以下是主要的改动点,也可以参照 AutolinkingSample 中的 third-party-library-sample。
package.json 的改动
库开发者需要在 package.json 中配置 harmony.autolinking。harmony.autolinking 通常需要传入一个对象,属性说明如下:
-
etsPackageClassName:ets包的类名,如果不指定该字段,会默认根据
package.json中的name字段生成,生成规则为:[组织名]+[包名]+Package,如:third-party-library-sample会转换成ThirdPartyLibrarySamplePackage; -
cppPackageClassName:cpp包的类名,如果不指定该字段,会默认根据
package.json中的name字段生成,生成规则同etsPackageClassName; -
cmakeLibraryTargetName:动态链接库的名字,如果不指定该字段,会默认根据
package.json中的name字段生成,生成规则为:rnoh__+[组织名]+[包名],如:third-party-library-sample会转换成rnoh__third_party_library_sample; -
ohPackageName:ohos 模块的名字,推荐使用 har 包中
oh-package.json5的name字段,部分场景中DevEco会严格校验这个名称。如果不指定该字段,会默认根据package.json中的name字段生成,生成规则为:@rnoh/+[组织名]+--+[包名],如:third-party-library-sample会转换成@rnoh/third-party-library-sample;{ "harmony": { "autolinking": { "ohPackageName": "@rnoh/third-party-library-sample" } } }支持多 HAR 包配置(数组格式):当三方库包含多个 HAR 文件时,可以使用数组格式为每个 HAR 指定不同的 ohPackage 名称:
{ "harmony": { "autolinking": { "ohPackageName": [ { "harName": "main.har", "packageName": "@scope/my-library" }, { "harName": "sdk.har", "packageName": "@scope/my-library-sdk" } ] } } }harName:HAR 文件名(仅文件名,不含路径)packageName:对应的 ohPackage 名称- 配置顺序:数组中的第一个 HAR 被视为主 HAR,用于生成 CMake
add_subdirectory和 import 语句 - 未匹配的 HAR 使用默认命名规则:
@rnoh/{npm-pkg-name}--{har-name}
远程依赖支持:数组格式支持通过
version字段配置远程依赖,从 OHPM 仓库获取 HAR 包:{ "harmony": { "autolinking": { "ohPackageName": [ { "harName": "local.har", "packageName": "@scope/local-lib" }, { "harName": "remote.har", "packageName": "@ohos/remote-lib", "version": "1.0.0" } ] } } }version:可选字段,指定版本号- 有
version时:生成版本号依赖(如"@ohos/remote-lib": "1.0.0"),ohpm install会从远程仓库下载 - 无
version时:生成file:路径依赖(如"@scope/local-lib": "file:../node_modules/..."),从本地 node_modules 获取
- 有
-
mainHarPath:自定义 HAR 扫描路径,默认为
harmony。如果 HAR 文件不在默认的harmony目录下,可以通过此字段指定:{ "harmony": { "autolinking": { "mainHarPath": "custom/path/to/hars" } } }- 支持递归扫描指定目录及其子目录下的所有
.har文件
- 支持递归扫描指定目录及其子目录下的所有
如果您的代码中以上名称都符合默认规则且只有单个 HAR 文件,可将 harmony.autolinking 设置成 true。
har 包的要求
-
ohos 模块需要有一个默认的导出
如 AutolinkingSample 中的
third-party-library-sample/harmony/library一样,需要在index.ets文件中有一个默认的导出,如:export { ThirdPartyLibrarySamplePackage as default } from './src/main/ets/ThirdPartyLibrarySamplePackage'; -
har 包位置要求
- 默认情况下,har 包需要放在
[三方库]/harmony目录下 - 如果配置了
mainHarPath,则放在指定的目录下 - autolinking 会递归扫描目录及其子目录下的所有
.har文件
- 默认情况下,har 包需要放在
注册自定义TurboModule和ArkTS组件
在之前的版本中,自定义ArkTS组件需要开发者在创建 RNInstance 时通过 wrappedCustomRNComponentBuilder 参数传入,这并不符合 Autolinking 的设计,为此 RNOH 框架新增了RNOHPackage类,库的开发者可通过继承RNOHPackage类来设计自己的ets Package类:
-
通过重写
getUITurboModuleFactoryByNameMap方法注册模块中的自定义TurboModule; -
通过重写
getAnyThreadTurboModuleFactoryByNameMap方法来注册模块中的自定义WorkerTurboModule; -
通过重写
createWrappedCustomRNComponentBuilderByComponentNameMap方法来注册模块中的自定义ArkTS组件。
RNOH项目(使用RNOH框架和RN三方库的开发者)
除了RN三方库需要适配之外,RNOH项目也是需要改动的,开发者可以参照着 AutolinkingSample/NativeProject 来阅读下面的指导。
-
安装
@rnoh/hvigor-plugin插件(插件的位置见上文):// NativeProject/hvigor/hvigor-config.json5 { "modelVersion": "5.0.0", "dependencies": { + "@rnoh/hvigor-plugin": "file:../../ReactProject/node_modules/@react-native-oh/react-native-harmony-cli/harmony/rnoh-hvigor-plugin-0.xx.xx.tgz" }, -
添加插件: 这一步主要涉及修改
hvigorfile.ts文件(具体是哪个模块中的hvigorfile.ts根据自己项目情况而定),在这个文件中首先是需要从@rnoh/hvigor-plugin中导入createRNOHModulePlugin函数,然后通过createRNOHModulePlugin函数来创建一个plugin实例,如:// NativeProject/entry/hvigorfile.ts import { hapTasks } from '@ohos/hvigor-ohos-plugin'; import { createRNOHModulePlugin } from "@rnoh/hvigor-plugin" export default { system: hapTasks, plugins: [ createRNOHModulePlugin({ nodeModulesPath: "../ReactProject/node_modules", // node_modules 文件夹相对于 harmony 工程的路径,默认为../node_modules codegen: null, // 不涉及 codegen,则配置成null autolinking: {} }), ] }createRNOHModulePlugin的详细配置文档在hvigorfile 配置,这里先主要讲解一下 autolinking 的参数配置。在这个Sample中,给 autolinking 传入的是一个空对象,但实际的项目中可能会涉及额外的配置,autolinking 对象的属性与
link-harmony命令的参数是有关联的,详细的说明如下:-
ohPackagePath:指定
oh-package.json5的位置,默认为./oh-package.json5; -
etsRNOHPackagesFactoryPath:指定
RNOHPackagesFactory.ets生成的位置,默认为./entry/src/main/ets/RNOHPackagesFactory.ets; -
cppRNOHPackagesFactoryPath:指定
RNOHPackagesFactory.h生成的位置,默认为./entry/src/main/cpp/RNOHPackagesFactory.h; -
cmakeAutolinkPath:指定
autolinking.cmake生成的位置,默认为./entry/src/main/cpp/autolinking.cmake; -
excludeNpmPackages:指定不执行
Autolinking的三方库列表; -
includeNpmPackages: 指定需要执行
Autolinking的三方库列表。
添加完成后,会由hvigor插件配合@react-native-oh/react-native-harmony-cli自动完成以下文件的添加和内容修改:
- 新增RNOHPackagesFactory.ets、RNOHPackagesFactory.h和autolinking.cmake文件,用来完成so的链接和Package的注册。
- 在指定的oh-package.json5中添加依赖,完成har包的安装。
-
-
添加AutoLinking配置:
CMakeLists.txt文件中增加autolink配置:# OH_MODULES_DIR根据实际路径修改 set(OH_MODULES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../oh_modules") include("${CMAKE_CURRENT_SOURCE_DIR}/autolinking.cmake") autolink_libraries(rnoh_app)PackageProvider.cpp文件中增加autolink配置:
-
导入RNOHPackagesFactory.h中的package对象;
-
合并手动link的package。
#include "RNOH/PackageProvider.h" #include "RNOHPackagesFactory.h" // ... 如果之前有手动链接的库,在这里引入 using namespace rnoh; std::vector<std::shared_ptr<Package>> PackageProvider::getPackages( Package::Context ctx) { const std::vector<std::shared_ptr<Package>> ManualLinkingPackage = { // ... 如果之前有手动link的package,放在这里 }; auto packages = createRNOHPackages(ctx); // autolinking for (const auto& pkg : ManualLinkingPackage) { packages.push_back(pkg); // 逐一添加手动link的package } return packages; }RNPackagesFactory.ets文件中增加autolink配置:
-
导入RNOHPackagesFactory.ets中的package对象;
-
合并手动link的package。
import type { RNPackageContext, RNOHPackage } from '@rnoh/react-native-openharmony'; import { createRNOHPackages as createRNOHPackagesAutolinking } from "./RNOHPackagesFactory" export function getRNOHPackages(ctx: RNPackageContext): RNOHPackage[] { return [ ...createRNOHPackagesAutolinking(ctx), // 添加手动link的package // ... ]; } -