乐趣区

关于openharmony:啃论文俱乐部移植speexdsp到OpenHarmony标准系统④

  • 大家好!我来自南京,在 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=gcc
fi

if [! -e $src1];then
    echo "$src1 is not exist!"
    exit 1
fi

if [! -e $src2];then
    echo "$src2 is not exist!"
    exit 1
fi

if [! -e $src3];then
    echo "$src3 is not exist!"
    exit 1
fi

rm -rf $src1.i* $src2.txt $src3.txt export_api.txt tested_api.txt

$CC -E $* $src1 -o $src1.i

if ["$?" != "0"];then
    exit 1
fi

remove_standard_api $src1.i $src1.i.tmp

nm $src2/* $flags_D | sort -u | grep "T" | sed "s/^.* T //g" >> $src2.txt
nm $src3/* $flags_DU | sort -u | sed "s/^.* U //g" >> $src3.txt

mixed_api $src2.txt $src1.i.tmp export_api.txt 0
mixed_api export_api.txt $src3.txt  tested_api.txt 1

rm -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_init
speex_preprocess_state_destroy
speex_preprocess
speex_preprocess_run
speex_preprocess_estimate_update
speex_preprocess_ctl
jitter_buffer_init
jitter_buffer_ctl
jitter_buffer_reset
jitter_buffer_destroy
jitter_buffer_put
jitter_buffer_get
jitter_buffer_get_another
jitter_buffer_update_delay
jitter_buffer_get_pointer_timestamp
jitter_buffer_tick
jitter_buffer_remaining_span
speex_echo_state_init
speex_echo_state_init_mc
speex_echo_state_reset
speex_echo_state_destroy
speex_echo_capture
speex_echo_cancellation
speex_echo_playback
speex_echo_cancel
speex_echo_ctl
speex_resampler_init
speex_resampler_init_frac
speex_resampler_set_quality
speex_resampler_set_rate_frac
speex_resampler_destroy
speex_resampler_process_float
speex_resampler_process_int
speex_resampler_process_interleaved_float
speex_resampler_process_interleaved_int
speex_resampler_set_rate
speex_resampler_get_rate
speex_resampler_get_ratio
speex_resampler_get_quality
speex_resampler_set_input_stride
speex_resampler_get_input_stride
speex_resampler_set_output_stride
speex_resampler_get_output_stride
speex_resampler_get_input_latency
speex_resampler_get_output_latency
speex_resampler_skip_zeros
speex_resampler_reset_mem
speex_resampler_strerror
speex_decorrelate_new
speex_decorrelate
speex_decorrelate_destroy

tested_api.txt 文件内容如下:

speex_preprocess_state_init
speex_preprocess_state_destroy
speex_preprocess
speex_preprocess_run
speex_preprocess_ctl
jitter_buffer_init
jitter_buffer_reset
jitter_buffer_put
jitter_buffer_get
jitter_buffer_tick
speex_echo_state_init
speex_echo_state_destroy
speex_echo_cancellation
speex_echo_cancel
speex_echo_ctl
speex_resampler_init
speex_resampler_destroy
speex_resampler_process_float
speex_resampler_set_rate
speex_resampler_skip_zeros

下期预报:speexdsp 功能分析和功能测试

退出移动版