OpenHarmony napi 编译 .so 并打包成 .har

2024-06-09 14:44

本文主要是介绍OpenHarmony napi 编译 .so 并打包成 .har,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、前言

最近在搞公司标准产品适配OpenHarmony 平台, 按照行业上的常用方法,在Android 是将底层代码用c++ 封装成 xxx.so  ,然后将其他一部分打包成 xxx.jar。 因此,在OpenHarmony 平台也是打算按照这个模式。正所谓,好记忆,不如烂笔头,写下这篇文章,以后也可以翻阅查看。

二、相关概念

1. Android 平台

1.1 xxxx.so

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。编译之后程序文件大,但加载快,隔离性也好。 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。多个应用程序可以使用同一个动态库,启动多个应用程序的时候,只需要将动态库加载到内存一次即可。一般Linux 编译为xx.so   Windows 编译为  xxx.dll.

编译动态库:

在Linux Android  

-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件 -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。 -L.:表示要连接的库在当前目录中 -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称。

1.2 xxx.jar  

在Java开发中,JAR(Java Archive)是一种常见的文件格式,用于不同的场景。
JAR包是Java的类进行编译生成的class文件打包的压缩包,通常用于存放类库和依赖。在开发过程中,我们经常需要引用一些通用的类,将这些类打包成JAR包便于管理和使用。例如,当我们使用某些功能时,就需要导入支持这些功能的JAR包。

2. OpenHarmony 平台

2.1 xxx.so

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。编译之后程序文件大,但加载快,隔离性也好。 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。多个应用程序可以使用同一个动态库,启动多个应用程序的时候,只需要将动态库加载到内存一次即可。

2.2 xxxx.har

在OpenHarmony 中,这个是新平台,因此也有跟Android 相类似的技术。

在 华为开发者文档有提到相关概念

应用程序包概述-应用程序包基础知识-开发基础知识-入门 | 华为开发者联盟 (huawei.com)

2.2.1 应用程序包概述

用户应用程序泛指运行在设备的操作系统之上,为用户提供特定服务的程序,简称“应用”。一个应用所对应的软件包文件,称为“应用程序包”。

HarmonyOS提供了应用程序包开发、安装、查询、更新、卸载的管理机制,方便开发者开发和管理HarmonyOS应用,具体如下:

  • 应用软件所涉及的文件多种多样,开发者可通过HarmonyOS提供的集成开发工具将其开发的可执行代码、资源、三方库等文件整合到一起制作成HarmonyOS应用程序包,便于开发者对应用程序的部署。

  • 应用软件所涉及的设备类型多种多样,开发者可通过HarmonyOS提供的应用程序包配置文件指定其应用程序包的分发设备类型,便于应用市场对应用程序包的分发管理。

  • 应用软件所包含的功能多种多样,将不同的功能特性按模块来划分和管理是一种良好的设计方式。HarmonyOS提供了同一应用程序的多包管理的机制,开发者可以将不同的功能特性聚合到不同的包中,方便后续的维护与扩展。

  • 应用软件涉及的芯片平台多种多样,有x86、ARM等,还有32位、64位之分,HarmonyOS为应用程序包屏蔽了芯片平台的差异,使应用程序包在不同的芯片平台都能够安装运行。

  • 应用软件涉及的软件信息多种多样,有应用版本、应用名称、组件、申请权限等的信息,HarmonyOS包管理为开发者提供了这些信息的查询接口,方便开发者在程序中查询所需要的包信息。

  • 应用软件涉及的资源多种多样,有媒体资源、原生资源、字符资源以及国际化的资源等,HarmonyOS包管理将不同的资源归档到不同的目录中,并集成资源索引文件,方便应用对资源的查找和使用。

2.2.2 应用程序包结构

在OpenHarmony 中应用程序包分为两种结构:

  • Stage模型应用程序包结构
  • FA模型应用程序包结构

2.3.1 基于Stage模型的应用结构

基于Stage模型开发的应用,经编译打包后,其应用程序包结构如下图应用程序包结构(Stage模型)所示:

