ubuntu18.04编译webrtc_android库

语言: CN / TW / HK

webrtc 是谷歌提供的音视频通讯方案, 能够很好的解决音视频互联互通的场景. 本文基于 Ubuntu 18.04 编译 android 版本的过程, 其它平台也可以参考, 基本都大同小异.

编译环境要求

  • 磁盘预留空间不小于 30GB.
  • 编译过程需要确保你能正常访问 google 相关服务, 如有条件可以在命令行使用代理访问.

```shell

export http_proxy=http://ip:port export https_proxy=http://ip:port export all_proxy=http://ip:port

```

  • 由于项目太大, 建议使用固态硬盘的电脑, 加快同步时间, 减少超时等出错几率.
  • 以下过程是基于 Ubuntu 18.04 编译.
  • Python3 >= 3.7 版本

编译webrtc android

安装 depot_tools 工具

depot_tools 工具包包含了谷歌 gclient, gcl, git-cl, repo 等工具, 用于管理项目源码, 分发及编译等. 安装方式如下:

```shell

使用 git clone 到本地

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

``` 在环境变量PATH 中加入路径, 以便方便使用命令. 根据自己使用的 shell 加到不同的启动文件中. ( .bashrc 或 .zshrc)

```shell

指定自己 depot_tools 的具体路径

export PATH=/path/to/depot_tools:$PATH

```

同步代码

同步代码我们主要使用的是 gclient 工具, 这是一个 python 脚本文件, 可以对于多模块依赖的项目源码进行管理, 可以根据不同系统同步所有所依赖模块的代码版本.

  • 创建工作目录 mkdir webrtc-checkout
  • 使用 fetch 下载 webrtc android 代码. (如果 fetch 执行出错的话, 也可以继续使用 gclient --with_branch_heads 同步下来 webrtc 源码).

```shell cd webrtc-checkout fetch --nohooks webrtc_android

``` - 使用 gclient 同步依赖项目源码及工具, 同步时间较长, 几个小时肯定要的.

```shell gclient sync

```

NOTE: - 如果 fetch 没有出错的话, webrtc 源码通过 git branch -av 是可以看到所有的 branch-heads 的分支. - 如果 fetch 出错后, 是通过 gclient 不带参数同步下来的 webrtc 源码. 就只能看到 master、infra/config 以及 lkgr 几个分支. 我们可以修改仓库的 .git/config 文件,在 [remote "origin"] 节中添加以下内容:

fetch = +refs/branch-heads/*:refs/remotes/origin/*

安装编译环境依赖库

``` cd webrtc-checkout/src ./build/install-build-deps-android.sh

```

选择源码版本

可以通过官方网站查看到所有的 webrtc 版本, 尽量优先选择稳定版本分支 checkout. https://chromiumdash.appspot.com/branches

image.png

我这里是使用 M108 分支进行编译.

使用 gn 编译

  • 使用 gn 设置编译目录及参数. gn 可以指定编译目录及参数, 因此相对于其它编译工具, 可以同时并行多个编译版本.

```shell cd src gn gen out/my_build --args='target_cpu="arm" target_os="android" android32_ndk_api_level=18'

```

target_os 参数可使用的值可以通过以下命令查看:

```shell gn help target_os

# output Possible values

- "android"
- "chromeos"
- "ios"
- "linux"
- "nacl"
- "mac"
- "win"

```

target_cpu 参数可使用的值可以通过以下命令查看:

```shell gn help target_cpu

# output Possible values

- "x86"
- "x64"
- "arm"
- "arm64"
- "mipsel"
- "mips64el"
- "s390x"
- "ppc64"
- "riscv32"
- "riscv64"
- "e2k"
- "loong64"

```

  • 使用 gn 执行编译. ninja -C out/my_build . ( 这个是增量编译, 第一次时间较长)

image.png

编译时间较长, 有 1w 多个目录需要编译, 估计得 1~2 小时吧.

  • 清除编译生成但留下编译配置. gn clean out/my_build

FAQ

  • 编译依赖组件 ffmpeg 出现如下错误:

../../third_party/ffmpeg/libavutil/arm/cpu.c:58:25: error: call to undeclared function 'getauxval'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] unsigned long ret = getauxval(AT_HWCAP); ^ ../../third_party/ffmpeg/libavutil/arm/cpu.c:58:25: note: did you mean 'get_auxval'? ../../third_party/ffmpeg/libavutil/arm/cpu.c:55:12: note: 'get_auxval' declared here static int get_auxval(uint32_t *hwcap) ^ 1 error generated. [3264/9167] ASM obj/third_party/ffmpeg/ffmpeg_internal/fft_vfp.o ninja: build stopped: subcommand failed.

Answer:

查看了 third_party/ffmpeg/libavutil/arm/cpu.c 源码, getauxval 函数是在以下这个头文件中定义.

c #if HAVE_GETAUXVAL #include <sys/auxv.h> #endif auxv.h 是定义在 android 交叉编译 third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sys/auxv.h 中, 声明函数时会限制 API 版本为 18 及以上.

```c

#if ANDROID_API >= 18 unsigned long int getauxval(unsigned long int __type) __INTRODUCED_IN(18); #endif / ANDROID_API >= 18 /

`` 而我在编译时指定的参数是--args='target_cpu="arm" target_os="android" ...' 是 32 位版本, 在src/.gn` 文件中能看到对于 32 位版本的 API 默认 16:

```shell # The SDK API level, in contrast, is set by build/android/AndroidManifest.xml. android32_ndk_api_level = 16 android64_ndk_api_level = 21

`` 所以如果编译 32 位版本, 解决这个问题的方式就是在编译时指定下android32_ndk_api_level` 的版本为 18 即可. 如:

```shell gn gen out/my_build --args='target_cpu="arm" target_os="android" android32_ndk_api_level=18'

`` 对于编译所有的参数, 可以使用gn args --list out/my_build` 具体查看.

  • 编译出现 ModuleNotFoundError: No module named 'dataclasses' 错误.

Answer:

通过相关资料了解 dataclasses 模块至少需要 python3.7 才支持的, 需要升级 python3 版本. 我看了下自己 ubuntu 18.04 还是 3.6 的版本, 通过 apt-get install 安装 3.8 版本.
为了切换方便, 可以通过 update-alternatives 进行管理, 相关的执行命令如下:

```shell # 安装 3.8 版本 sudo apt-get install python3.8

# 为 python3 安装可切换的管理版本 sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1 sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2

# 切换python3 使用的版本, 根据提示选择使用的版本编号 sudo update-alternatives --config python3

```

References