基于Docker编译&调试WebRTC源码
学习音视频,绕不过WebRTC这个大名鼎鼎的框架,今天来看下如何使用Docker编译&调试WebRTC吧。
前言
本文将带大家学习如何在Docker下,配置WebRTC的编译&调试开发环境——基于Ubuntu 18.04系统,并记录了对WebRTC Sdk的Java和native进行调试的方法。
WebRTC是谷歌的一个著名开源项目之一,托管在谷歌的服务器上。由于众所周知的原因,谷歌的产品服务难以在国内访问。请各位合理使用网络,准备上网加速工具,可以避免很多问题。
WebRTC官网:WebRTC。
编译
配置Docker环境
本文主要以MacOS和Linux为例,Windows用户请找到对应命令的图形化操作路径即可。
1. 安装Docker
请参考Docker官方文档进行安装:Install Docker Engine。
2. 获取Ubuntu 18.04镜像
强烈建议镜像使用 Ubuntu 18.04及以上版本,避免后续环境配置的问题!!!
打开终端,执行:
1 | docker pull ubuntu:18.04 |
即可获取到Ubuntu 18.04镜像。
3. 创建一个Ubuntu 18.04容器
1 | docker run -d -p 22:2222 ubuntu:18.04 |
这里映射了容器内的22端口到主机的2222端口,为的是后续使用
rsync
同步文件方便。
4. 容器内系统的基础配置
1 | apt update && apt upgrade -y |
安装源码下载工具
下载WebRTC源码需要用到Google开发的depot tools,它是为Chromium项目专门开发的一套源码管理工具,底层用到了Git。
depot tools的使用文档:depot tools(7) Manual Page
1 | mkdir ~/.local |
下载源码
因为主要在Android平台上进行开发,所以仅下载WebRTC核心+Android部分的代码。
1 | mkdir ~/code/webrtc |
上面拉取的是最新的主线代码,强烈建议使用--no-history
参数,加快下载速度,减少磁盘占用。
2021年11月13日 完整下完整套代码,约27G~
一般项目开发中会选择一个正式的release版本。截止到2021年11月13日,最新的版本是M85
,下面基于M85创建一个自己的开发分支。
Release信息可以在这查询:Chrome Release Notes | WebRTC
1 | # 基于M85 release(对应的分支名为branch-heads/4183)创建一个名为m85的分支,并且切换过去 |
安装编译依赖
在WebRTC源码中,包含了自动安装编译依赖的脚本,直接使用即可。
1 | # 如果没有安装python命令,需要软链接下 |
开始编译
同样,WebRTC源码中包含了编译Android AAR的脚本,直接使用。
1 | ./tools_webrtc/android/build_aar.py --build-dir Build --arch arm64-v8a |
上面的命令中,我们指定了编译中间产物的路径和目标架构。
可以通过./tools_webrtc/android/build_aar.py -h
查看可传入的参数列表及详细的信息:
从图中可以看到WebRTC支持编译armeabi-v7a
、arm64-v8a
、x86
、x86_64
这四种架构。
建议只编译所需架构,减少非必要的时间。笔者用nuci5beh(豆子峡谷)单编译arm64-v8a架构,花了十分钟。
最终编译产物(aar文件)将会在~/code/webrtc/src/
目录下,即~/code/webrtc/src/libwebrtc.aar
。
调试
光说不练假把式,来看下如何使用Android Studio调试WebRTC Android Sdk的Java和native代码吧。
WebRTC官方给的Android Demo是这个:examples/androidapp - src - Git at Google (googlesource.com)。
但由于一些问题,无法使用Android Studio进行调试。原因可看:9282 - Support Android Studio for Android development - webrtc (chromium.org)。
幸运的是,国内的小伙伴mthli (Matthew Lee) (github.com)提供了一份可导入Android Studio进行调试的Demo:YaaRTC。我们用它来演示如何进行调试吧。
编译Debug包
通常,调试需要用到包含符号信息等调试信息的包,即Debug包。但是在编译时,默认会把调试信息strip掉。因此需要修改下编译脚本,并重新构建生成aar
文件。
建议参考断点调试 - WebRTC 学习指南 (mthli.com) 。这里抄录下相关配置。
1 | # 修改~/code/webrtc/src/build/toolchain/android/BUILD.gn文件 |
编译时,注意还需要添加一些参数:
1 | ./tools_webrtc/android/build_aar.py --build-dir=Build --arch arm64-v8a --extra-gn-args "is_debug=true symbol_level=2 android_full_debug=true" |
等待编译完成,这样就得到了带调试信息的Debug包。记得用它替换掉项目中正在用的libwebrtc.aar
。
配置build.gradle
除了需要Debug包以外,还需要在引用了WebRTC Android Sdk模块的build.gradle
中,做如下修改:
1 | android { |
YaaRTC已经配置好了,不放心的小伙伴可以检查下。
开始调试
同步源码从容器到宿主机
如果仅需要调试WebRTC SDK的Java代码,可跳过此步骤。
调试Native层需要用到源码,由于WebRTC的源码位于容器中,因此需要先把它弄到宿主机。可以直接使用docker cp
命令:
1 | # 使用Docker cp命令 |
很明显,这样做有缺点:
- 宿主机和容器中各有一份完全相同的源码,占据磁盘空间。
- 这样会把整份文件夹(包括check用的metadata)拷贝到宿主机,其实没有必要。
关于第一点,笔者认为可以通过sambad等方式,将容器的源码挂在到本地实现(尚未验证)。因为本地不需要编译,理论不会对容器内的编译产生影响。
关于第二点,事实上只需要同步部分native代码。因此,不嫌麻烦,可以手动只同步特定文件夹。如~/code/webrtc/src/pc/
。
其实第二点还有一个更好的解决方案,就是使用rsync
。它支持增量同步和指定同步/屏蔽特定文件。可以完美解决我们的第二点需求。此处不做讨论。
配置调试选项
如果需要调试Java和native,需要修改debug type
为Dual
。操作如下图:
在LLDB Debugger启动前,还需要对源码文件进行映射(mapping)——因为Sdk是在容器中编译的,和宿主机上实际的位置并不一致。
按如下操作添加映射规则:
1 | settings set target.source-map {符号文件中的路径} {宿主机中实际的路径} |
其中,符号文件中的路径,需要「开启Debug」+「进行一次呼叫然后挂断」,再按下图步骤,使用如下命令查看:
1 | image lookup -vrn webrtc::PeerConnection::RestartIce |
注意到有一个有趣的现象:该应用在挂断时会发生Crash。开始不明白为什么,以为是个Bug,等到写此文时突然意识到:如果不crash,那我们恐怕无法拿到符号文件中的路径——因为没办法进行上图中第4步。
调试Java
跟普通应用的调试方法一样,在需要调试的位置添加断点即可,如下图所示。
调试native
通过Android Studio打开C++源码文件,然后在需要调试位置加上断点,再进入Debug。如下图所示:
结束语
非常感谢@mthil分享的经验!