在开发态,一个应用包含一个或者多个Module,可以在DevEco Studio工程中创建一个或者多个Module。Module是HarmonyOS应用/服务的基本功能单元,包含了源代码、资源文件、第三方库及应用/服务配置文件,每一个Module都可以独立进行编译和运行。

Module分为“Ability”和“Library”两种类型,“Ability”类型的Module对应于编译后的HAP(Harmony Ability Package)

“Library”类型的Module对应于HAR(Harmony Archive),或者HSP(Harmony Shared Package)。

其中,

开发者通过DevEco Studio把应用程序编译为一个或者多个.hap后缀的文件,即HAPHAP是HarmonyOS应用安装的基本单位,包含了编译后的代码、资源、三方库及配置文件。

打包后的HAP包结构包括ets、libs、resources等文件夹和resources.index、module.json、pack.info等文件。

  • ets目录用于存放应用代码编译后的字节码文件。
  • libs目录用于存放库文件。库文件是HarmonyOS应用依赖的第三方代码(.so二进制文件)
  • resources目录用于存放应用的资源文件(字符串、图片等),便于开发者使用和维护,详见资源分类与访问。
  • resources.index是资源索引表,由IDE编译工程时生成。
  • module.json是HAP的配置文件,内容由工程配置中的module.json5和app.json5组成,该文件是HAP中必不可少的文件。IDE会自动生成一部分默认配置,开发者按需修改其中的配置。详细字段请参见应用配置文件。
  • pack.info是Bundle中用于描述每个HAP属性的文件,例如app中的bundleName和versionCode信息、module中的name、type和abilities等信息,由IDE工具生成Bundle包时自动生成。

 应用程序包结构(Stage模型)

2.2.3 共享包概述

HarmonyOS提供了两种共享包,HAR(Harmony Archive)静态共享包,和HSP(Harmony Shared Package)动态共享包。

HAR与HSP都是为了实现代码和资源的共享,都可以包含代码、C++库、资源和配置文件.

 HAR和HSP在APP包中的形态示意图

2.2.3.1 HAR

HAR中的代码和资源跟随使用方编译,如果有多个使用方,它们的编译产物中会存在多份相同拷贝.

2.2.3.2 HSP

HSP中的代码和资源可以独立编译,运行时在一个进程中代码也只会存在一份。

HAR不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。

三、HAR模式创建工程

HAR-共享包-应用程序包基础知识-开发基础知识-入门 | 华为开发者联盟 (huawei.com)

2.1 创建HAR工程

通过DevEco Studio创建一个HAR模块,详见创建库模块。HAR模块默认不开启混淆能力,开启混淆能力,需要把HAR模块的build-profile.json5文件中的artifactType字段设置为obfuscation,配置如下所示:

{"apiType": "stageMode","buildOption": {"artifactType": "obfuscation"}
}

artifactType字段有以下两种取值,默认缺省为original。

  • original:不混淆。
  • obfuscation:混淆。

需要对代码资产进行保护时,建议开启混淆能力,混淆能力开启后,DevEco Studio在构建HAR时,会对代码进行编译、混淆及压缩处理,保护代码资产。

注意:artifactType字段设置为obfuscation时,apiType字段必须设置为stageMode,因为Stage模型才支持混淆。

2.2 HAR开发注意事项

  • HAR不支持在配置文件中声明abilities、extensionAbilities组件。
  • HAR不支持在配置文件中声明pages页面。
  • HAR不支持在build-profile.json5文件的buildOption中配置worker。
  • FA模型与Stage模型的HAR不支持相互引用。
  • Stage模型的HAR,不能引用AppScope内的内容。在编译构建时AppScope中的内容不会打包到HAR中,导致HAR资源引用失败。

2.3 导出HAR的ArkUI组件、接口、资源

2.3.1 Index.ets接口文件

Index.ets文件是HAR导出声明文件的入口,HAR需要导出的接口,统一在Index.ets文件中导出。Index.ets文件是DevEco Studio默认自动生成的,用户也可以自定义,在模块的oh-package.json5文件中的main字段配置入口声明文件,配置如下所示:

