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