- 大家好!我来自南京,在OpenHarmony成长打算啃论文俱乐部,与
华为、软通能源、润和软件、拓维信息、深开鸿
等公司一起,学习和钻研操作系统技术
从往年1月11日退出OpenHarmony俱乐部曾经有靠近8个月工夫了。笔者始终在思考啃论文给我带来了些什么,通过啃论文能为OpenHarmony做些什么。笔者利用大二升大三寒假两个月工夫移植了Speexdsp这个三方库到OpenHarmony规范零碎,而对于后面的问题我仿佛找到了答案,现将啃论文和三方库移植分享教训如下:
因为想要分享的内容较多,为防止读者姥爷们失去看上来的急躁,分享将以连载的形式进行。
下期预报:speexdsp功能分析和功能测试
本期为移植speexdsp到OpenHarmony规范零碎
的第④期,次要内容如下:
speexdsp移植后已提交至openhamrony sig仓库:https://gitee.com/openharmony...
五、在OpenHarmony编译体系下增量编译Speexdsp
倡议先增量编译生成三方库的动态链接库和可执行文件,验证是否胜利把三方库退出OpenHarmonybian编译体系。
- 胜利编译出so和可执行文件,即胜利把三方库退出到ohos编译体系。之后还要验证三方库在ohos运行,性能是否失常。性能失常能力视为移植胜利。
举荐增量编译出三方库的动态链接库和测试用例,不举荐的做法是把三方库退出openharmony编译体系后全量编译出烧录ohos用的固件。
- 第一是因为全量编译ohos对电脑的性能,特地是内存要求比拟高(笔者的笔记本上的虚拟机内存给到了32G,对学生开发者来讲,编译ohos的硬件门槛还是有点高的。)增量编译对内存要求不是特地高。(笔者的8G内存二合一笔记本都能够编译进去,并且虚拟机内存只给到了4GB左右)
- 第二是因为全量编译破费工夫较多(笔者残缺编译出一个固件须要3个小时左右。)增量编译须要的工夫绝对较少(笔者大略只须要破费9分钟左右)
全量编译和增量编译概念
- 全量编译是将所有文件从新编译,从新生成解决方案就是全量编译
- 增量编译只对改变的文件进行编译,执行生成解决方案就是增量编译
在源码目录执行如下命令,进行增量编译:
./build.sh --product-name rk3568 --ccache --build-target=speexdsp --target-cpu arm64
ohos3.2beta1
版本开始新增个性,反对64位零碎的编译,默认状况下编译的都是32位零碎,在编译命令中增加--target-cpu arm64
即可构建64位零碎,编译so和可执行文件的执行语句更改为:
放慢本地编译的一些参数
编译时,适当抉择增加以下的编译参数能够放慢编译的过程。
增加--ccache参数:
- 原理:ccache会缓存c/c++编译的编译输入,下一次在编译输出不变的状况下,间接复用缓存的产物。
装置:
疾速装置:执行sudo apt-get install ccache命令。
- 应用:执行./build.sh --product-name 产品名 --ccache命令。
增加--fast-rebuild参数
- 原理:编译流程次要分为:preloader->loader->gn->ninja这四个过程,在本地没有批改gn和产品配置相干文件的前提下,增加--fast-rebuild会让你间接从ninja编译开始。
- 应用:执行./build.sh --product-name 产品名 --fast-rebuild命令。
增加enable_notice_collection=false参数
- 原理:省略掉收集开源软件模块的license的过程。
- 应用:执行./build.sh --product-name 产品名 --gn-args --enable_notice_collection=false --ccache命令。
增加--build-target参数
该参数用于指定编译模块,如何找模块的名字:
- 相干仓下BUILD.gn中关注group、ohos_shared_library、ohos_executable等关键字。
- ./build.sh --product-name 产品名 --build-target 模块名 --build-only-gn生成build.ninja,而后去该文件中查找相干模块名。
- 应用:执行./build.sh --product-name 产品名 --build-target ark_js_host_linux_tools_packages命令。
解决编译报错
(笔者了解移植过程必定不会是一帆风顺的)
执行编译命令后,有局部报错
1.局部头文件缺失报错‘speexdsp_config_types.h’ file not found
编译找不到third_party/speexdsp/include/speex目录下的speexdsp_config_types.h文件。
../../third_party/speexdsp/include/speex/speexdsp_types.h:122:10: fatal error: 'speexdsp_config_types.h' file not found
解决办法:
- speexdsp_types.h 是由linux下编译生成的,因而须要在Linux下编译整个Speexdsp源码,而后把在speexdsp原生库目录下build/include/speex目录生成的speexdsp_types.h文件拷贝到要ohos源码下的third_party/speexdsp/include/speex目录下,
2.json文件语法产生谬误。
解决办法:
查看out/rk3568目录下build.log文件,查看源码/build/subsystem_config.json文件语法
笔者呈现这个问题的起因是json文件语法产生谬误,在subsystem_config.json文件第一行的{
没有匹配}
,增加下来就没问题。
编译胜利
解决完编译报错后,再次执行编译命令。
./build.sh --product-name rk3568 --ccache --build-target=speexdsp --target-cpu arm64
编译胜利,终端打印信息如下:
(上面只选取要害的一小部分,理论打印进去的信息有两千行左右。)
[email protected]:~/Desktop/OpenHarmony/sources$ ./build.sh --product-name rk3568 --ccache --build-target=speexdsp --target-cpu arm64++++++++++++++++++++++++++++++++++++++++2022-09-07 22:03:47--product-name rk3568 --ccache --build-target=speexdsp --target-cpu arm64......······[OHOS INFO] [1595/1633] STAMP obj/third_party/speexdsp/speexdsp_share.inputdeps.stamp[OHOS INFO] [1596/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/ttyname_r.o[OHOS INFO] [1597/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/ualarm.o[OHOS INFO] [1598/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/unlink.o[OHOS INFO] [1599/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/unlinkat.o[OHOS INFO] [1600/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/usleep.o[OHOS INFO] [1601/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/write.o[OHOS INFO] [1602/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/writev.o[OHOS INFO] [1603/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/string/soft_musl_src_nossp/mempcpy.o[OHOS INFO] [1604/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/string/soft_musl_src_nossp/memset.o[OHOS INFO] [1605/1633] STAMP obj/third_party/musl/soft_musl_src.stamp[OHOS INFO] [1606/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/buffer.o[OHOS INFO] [1607/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/fftwrap.o[OHOS INFO] [1608/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/filterbank.o[OHOS INFO] [1609/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/env/soft_musl_src_nossp/__libc_start_main.o[OHOS INFO] [1610/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/scal.o[OHOS INFO] [1611/1633] ASM obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/thread/aarch64/soft_musl_src_nossp/__set_thread_area.o[OHOS INFO] [1612/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/env/soft_musl_src_nossp/__init_tls.o[OHOS INFO] [1613/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/env/soft_musl_src_nossp/__stack_chk_fail.o[OHOS INFO] [1614/1633] STAMP obj/third_party/musl/soft_musl_src_nossp.stamp[OHOS INFO] [1615/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/jitter.o[OHOS INFO] [1616/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/preprocess.o[OHOS INFO] [1617/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/resample.o[OHOS INFO] [1618/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/mdf.o[OHOS INFO] [1619/1633] SOLINK obj/third_party/musl/usr/lib/aarch64-linux-ohos/libc.so[OHOS INFO] [1620/1633] STAMP obj/third_party/musl/soft_shared_libs.stamp[OHOS INFO] [1621/1633] STAMP obj/build/config/common_deps.stamp[OHOS INFO] [1622/1633] STAMP obj/build/config/executable_deps.stamp[OHOS INFO] [1623/1633] STAMP obj/build/config/shared_library_deps.stamp[OHOS INFO] [1624/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/smallft.o[OHOS INFO] [1625/1633] SOLINK speexdsp/speexdsp/libspeexdsp_share.z.so[OHOS INFO] [1626/1633] LINK speexdsp/speexdsp/testdenoise[OHOS INFO] [1627/1633] LINK speexdsp/speexdsp/testecho[OHOS INFO] [1628/1633] LINK speexdsp/speexdsp/testjitter[OHOS INFO] [1629/1633] LINK speexdsp/speexdsp/testresample[OHOS INFO] [1630/1633] LINK speexdsp/speexdsp/testresample2[OHOS INFO] [1631/1633] STAMP obj/out/rk3568/build_configs/speexdsp/speexdsp/speexdsp_info.stamp[OHOS INFO] [1632/1633] ACTION //out/rk3568/build_configs/speexdsp/speexdsp:speexdsp(//build/toolchain/ohos:ohos_clang_arm64)[OHOS INFO] [1633/1633] STAMP obj/out/rk3568/build_configs/speexdsp/speexdsp/speexdsp.stamp[OHOS INFO] ---------------------------------------------[OHOS INFO] ccache summary:[OHOS INFO] cache hit (direct) : 0[OHOS INFO] cache hit (preprocessed) : 0[OHOS INFO] cache miss : 1340[OHOS INFO] hit rate: 0.00% [OHOS INFO] mis rate: 100.00% [OHOS INFO] ---------------------------------------------[OHOS INFO] c targets overlap rate statistics[OHOS INFO] subsystem files NO. percentage builds NO. percentage overlap rate[OHOS INFO] aafwk 25 0.9% 25 0.9% 1.00[OHOS INFO] arkui 11 0.4% 11 0.4% 1.00[OHOS INFO] bundlemanager 45 1.5% 45 1.5% 1.00[OHOS INFO] communication 197 6.7% 197 6.7% 1.00[OHOS INFO] hiviewdfx 32 1.1% 32 1.1% 1.00[OHOS INFO] securec 78 2.7% 78 2.7% 1.00[OHOS INFO] speexdsp 14 0.5% 14 0.5% 1.00[OHOS INFO] startup 46 1.6% 46 1.6% 1.00[OHOS INFO] third_party 1065 36.3% 1065 36.3% 1.00[OHOS INFO] thirdparty 1065 36.3% 1065 36.3% 1.00[OHOS INFO] utils 58 2.0% 58 2.0% 1.00[OHOS INFO] zxing-cpp-1.2.0 117 4.0% 117 4.0% 1.00[OHOS INFO] [OHOS INFO] c overall build overlap rate: 1.00[OHOS INFO] [OHOS INFO] [OHOS INFO] rk3568 build success[OHOS INFO] cost time: 0:02:24=====build successful=====
验证编译后果
编译speexdsp生成的动态链接库和测试用的可执行程序,在openharmony源码目录的out/rk3568下。
out/rk3568/speexdsp目录构造如下:
├── libspeexdsp_share.z.so # 动态链接库├── testdenoise # 测试用例 ├── testecho # 测试用例 ├── testjitter # 测试用例 ├── testresample # 测试用例 └── testresample2 # 测试用例
六、API接口导出
在源码third_party/speexdsp目录下新建export_api文件夹。
1.在export_api目录下新建allHeads.h文件
该头文件中蕴含所有库对外导出的头文件。speexdsp有5个测试程序testdenoise、testecho、testjitter、testresample、testresample2。
查看这五个测试程序的源文件testdenoise.c、testecho.c、testjitter.c、testresample.c、testresample2.c。
其用到的libspeexdsp_share.z.so的头文件如下:
#include "speex_preprocess.h"#include "speex_echo.h"#include "speex_jitter.h"#include "speex_resampler.h"
2.新增allDySos目录,该目录下搁置生成的动静库:
3、新增allTests目录,该目录下搁置所有生成的测试文件:
4、新建自动化测试脚本export_interface.sh,如下所示:
其中cxx="0"示意依据.c文件进行导出,cxx="1"则示意依据.cpp文件进行导出(如果导出c++的三方库的api接口,应用该脚本就让cxx=1):
#!/bin/sh#C库cxx="0"mixed_api() { while read line do if [ $cxx != "1" -o "$4" == "1" ];then tmp=$line else tmp=`echo $line | sed "s/(.*$//g" | sed "s/^.*:://g"` fi res=`cat $2 |grep "$tmp" -F` if [ "$res" != "" ];then echo "$line" >> $3 fi done < $1}remove_standard_api() { flag="0" while read line do tmp1=`echo $line |grep ".*#.*\/usr\/"` tmp2=`echo $line |grep ".*#.*[0-9].*\".*\""` if [ "$tmp1" != "" ];then flag="0" elif [ "$tmp2" != "" ];then flag="1" elif [ $flag == "1" ];then echo "$line" >> $2 fi done < $1}src1="allHeads.h"src2="allDySos"src3="allTests"if [ $cxx == "1" ];then flags_D="-DC" flags_DU="-DCu" CC=g++else flags_D="-D" flags_DU="-Du" CC=gccfiif [ ! -e $src1 ];then echo "$src1 is not exist!" exit 1fiif [ ! -e $src2 ];then echo "$src2 is not exist!" exit 1fiif [ ! -e $src3 ];then echo "$src3 is not exist!" exit 1firm -rf $src1.i* $src2.txt $src3.txt export_api.txt tested_api.txt$CC -E $* $src1 -o $src1.iif [ "$?" != "0" ];then exit 1firemove_standard_api $src1.i $src1.i.tmpnm $src2/* $flags_D | sort -u | grep " T " | sed "s/^.* T //g" >> $src2.txtnm $src3/* $flags_DU | sort -u | sed "s/^.* U //g" >> $src3.txtmixed_api $src2.txt $src1.i.tmp export_api.txt 0mixed_api export_api.txt $src3.txt tested_api.txt 1rm -rf $src1.i* $src2.txt $src3.txt
执行脚本导出api接口
执行该脚本导出api接口时,须要给脚本传入编译头文件的参数。(运行此api接口导出脚本在PC端)
例如
./export_interface.sh -I 头文件所在门路 -D宏定义(编译所有动静库时,cflags/cflags_cc中的参数)
- 头文件所在门路为绝对路径
- D宏定义指的是(编译所有动静库时,cflags/cflags_cc中的参数)
笔者导出speexdsp API接口,在export_api文件夹下关上终端输出了如下命令:
chmod 777 export_interface.sh./export_interface.sh -I/home/jiajiahao/Desktop/OpenHarmony/sources/third_party/speexdsp/include/speex
后果是生成export_api.txt(导出so对外api接口)与testd_api.txt(导出测试程序所用到so对外导出api接口 )。
export_api.txt文件内容如下:
speex_preprocess_state_initspeex_preprocess_state_destroyspeex_preprocessspeex_preprocess_runspeex_preprocess_estimate_updatespeex_preprocess_ctljitter_buffer_initjitter_buffer_ctljitter_buffer_resetjitter_buffer_destroyjitter_buffer_putjitter_buffer_getjitter_buffer_get_anotherjitter_buffer_update_delayjitter_buffer_get_pointer_timestampjitter_buffer_tickjitter_buffer_remaining_spanspeex_echo_state_initspeex_echo_state_init_mcspeex_echo_state_resetspeex_echo_state_destroyspeex_echo_capturespeex_echo_cancellationspeex_echo_playbackspeex_echo_cancelspeex_echo_ctlspeex_resampler_initspeex_resampler_init_fracspeex_resampler_set_qualityspeex_resampler_set_rate_fracspeex_resampler_destroyspeex_resampler_process_floatspeex_resampler_process_intspeex_resampler_process_interleaved_floatspeex_resampler_process_interleaved_intspeex_resampler_set_ratespeex_resampler_get_ratespeex_resampler_get_ratiospeex_resampler_get_qualityspeex_resampler_set_input_stridespeex_resampler_get_input_stridespeex_resampler_set_output_stridespeex_resampler_get_output_stridespeex_resampler_get_input_latencyspeex_resampler_get_output_latencyspeex_resampler_skip_zerosspeex_resampler_reset_memspeex_resampler_strerrorspeex_decorrelate_newspeex_decorrelatespeex_decorrelate_destroy
tested_api.txt文件内容如下:
speex_preprocess_state_initspeex_preprocess_state_destroyspeex_preprocessspeex_preprocess_runspeex_preprocess_ctljitter_buffer_initjitter_buffer_resetjitter_buffer_putjitter_buffer_getjitter_buffer_tickspeex_echo_state_initspeex_echo_state_destroyspeex_echo_cancellationspeex_echo_cancelspeex_echo_ctlspeex_resampler_initspeex_resampler_destroyspeex_resampler_process_floatspeex_resampler_set_ratespeex_resampler_skip_zeros