{"main": "Index.ets"
}

2.3.2 导出ArkUI组件

ArkUI组件的导出方式与ts的导出方式一致,通过export导出ArkUI组件,示例如下:

// library/src/main/ets/components/MainPage/MainPage.ets
@Component
export struct MainPage {@State message: string = 'Hello World'build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}
}

HAR对外暴露的接口,在Index.ets导出文件中声明如下所示:

// library/Index.ets
export { MainPage } from './src/main/ets/components/MainPage/MainPage'

2.3.3 导出ts类和方法

// library/src/main/ts/test.ets
export class Log {static info(msg: string) {console.info(msg);}
}export function func() {return "har func";
}export function func2() {return "har func2";
}

HAR对外暴露的接口,在Index.ets导出文件中声明如下所示:

// library/Index.ets
export { Log } from './src/main/ts/test'
export { func } from './src/main/ts/test'
export { func2 } from './src/main/ts/test'

2.3.4 导出native方法

在HAR中也可以包含C++编写的so。对于so中的native方法,HAR通过以下方式导出,以导出libnative.so的加法接口add为例:

// library/src/main/ets/utils/nativeTest.ts
import native from "libnative.so"export function nativeAdd(a: number, b: number) {let result: number = native.add(a, b);return result;
}

HAR对外暴露的接口,在Index.ets导出文件中声明如下所示:

// library/Index.ets
export { nativeAdd } from './src/main/ets/utils/nativeTest'

2.3.5 资源

HAR模块编译打包时会把资源打包到HAR中。在编译构建HAP时,DevEco Studio会从HAP模块及依赖的模块中收集资源文件,如果不同模块下的资源文件出现重名冲突时,DevEco Studio会按照以下优先级进行覆盖(优先级由高到低):

  • AppScope(仅API9的Stage模型支持)。
  • HAP包自身模块。
  • 依赖的HAR模块,如果依赖的多个HAR之间有资源冲突,会按照依赖顺序进行覆盖(依赖顺序在前的优先级较高)。

2.3.6 HAR工程编译

开发及引用静态共享包(API 9)-开发及引用共享包-应用/服务开发-DevEco Studio使用指南-工具 | 华为开发者联盟 (huawei.com)

2.3.6.1 创建库模块
  1. 鼠标移到工程目录顶部,单击右键,选择New > Module,在工程中添加模块。
  2. Choose Your Ability Template界面中,选择Static Library,并单击Nex

3. 在Configure New Module界面中,设置新添加的模块信息,设置完成后,单击Finish完成创建。

  • Module name:新增模块的名称。
  • Language:开发语言。
  • Device type:支持的设备类型。
  • Enable native:是否创建一个用于调用C++代码的模块

创建完成后,会在工程目录中生成库模块及相关文件。

库模块的工程结构,如下图所示:

相关字段的描述如下,其余字段与Entry或Feature模块相关字段相同,可参考工程介绍。

  • libs:用于存放.so文件。
  • src > main > cpp > types:用于存放C++ API描述文件,子目录按照so维度进行划分。
  • src > main > cpp > types > liblibrary > index.d.ts:描述C++接口的方法名、入参、返回参数等信息。
  • src > main > cpp > types > liblibrary > oh-package.json5:描述so三方包声明文件入口和so包名信息。
  • src > main > cpp > CMakeLists.txt:CMake配置文件,提供CMake构建脚本。
  • src > main > cpp > hello.cpp:共享包C++代码源文件。
  • index.ets:共享包导出声明的入口。
2.3.6.2 编译库模块

开发完库模块后,选中模块名,然后通过DevEco Studio菜单栏的Build > Make Module ${libraryName}进行编译构建,生成HAR。HAR可用于工程其它模块的引用,或将HAR上传至ohpm仓库,供其他开发者下载使用。若部分源码文件不需要打包至HAR中,可通过创建.ohpmignore文件,配置打包时要忽略的文件/文件夹。

编译构建的HAR可在模块下的build目录下获取,包格式为*.har。

