啃论文俱乐部——移植speexdsp到OpenHarmony标准系统③ 原创 精华
- 大家好!我来自南京,在OpenHarmony成长计划啃论文俱乐部,与
华为、软通动力、润和软件、拓维信息、深开鸿
等公司一起,学习和研究操作系统技术
,
从今年1月11日加入OpenHarmony俱乐部已经有接近8个月时间了。笔者一直在思考啃论文给我带来了些什么,通过啃论文能为OpenHarmony做些什么。笔者利用大二升大三暑假两个月时间移植了Speexdsp这个三方库到OpenHarmony标准系统,而关于前面的问题我似乎找到了答案,现将啃论文和三方库移植分享经验如下:
由于想要分享的内容较多,为避免读者姥爷们失去看下去的耐心,分享将以连载的方式进行。
下期预告:在OpenHarmony的编译体系下编译speexdsp的so和测试用的可执行文件,以及编译报错的解决办法。
往期回顾:
啃论文俱乐部——移植speexdsp到OpenHarmony标准系统①
啃论文俱乐部——移植speexdsp到OpenHarmony标准系统②
本期为移植speexdsp到OpenHarmony标准系统
的第③期,主要内容如下:
目录
- 由于想要分享的内容较多,为避免读者姥爷们失去看下去的耐心,分享将以连载的方式进行。 下期预告:在OpenHarmony的编译体系下编译speexdsp的so和测试用的可执行文件,以及编译报错的解决办法。
- 四、将三方库加入到OpenHarmony的编译体系
- OpenHarmony三方库编译环境搭建
- 配置speexdsp源码
- speexdsp编译gn化,新增工程构建脚本。
- 测试用例gn化,新增工程构建脚本
- OpenHarmony/sources/third_party/speexdsp目录下添加ohos.build。
- 修改build/subsystem_config.json,新增子系统定义。
- 修改vendor/hihope/rk3568/config.json文件将speexdsp添加至rk3568开发板,在vendor目录下新增产品的定义。
- 下期分享内容:在OpenHarmony的编译体系下编译speexdsp的so和测试用的可执行文件,以及编译报错的解决办法
- 知识点附送
speexdsp移植后已提交至openhamrony sig仓库:https://gitee.com/openharmony-sig/contest/tree/master/2022_OpenHarmony_thirdparty/speexdsp
四、将三方库加入到OpenHarmony的编译体系
根据上一步分析结果,编写gn文件,将三方库加入到OpenHarmony的编译体系。
OpenHarmony编译构建子系统提供了一个基于Gn和ninja的编译构建框架。根据产品配置,编译生成对应的镜像包。其中编译构建流程为:
- 使用Gn配置构建目标。
- Gn运行后会生成ninja文件。
- 通过运行ninja来执行编译任务。
OpenHarmony三方库编译环境搭建
本次移植时在openharmony3.2Beta1版本上运行的,所以需要准备openharmony3.2Beta1的源码。
先在Widows上安装虚拟机,在虚拟机上安装Ubuntu18.04或者20.04。笔者使用的为Ubuntu20.04。
1.将Ubuntu Shell
环境修改为bash
- 打开终端执行
- 将Shell由dash改为bash。
- 选择
<否>
- 更改成功如下:
2.下载华为集成开发环境 DevEco Device Tool Linux版本,目前最新版本号为3.1.0.200
HUAWEI DevEco Device Tool(以下简称DevEco Device Tool)是OpenHarmony面向智能设备开发者提供的一站式集成开发环境,支持OpenHarmony的组件按需定制,支持代码编辑、编译、烧录和调试等功能,支持C/C++语言,以插件的形式部署在Visual Studio Code上。
- 直接在Ubuntu上打开firefox输入下载地址下载
- 解压DevEco Device Tool安装包,并对解压后的文件赋权
-
安装DevEco Device
-
执行命令安装DevEco Device
终端打印出这条信息说明安装成功
3.获取标准系统源码
执行命令sudo apt-get install git git-lfs
安装git客户端和git-lfs
- 配置git用户信息
git config --global credential.helper store
执行这个命令会在本地生成一个文本,上边记录配置。然后再拉取代码就不用再输入账号信息了。
- 进入gitee官网个人主页,个人头像下方就是user.name
-
再进入设置点击邮箱管理就可以得到你的your-email-address
-
安装gitee码云repo工具
- 使用repo+https下载发布Tag节点源码
创建源码存放目录
进入创建的源码存放目录,执行以下命令下载源码
如果要下载最新分支的代码则执行:
repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
3.在源码目录下执行脚本安装编译器及二进制工具
下载的prebuilts二进制默认存放在与OpenHarmony同目录下的OpenHarmony_2.0_canary_prebuilts下。
如果执行bash build/prebuilts_download.sh出现以下warning,在源码/prebuilts/python/linux-x86/3.9.2/bin/执行python -m pip install --user --upgrade pip==22.3.1(22.3.1是要升级的版本号)
4.安装依赖工具
如果安装了如上的依赖工具不行,执行以下语句安装最新的依赖工具
依赖工具列表 https://gitee.com/landwind/openharmony_oneclick_env_init/raw/master/apt_install.list
5.将python 3.8设置为默认python版本。
- 查看python 3.8的位置:
将python和python3切换为python3.8
6.最后测试一下OpenHarmony三方库编译环境
在源码根目录下执行编译命令
在源码目录下执行编译zlib命令,生成libzlib.z.so
编译生成了libzlib.z.so,编译环境没问题。
OpenHarmony环境重置
- 安装依赖包:
unix_time=`date '+%s'`;for one_tools in `curl -s -k https://gitee.com/landwind/openharmony_oneclick_env_init/raw/master/apt_install.list`;do echo "apt-get install -y ${one_tools}">>/tmp/openharmony_deps_${unix_time}.sh; done;sudo apt-get update;sudo bash -x /tmp/openharmony_deps_${unix_time}.sh
- 删除out:
rm -rf out
- 重置工作区,删除所有修改(记得备份你改的代码):
repo forall -c "pwd;git reset --hard; git clean -fd"
- 更新最新代码:
repo sync -c -j8; repo forall -c "pwd;git lfs install;git lfs pull"
- 执行prebuilts下载脚本:
bash build/prebuilts_download.sh
配置speexdsp源码
下载完openharmony3.2Beta1源码后,将speexdsp的源码拷贝到openhamony的third_party目录下。
在OpenHarmony/sources/third_party/speexdsp和OpenHarmony/sources/third_party/speexdsp/libspeexdsp下分别编写一份BUILD.gn文件,完成speexdsp的gn及测试用例的gn化。测试用例指的是测试speexdsp功能的程序。
speexdsp编译gn化,新增工程构建脚本。
OpenHarmony/sources/third_party/speexdsp下添加BUILD.gn脚本文件。
OpenHarmony/sources/third_party/speexdsp/BUILD.gn内容如下:
代码解析
第一行:
import函数将ohos.gni文件导入到当前作用域。导入的文件是独立执行的,生成的作用域被复制到当前文件中。一个.gni文件会定义构建参数和模板。build目录下ohos.gni文件内容如下
第三行到第九行:
- configs定义了该模块编译配置的环境变量speexdsp_nowarn_config,第24行ohos_shared_library定义了最终生成的模块名,这里代表此模块为最终生成libspeexdsp.z.so。所以在第五行到第七行中config中添加了编译libspeexdsp.z.so需要添加的编译器标志
- 但是"-Wno-implicit-function-declaration"、“-Wno-pointer-sign”"、-Wno-unused-variable"并非是分析speexdsp原生库得来的cflag编译器标志。
- 而是后来在ohos上编译验证过程中,根据编译报错信息添加的。如果不添加它们,执行./build.sh --product-name rk3568 --ccache --build-target=speexdsp命令后,则无法编译生成openharmony上的运行的libspeexdsp.z.so库,会出现编译警告信息-W-implicit-function-declaration、-W-pointer-sign、-W-unused-variable。解决办法就是在gn化时添加cflag标志"-Wno-implicit-function-declaration"、“-Wno-pointer-sign”“、-Wno-unused-variable”。
- clang编译器警告消除:
1.出现警告的就是直接在-W后面加no,比如-Wimplicit-function-declaration改为 -Wno-implicit-function-declaration
2.还有另外的一种方法:-Wimplicit-function-declaration=no
- clang编译器警告消除:
第十一到第二十二行:
- configs定义了该模块编译配置的环境变量speexdsp_cflag_config,在第十三行到第十六行添加了编译需要添加的编译器标志 “-g”,“-O2”,“-fvisibility=hidden”, “-DHAVE_CONFIG_H”。
- “-g”,“-O2”,"-fvisibility=hidden"通过分析原生库config.log和makefile文件,具体请查看第二期内容。
- "-DHAVE_CONFIG_H"通过分析执行build命令后编译ohos上speexdsp的so库报错信息得来
- 添加"-DHAVE_CONFIG_H"后仍然有报错信息,解决办法是把linux下编译speexdsp原生库./configure后生成的config.h放置在thrid_party/speexdsp下。
- 添加"-DHAVE_CONFIG_H"后仍然有报错信息,解决办法是把linux下编译speexdsp原生库./configure后生成的config.h放置在thrid_party/speexdsp下。
第二十四行到第五十二行:
- 第24行ohos_shared_library定义了最终生成的模块名,这里代表此模块为最终生成libspeexdsp.z.so/动态库
如果是生成静态库ohos_static_library(" ") { }
-
第二十五行到第三十五行sources模块包含了需要编译的源码文件
-
第四十六行到五十行include_dirs模块包含了编译依赖的头文件路径
-
第五十一行part_name 该模块编译依赖的编译子系统组件名。该配置项是为了模块最终生成的so文件能在系统编译完后自动拷贝到系统目录中。如果没有配置该项,系统编译完后是不会自动将生成的so文件拷贝到系统目录。
测试用例gn化,新增工程构建脚本
OpenHarmony/sources/third_party/speexdsp/libspeexdsp下添加BUILD.gn脚本文件。
代码解析
测试用例gn化代码解析的内容与speexdsp编译gn化内容相似,这里不做重复解释,只补充以下几点。
- 测试用例是在ohos上测试libspeexdsp.z.so功能用的。
- 第28、48、68、88、108行:gn中的目标类型executable表示生成可执行文件testdenoise、testecho、testjitter、testresample、testresample2。
- 第41、61、81、101、121行:deps表示测试用例模块编译依赖其他模块,这里指的是测试用例的编译依赖。libspeexdsp.z.so库。
- 第45、65、85、105、125行:part_name表示测试用例模块编译依赖的编译子系统组件名。该配置项是为了模块最终生成的so文件能在系统编译完后自动拷贝到系统目录中。如果没有配置该项,系统编译完后是不会自动将生成的so文件拷贝到系统目录。
OpenHarmony/sources/third_party/speexdsp目录下添加ohos.build。
- 定义子系统并加入到编译框架
在系统源码根目录下创建一个目录作为子系统目录,子系统目录可创建在OpenHarmony源码目录任意位置。- 本项目以third_party/speexdsp作为为子系统目录,子系统名字即为speexdsp。
子系统speexdsp目录下创建ohos.build文件,build构建时会先读取该文件。
- build文件夹下的subsystem_config.json文件,主要包含子系统名称与路径信息,在preloader阶段被加载,根据子系统名称和路径信息查找该路径下的ohos.build文件。
- 其中需要包含module_list、inner_kits、system_kits、test_list四个部分的声明:
- module_list:部件包含的模块列表
- inner_kits:部件提供其它部件的接口
- system_kits:部件提供给生成应用的接口
- test_list:部件对应模块的测试用例
修改build/subsystem_config.json,新增子系统定义。
在源码/build/subsystem_config.json中增加子系统选项,把子系统speexdsp配置到build/subsystem_config.json。
注意:要求符合json语法规范,要在}
前加,
(如下图所示)
修改vendor/hihope/rk3568/config.json文件将speexdsp添加至rk3568开发板,在vendor目录下新增产品的定义。
将子系统及其组件加入产品定义中,以rk3568为例,产品定义文件在vendor/hihope/rk3568/config.json,需要将以下内容添加到config.json中:
下期分享内容:在OpenHarmony的编译体系下编译speexdsp的so和测试用的可执行文件,以及编译报错的解决办法
知识点附送
本文中知识点附送
的内容并不和移植speexdsp到openharmony标准系统
直接相关,仅作为拓展阅读的知识点,因此读者可以不作过细的了解。
gn
-
generate ninja工具,在out目录下生成ninja编译文件*.ninja,gn的可执行文件位置在prebuilts/build-tools/linux-x86目录里
ninja
ninja构建工具,编译时根据gn生成的*.ninja文件进行编译构建,ninjiad的可执行文件位置在prebuilts/build-tools/linux-x86目录里
关于deps、external_deps的使用
在添加一个模块的时候,需要在BUILD.gn中声明它的依赖,为了便于后续处理部件间依赖关系,我们将依赖分为两种——部件内依赖deps和部件间依赖external_deps。
依赖分类:
如上图所示,主要分为部件内依赖(图左)和部件间依赖(图右)。
部件内依赖: 现有模块module1属于部件part1,要添加一个属于部件part1的模块module2,module2依赖于module1,这种情况就属于部件内依赖。
部件间依赖: 现有模块module1属于部件part1,要添加一个模块module2,module2依赖于module1,module2属于部件part2。模块module2与模块module1分属于两个不同的部件,这种情况就属于部件间依赖。
部件内依赖示例:
部件间依赖示例:
注意:部件间依赖要写在external_deps里面,格式为”部件名:模块名"的形式,并且依赖的模块必须是依赖的部件声明在inner_kits中的模块。
查看.ninja_log文件可以知道每个模块编译的开始和结束时间
out/rk3568/.ninja_log文件记录了每个模块编译的开始和结束时间(ms),结束时间和开始时间间隔越短表示模块的编译时间越短,编译性能越高。
从左到右分别表示:start time|end time|mtime|command hash。
mtime(modify time)显示的是文件内容被修改的最后时间
这是我见过最细致的完整的流程分享了,必须支持!
逐行讲解,够用心
期待更新 支持!!
如果DevEco Device Tool更新,移植是不是可能要重新适配
和编译工具没关系
要更新三方库版本可能要重新适配
移植speexdsp到openharmony第5期已更新:https://ost.51cto.com/posts/16848
不是rk3568开发板的话能开发吗
可以,适配了openhamrony标准系统的都行