本文以OpenHarmony-3.2-Beta4上适配modbus编译动态库为例。
获取三方库
使用之前要做好代码溯源,确认可用的版本,开源许可和发布方式等。
通过正确的路径获取源码,可以是官网,或者指定托管的github或者gitee仓。
官网:https://libmodbus.org/
github:https://github.com/stephane/libmodbus
移植三方库
三方库移植主要需要以下四步。
linux编译
编译三方库:
1、如果原三方库根目录存在CMakeLists.txt文件,新建build目录,通过cmake生成makeflie然后make。
2、如果根目录存在autogen.sh或configure.ac文件,使用Makefile.am构建,先执行./autogen.sh,再执行./configure命令生成Makefile,最后make和make install。
分析编译过程:
提取编译动态链接库和测试用的可执行文件所需要的源文件和头文件、编译添加的cflag和其他编译器参数,以及编译需要的链接库。
根据三方库的编译有两种情况:
1、在cmake生成makefile的过程中,分析build.make(生成目标的源文件)、depend.make(需要依赖的其他C源文件)、flags.make(cflags相关标记)、link.txt(链接库相关信息)等得出三方库对应的依赖关系。
2、使用Makefile.am构建的三方库,分析make.am内容,分析编译动态链接库和测试用的可执行文件需要的源文件,添加的编译器参数。链接库则通过分析makefile文件提取。
OpenHarmony适配
三方库一般放置在third_party目录下。
编译之前要增加模块配置,可以参考以下链接:
https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-build-module.md#新增并编译模块
部件名:modbus_part_name = “libmodbus”
子系统名:modbus_subsystem_name = “modbus”
新增子系统和部件名的方式:
1、在模块目录下配置BUILD.gn,根据模板类型选择对应的gn模板
third_party/libmodbus/BUILD.gn
2、在新建的子系统目录下每个部件对应的文件夹下创建bundle.json文件,定义部件信息。
third_party/libmodbus/bundle.json
3、修改build目录下的subsystem_config.json文件。
build\subsystem_config.json
4、在vendor/{product_company}/{product-name}目录下的产品配置如product-name是hispark_taurus_standard时,在config.json中添加对应的部件,直接添加到原有部件后即可。
productdefine\common\inherit\rich.json
这几步适配都需要根据三方库的引用方式来确定,并不需要每步都配置。如果当前模块是需要添加到已经有的部件或子系统,就只需要配置1和2步即可。
增量编译
编译动态链接库和可执行文件:
./build.sh --product-name rk3568 --ccache --build-target三方库名称 --target-cpu arm64
注:ohos到3.2版本之后,默认编译的都是32位系统,若要支持64位系统,在编译命令中添加–target-cpu arm64
例如:./build.sh --product-name rk3568 --ccache -T libmodbus
编译过程可能出现报错,根据报错信息调整gn。消除编译警告,例如:-Wimplicit-function-declaration改为-Wno-implicit-function-declaration加到gn的cflags信息里面。
编译成功生成的动态链接库和测试用的可执行文件在out目录下。
例如:out/ rk3568/modbus/libmodbus/libmodbus.z.so
验证接口
将编译好的动态库和测试用例的可执行文件推送到开发板上。然后验证是否成功,保证测试用例都能在开发板上运行通过。
API接口是提供给北向调用的,实现指定的功能,使用者不需要了解其内部具体实现。
按照业务需要提供native和js接口。
引用方式
静态库
在部件中需要使用的gn中配置deps项,然后在代码中直接引用接口。
“//third_party/libmodbus:modbus”,
例如:
动态库
先编译动态库,然后放在板子指定路径,然后通过dlopen导入动态库,最后在代码中通过句柄调引用接口。例如:
if(handle == nullptr){
MMI_HILOGE("Open failed, so name:%{public}s, msg:%{public}s", pluginPath.data(), dlerror());
return false;
}