在编译构建HAR时,请注意以下事项:

  • 在编译构建HAR的过程中,不会将模块中的C++代码直接打包进.har文件中,而是将C++代码编译成动态依赖库.so文件放置在.har文件中的libs目录下。
  • 在编译构建HAR的过程中,会生成资源文件ResourceTable.txt,以便编辑器可以对HAR中的资源文件进行联想。因此,如果不使用DevEco Studio对HAR进行构建,则DevEco Studio的编辑器会无法联想HAR中的资源。
2.3.6.3 发布HAR

文档中心

1. 在库模块中(与src文件夹同一级目录下),添加如下文件:

    • 新建README.md文件:在README.md文件中必须包含包的介绍和引用方式,还可以根据包的内容添加更详细介绍。
    • 新建CHANGELOG.md文件:填写HAR的版本更新记录。
    • 添加LICENSE文件:LICENSE许可文件。

  1. 重新编译库模块,生成*.har文件。
  2. 利用工具ssh-keygen生成公、私钥,可执行以下命令.

四、引用HAR的ArkUI组件、接口、资源

文档中心

引用HAR前,需要先配置对HAR的依赖,配置方式可参考引用HAR文件和资源。

4.1 配置app 工程 HAR 依赖

引用三方HAR,包括从仓库进行安装、从本地文件夹和本地压缩包中进行安装三种方式。

4.1.1 引用ohpm仓中的HAR,首先需要设置三方HAR的仓库信息。DevEco Studio默认仓库地址为OpenHarmony三方库中心仓,如果您需要设置自定义仓库,请在DevEco Studio的Terminal窗口执行如下命令(执行命令前,请确保将DevEco Studio中ohpm安装bin目录配置在“环境变量-系统变量-PATH”中,第一次配置环境变量后,需重启DevEco Studio):

ohpm config set registry your_registry1,your_registry2

说明:ohpm支持多个仓库地址,采用英文逗号分隔。

然后通过如下两种方式设置三方包依赖信息:

方式一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。

ohpm install @ohos/lottie

方式二:在工程的oh-package.json5中设置三方包依赖,配置示例如下:

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

依赖设置完成后,需要执行ohpm install命令安装依赖包,依赖包会存储在工程的oh_modules目录下。

ohpm install

4.2 引用本地HAR包

引用本地HAR包,有如下两种方式:

方式一:在Terminal窗口中,执行如下命令进行安装,并会在oh-package.json5中自动添加依赖。

ohpm install ./package.har

方式二:在工程的oh-package.json5中设置三方包依赖,配置示例如下:

"dependencies": {"package": "file:./package.har"
}

依赖设置完成后,需要执行ohpm install命令安装依赖包,依赖包会存储在工程的oh_modules目录下。

ohpm install

在引用共享包时,请注意以下事项:

当前只支持在模块和工程下的oh-package.json5文件中声明dependencies依赖,才会被当做依赖使用,并在编译构建过程中进行相应的处理。

4.3 引用HAR的ArkUI组件

HAR的依赖配置成功后,可以引用HAR的ArkUI组件。ArkUI组件的导入方式与ts的导入方式一致,通过import引入HAR导出的ArkUI组件,示例如下所示:

// entry/src/main/ets/pages/Index.ets
import { MainPage } from "library"@Entry
@Component
struct Index {@State message: string = 'Hello World'build() {Row() {// 引用HAR的ArkUI组件MainPage()Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}
}

4.4 引用HAR的ts类和方法

通过import引用HAR导出的ts类和方法,示例如下所示:

// entry/src/main/ets/pages/Index.ets
import { Log } from "library"
import { func } from "library"@Entry
@Component
struct Index {build() {Row() {Column() {Button('Button').onClick(()=>{// 引用HAR的类和方法Log.info("har msg");func();})}.width('100%')}.height('100%')}
}

4.5 引用HAR的native方法

通过import引用HAR导出的native方法,示例如下所示:

// entry/src/main/ets/pages/Index.ets
import { nativeAdd } from "library"@Entry
@Component
struct Index {@State message: string = 'Hello World'build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)Button('nativeAdd(1, 2)').onClick(()=> {this.message = "result: " + nativeAdd(1, 2);})}.width('100%')}.height('100%')}
}

4.6 引用HAR的资源

通过$r引用HAR中的资源,例如在HAR模块的src/main/resources里添加字符串资源(在string.json中定义,name:hello_har)和图片资源(icon_har.png),然后在Entry模块中引用该字符串和图片资源的示例如下所示:

// entry/src/main/ets/pages/Index.ets
@Entry
@Component
struct Index {build() {Row() {Column() {// 引用HAR的字符串资源Text($r("app.string.hello_har")).fontSize(50).fontWeight(FontWeight.Bold)// 引用HAR的图片资源Image($r("app.media.icon_har"))}.width('100%')}.height('100%')}
}

/**
 *         ┏┓   ┏┓+ +
 *        ┏┛┻━━━┛┻┓ + +
 *        ┃       ┃
 *        ┃   ━   ┃ ++ + + +
 *        ████━████ ┃+
 *        ┃       ┃ +
 *        ┃   ┻   ┃
 *        ┃       ┃ + +
 *        ┗━┓   ┏━┛
 *          ┃   ┃
 *          ┃   ┃ + + + +
 *          ┃   ┃    Code is far away from bug with the animal protecting
 *          ┃   ┃ +     神兽保佑,代码无bug
 *          ┃   ┃
 *          ┃   ┃  +
 *          ┃    ┗━━━┓ + +
 *          ┃        ┣┓
 *          ┃        ┏┛
 *          ┗┓┓┏━┳┓┏┛ + + + +
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛+ + + +
 *
 * @author chenxi
 * @date 2024年6月8日10:12:53
 */

参考:HAR-共享包-应用程序包基础知识-开发基础知识-入门 | 华为开发者联盟 (huawei.com)

这篇关于OpenHarmony napi 编译 .so 并打包成 .har的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1045477

相关文章

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

springboot3打包成war包,用tomcat8启动

1、在pom中,将打包类型改为war <packaging>war</packaging> 2、pom中排除SpringBoot内置的Tomcat容器并添加Tomcat依赖,用于编译和测试,         *依赖时一定设置 scope 为 provided (相当于 tomcat 依赖只在本地运行和测试的时候有效,         打包的时候会排除这个依赖)<scope>provided

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码

Golang test编译使用

创建文件my_test.go package testsimport "testing"func TestMy(t *testing.T) {t.Log("TestMy")} 通常用法: $ go test -v -run TestMy my_test.go=== RUN TestMyTestMy: my_test.go:6: TestMy--- PASS: TestMy (0.

C++/《C/C++程序编译流程》

程序的基本流程如图:   1.预处理        预处理相当于根据预处理指令组装新的C/C++程序。经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。 读取C/C++源程序,对其中的伪指令(以#开头的指令)进行处理将所有的“#define”删除,并且展开所有的宏定义处理所有的条件编译指令,如:“#if”、“

编译linux内核出现 arm-eabi-gcc: error: : No such file or directory

external/e2fsprogs/lib/ext2fs/tdb.c:673:29: warning: comparison between : In function 'max2165_set_params': -。。。。。。。。。。。。。。。。。。 。。。。。。。。。。。。。 。。。。。。。。 host asm: libdvm <= dalvik/vm/mterp/out/Inte

QT 编译报错:C3861: ‘tr‘ identifier not found

问题: QT 编译报错:C3861: ‘tr’ identifier not found 原因 使用tr的地方所在的类没有继承自 QObject 类 或者在不在某一类中, 解决方案 就直接用类名引用 :QObject::tr( )

hector_quadrotor编译总结 | ubuntu 16.04 ros-kinetic版本

hector_quadrotor编译总结 | ubuntu 16.04 ros-kinetic版本 基于Ubuntu 16.04 LTS系统所用ROS版本为 Kinetic hector_quadrotor ROS包主要用于四旋翼无人机的建模、控制和仿真。 1.安装依赖库 所需系统及依赖库 Ubuntu 16.04|ros-kinetic|Gazebo|gazebo_ros_pkgs|ge