转载:http://depthlove.github.io/2019/05/02/webrtc-development-2-source-code-download-and-build/

在使用任何工具之前,我们都有必要对工具做大概地的了解,做到粗犷但不失偏颇,这对我们选择工具和切入点是很关键的。本节的标题虽然是 WebRTC 源码下载与编译,但在这之前,我们有必要大概地了解 WebRTC,比如开发机构、免费性、支持的平台、功能亮点。

WebRTC 是一个免费开源的跨平台项目,由 Google,Mozilla,Opera 等支持,支持 Chrome,Firefox,Opera 以及 Android 和 iOS 平台,能够给浏览器、手机应用和物联网设备提供了实时互动能力。

WebRTC 是一组协议和 API。WebRTC 的起源可追溯到 2011年,经过六年多的时间的发展,在 2017年底 WebRTC 1.0 标准正式出炉。通过 WebRTC 的 Release Notes 可以看到现在最新的 release 版本是 M74 Release Noted。

2015年移动端直播的兴起,观众可以在手机端实时看主播的直播,但是观众与主播之间的沟通需要通过发弹幕来进行,这种交流的实时性较差,沟通不便利,观众参与感较差。2016年初移动端上出现了主播与观众之间可以通过实时视频聊天这种方式来沟通,即,视频连麦。那我们想实现这种视频连麦的功能该怎么做呢?

现在通过 WebRTC 以及其它一些音视频工具,我们就可以搭建一个视频聊天工具,做到视频连麦,也能做到类似于微信视频群聊。关于各种实现视频连麦的方式,这里就不细说了,放到后面的章节来解说。

了解到 WebRTC 是个什么东西后,通常人的心里就会产生一种跃跃欲试的冲动,想试试,那试试就试试呗。“磨刀不误砍柴工”这句话是有道理的,当我们没有经验和没有人传授经验的时候,那我们就要琢磨这句“磨刀不误砍柴工”了。我们要砍柴做饭,找到一把刀拿起就跑到树林里去砍柴,结果发现刀太钝,砍柴真费劲。这个时候,我们就意识到砍柴刀要用磨刀石磨一磨,磨锋利了,就能提升砍柴的效率。我举这个例子,就想说明两点:

第一,先尝试可以加深理解,获取自己的经验。

第二,通过获取的经验,重新调整,比如调整做事步骤,加深理论学习等。

WebRTC 支持 Windows, Mac OS X, Linux, Android 和 iOS 平台,这里以 iOS 平台为例来描述 WebRTC 的源码下载和编译过程。

一、安装 depot_tools 工具包

下载源码的时候,要用到 depot_tools 工具包,这是 Chromium 官方推荐的工具包,具备下载、同步、编译、上传代码等功能。depot_tools 的详细介绍见 Using depot_tools。depot_tools 包含如下工具包:

1
2
3
4
5
6
7
8
9
10
11
12
13
gclient
gcl
git-cl
svn [只在 Windows 上使用]
drover
cpplint.py
pylint
presubmit_support.py
repo
wtf
weekly
git-gs
zsh-goodies

step 1

depot_tools 源码属于 Google 的服务,即墙外资源,在获取 depot_tools 源码前,先需要开启 VPN 服务,然后在终端执行命令

1
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
1
2
3
4
5
6
suntongmiandeMacBook-Pro:~ suntongmian$ cd /Users/suntongmian/Documents/develop/webrtc
suntongmiandeMacBook-Pro:webrtc suntongmian$
suntongmiandeMacBook-Pro:webrtc suntongmian$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
正克隆到 'depot_tools'...
fatal: unable to access 'https://chromium.googlesource.com/chromium/tools/depot_tools.git/': Failed to connect to chromium.googlesource.com port 443: Operation timed out
suntongmiandeMacBook-Pro:webrtc suntongmian$

出现 “Failed to connect to chromium.googlesource.com port 443: Operation timed out” 问题后,需要检查 VPN 服务是否开启,网络状况是否良好。如果在 VPN 服务开启和网络状况良好的情况下,仍然不能 clone 代码成功,那就需要检查终端能否成功访问墙外的资源。

我开启了 VPN 服务,网络状况也很好,也能通过 Google 浏览器访问资源,但就是不能 clone depot_tools 源码成功。这个时候,我通过命令 curl 来检查终端是否具备翻墙功能。

首先,在终端执行命令

1
curl www.baidu.com
1
2
3
4
5
suntongmiandeMacBook-Pro:webrtc suntongmian$ curl www.baidu.com
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div
www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
suntongmiandeMacBook-Pro:webrtc suntongmian$

可以看到,能很快获取到 www.baidu.com 的资源。说明网络是正常的。

其次,在终端执行命令

1
curl www.google.com
1
2
3
suntongmiandeMacBook-Pro:webrtc suntongmian$ curl www.google.com
curl: (7) Failed to connect to www.google.com port 80: Operation timed out
suntongmiandeMacBook-Pro:webrtc suntongmian$

可以看到,出现了请求超时的问题。说明通过终端不能访问 Google 服务。那该怎么解决呢?

我的 MacBook 电脑上使用了 ShadowsocksX 客户端来启动 VPN 服务,但只支持浏览器能使用 VPN 服务。我参考了 MAC 终端走代理服务器 一文中提到的方法来解决这个问题。

我的 ShadowsocksX 客户端中 Socks5 配置信息如下

1
2
3
本地Socks5监听地址:127.0.0.1
本地Socks5监听端口:10808
连接超时:60

通过 Socks5 的配置信息,在终端中执行命令

1
2
3
export http_proxy=socks5://127.0.0.1:10808
export https_proxy=socks5://127.0.0.1:10808
export all_proxy=socks5://127.0.0.1:10808
1
2
3
4
5
6
suntongmiandeMacBook-Pro:webrtc suntongmian$ export http_proxy=socks5://127.0.0.1:10808
suntongmiandeMacBook-Pro:webrtc suntongmian$
suntongmiandeMacBook-Pro:webrtc suntongmian$ export https_proxy=socks5://127.0.0.1:10808
suntongmiandeMacBook-Pro:webrtc suntongmian$
suntongmiandeMacBook-Pro:~ suntongmian$ export all_proxy=socks5://127.0.0.1:10808
suntongmiandeMacBook-Pro:~ suntongmian$

提示:执行后,只对当前终端起作用。重启终端后,默认失效。

启动了终端代理,然后再次执行命令

1
curl www.google.com
1
2
3
4
suntongmiandeMacBook-Pro:webrtc suntongmian$ curl www.google.com
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en"><head><meta content="Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for." name="description"><meta content="noodp" name="robots"><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/logos/doodles/2019/us-teacher-appreciation-week-2019-begins-4994791740801024-l.png" itemprop="image"><meta content="Happy US Teacher Appreciation Week 2019!" property="twitter:title"><meta content="Happy US Teacher Appreciation Week 2019! #GoogleDoodle"
\u003E\x22,\x22psrl\x22:\x22Remove\x22,\x22sbit\x22:\x22Search by image\x22,\x22srch\x22:\x22Google Search\x22},\x22ovr\x22:{},\x22pq\x22:\x22\x22,\x22refpd\x22:true,\x22rfs\x22:[],\x22sbpl\x22:24,\x22sbpr\x22:24,\x22scd\x22:10,\x22sce\x22:5,\x22stok\x22:\x22s4ND7ehgr2lcHpcv5T93UySs4ho\x22,\x22uhde\x22:false}}';google.pmc=JSON.parse(pmc);})();</script>        </body></html>suntongmiandeMacBook-Pro:webrtc suntongmian$
suntongmiandeMacBook-Pro:webrtc suntongmian$

发现可以正常访问 www.google.com 的资源了。

解决了终端的代理问题后,再次执行命令

1
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
1
2
3
4
5
6
7
8
9
10
suntongmiandeMacBook-Pro:webrtc suntongmian$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
正克隆到 'depot_tools'...
remote: Sending approximately 24.21 MiB ...
remote: Total 31833 (delta 22312), reused 31833 (delta 22312)
接收对象中: 100% (31833/31833), 24.21 MiB | 1.25 MiB/s, 完成.
处理 delta 中: 100% (22312/22312), 完成.
suntongmiandeMacBook-Pro:webrtc suntongmian$
suntongmiandeMacBook-Pro:webrtc suntongmian$ ls
depot_tools
suntongmiandeMacBook-Pro:webrtc suntongmian$

到此,可以看到 depot_tools 源码已经下载成功了。

step 2

获取 depot_tools 文件夹所在的目录,在终端执行命令

1
pwd
1
2
3
4
5
6
suntongmiandeMacBook-Pro:webrtc suntongmian$ ls
depot_tools
suntongmiandeMacBook-Pro:webrtc suntongmian$
suntongmiandeMacBook-Pro:webrtc suntongmian$ pwd
/Users/suntongmian/Documents/develop/webrtc
suntongmiandeMacBook-Pro:webrtc suntongmian$

step 3

添加环境变量,命令格式为

1
export PATH=$PATH:/path/depot_tools

其中,path 为上一步通过 pwd 命令获取的 depot_tools 文件夹所在目录。

在终端执行命令

1
export PATH=$PATH:/Users/suntongmian/Documents/develop/webrtc/depot_tools
1
2
suntongmiandeMacBook-Pro:webrtc suntongmian$ export PATH=$PATH:/Users/suntongmian/Documents/develop/webrtc/depot_tools
suntongmiandeMacBook-Pro:webrtc suntongmian$

提示:执行后,只对当前终端起作用。重启终端后,默认失效。

step 4

到此,depot_tools 的配置已经完成。想知道 depot_tools 是否成功安装,在终端执行命令

1
fetch --help
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
suntongmiandeMacBook-Pro:webrtc suntongmian$ fetch --help
usage: fetch.py [options] <config> [--property=value [--property2=value2 ...]]This script can be used to download the Chromium sources. See
http://www.chromium.org/developers/how-tos/get-the-code
for full usage instructions.Valid options:-h, --help, help   Print this message.--nohooks          Don't run hooks after checkout.--force            (dangerous) Don't look for existing .gclient file.-n, --dry-run      Don't run commands, only print them.--no-history       Perform shallow clones, don't fetch the full git history.Valid fetch configs:androidandroid_internalbreakpadchromiumconfig_utilcrashpaddartdepot_toolsgoma_clientgypinfrainfra_internalinspector_protocoliosios_internalnaclnaclportsnode-cipdfiumskiaskia_buildbotsyzygyv8webrtcwebrtc_androidwebrtc_ios
suntongmiandeMacBook-Pro:webrtc suntongmian$

打印上面的信息,说明 depot_tools 工具包已经成功安装。接下来就可以通过 depot_tools 工具下载 WebRTC 源码了。

二、下载 WebRTC 源码

WebRTC 文件量较大,在下载之前,磁盘的剩余可用容量要满足:

Linux: 6.4 GB.
Linux (with Android): 16 GB (of which ~8 GB is Android SDK+NDK images).
Mac (with iOS support): 5.6GB

我使用的是 MacBook Pro 2015款机器:

1
2
3
4
5
6
7
8
9
10
macOS Mojave
版本 10.14.4MacBook Pro (Retina, 13-inch, Early 2015)
处理器 2.7 GHz Intel Core i5
内存 8 GB 1867 MHz DDR3
启动磁盘 Macintosh HD
图形卡 Intel Iris Graphics 6100 1536 MB
磁盘空间 128 GB
可用磁盘空间 17.11 GB

我的 Mac 电脑可用磁盘空间 17.11 GB,是足以装的下 5.6 GB 文件的,好了,接下来就可以放心下载源码了。

step 1

下载所需要的工程,在终端执行命令

1
fetch --nohooks webrtc_ios

在 “安装 depot_tools 工具包” 的步骤中,通过 fetch –help,可以看到代码目录 webrtc,webrtc_android,webrtc_ios 等。我要在 iOS 平台上使用,就选择了 webrtc_ios。选择依据见 WebRTC Native Code, iOS 中提到的 “This will fetch a regular WebRTC checkout with the iOS-specific parts added.”

这条命令执行时,要下载的文件比较多,需要耐心等待命令的执行结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
suntongmiandeMacBook-Pro:webrtc suntongmian$ fetch --nohooks webrtc_ios
Running: gclient root
WARNING: Your metrics.cfg file was invalid or nonexistent. A new one will be created.
Running: gclient config --spec 'solutions = [{"url": "https://webrtc.googlesource.com/src.git","managed": False,"name": "src","deps_file": "DEPS","custom_deps": {},},
]
target_os = ["ios", "mac"]
'
Running: gclient sync --nohooks --with_branch_heads________ running 'git -c core.deltaBaseCacheLimit=2g clone --no-checkout --progress https://webrtc.googlesource.com/src.git /Users/suntongmian/Documents/develop/webrtc/_gclient_src_twA2Fg' in '/Users/suntongmian/Documents/develop/webrtc'
Cloning into '/Users/suntongmian/Documents/develop/webrtc/_gclient_src_twA2Fg'...
remote: Sending approximately 253.71 MiB ...
remote: Counting objects: 22, done
remote: Finding sources: 100% (22/22)
Receiving objects:  57% (183907/320504), 74.04 MiB | 1.88 MiB/s
[0:01:00] Still working on:
[0:01:00]   src
Receiving objects:  60% (192303/320504), 88.48 MiB | 1.35 MiB/s
[0:01:10] Still working on:
[0:01:10]   src...[2:03:36] Still working on:
[2:03:36]   src/third_party/icu[2:03:46] Still working on:
[2:03:46]   src/third_party/icu[2:03:52] Still working on:
[2:03:52]   src/third_party/icu
Syncing projects: 100% (38/38), done.
Running: git submodule foreach 'git config -f $toplevel/.git/config submodule.$name.ignore all'
Running: git config --add remote.origin.fetch '+refs/tags/*:refs/tags/*'
Running: git config diff.ignoreSubmodules all
suntongmiandeMacBook-Pro:webrtc suntongmian$

step 2

与远端 repo 进行代码同步,在终端执行命令

1
gclient sync

这条命令执行时,要下载的文件比较多,需要耐心等待命令的执行结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
suntongmiandeMacBook-Pro:src suntongmian$ gclient sync
Syncing projects: 100% (38/38), done.                                           ________ running '/usr/bin/python src/build/mac_toolchain.py' in '/Users/suntongmian/Documents/develop/webrtc'
Skipping Mac toolchain installation for mac________ running '/usr/bin/python src/tools/clang/scripts/update.py' in '/Users/suntongmian/Documents/develop/webrtc'
Downloading https://commondatastorage.googleapis.com/chromium-browser-clang/Mac/clang-359912-2.tgz
<urlopen error [Errno 54] Connection reset by peer>
Retrying in 5 s ...
Downloading https://commondatastorage.googleapis.com/chromium-browser-clang/Mac/clang-359912-2.tgz Traceback (most recent call last):File "src/tools/clang/scripts/update.py", line 322, in <module>sys.exit(main())File "src/tools/clang/scripts/update.py", line 318, in mainreturn UpdateClang()File "src/tools/clang/scripts/update.py", line 252, in UpdateClangDownloadAndUnpackClangPackage(sys.platform, LLVM_BUILD_DIR)File "src/tools/clang/scripts/update.py", line 171, in DownloadAndUnpackClangPackageDownloadAndUnpack(cds_full_url, output_dir, path_prefix)File "src/tools/clang/scripts/update.py", line 141, in DownloadAndUnpackDownloadUrl(url, f)File "src/tools/clang/scripts/update.py", line 100, in DownloadUrlresponse = urllib.urlopen(url)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopenreturn opener.open(url, data, timeout)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 431, in openresponse = self._open(req, data)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 449, in _open'_open', req)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chainresult = func(*args)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1240, in https_opencontext=self._context)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1194, in do_openh.request(req.get_method(), req.get_selector(), req.data, headers)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1053, in requestself._send_request(method, url, body, headers)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1093, in _send_requestself.endheaders(body)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1049, in endheadersself._send_output(message_body)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 893, in _send_outputself.send(msg)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 855, in sendself.connect()File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1266, in connectHTTPConnection.connect(self)File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 835, in connectself._tunnel()File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 812, in _tunnel(version, code, message) = response._read_status()File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 417, in _read_statusraise BadStatusLine(line)
httplib.BadStatusLine: ''
Error: Command '/usr/bin/python src/tools/clang/scripts/update.py' returned non-zero exit status 1 in /Users/suntongmian/Documents/develop/webrtc
suntongmiandeMacBook-Pro:src suntongmian$

出现了错误 “Error: Command ‘/usr/bin/python src/tools/clang/scripts/update.py’”,暂时不用管,继续后续的步骤。

执行结果中的 src/tools/clang/scripts/update.py, https://commondatastorage.googleapis.com/chromium-browser-clang/Mac/clang-359912-2.tgz 后面的步骤会用到。

三、执行编译

在执行编译前,我们需要配置好编译的参数和环境,生产出构建文件。这里就需要用到 GN 这个工具了。GN 是一个为 Ninja 生成构建文件的元构建系统。Ninja 是一个小型构建系统,特点是构建速度快。

step 1

使用 GN 来生产 Ninja 工程文件,在终端执行命令

1
gn gen out/ios --args='target_os="ios" target_cpu="arm64" is_debug=true'
1
2
3
4
5
6
7
8
9
10
11
suntongmiandeMacBook-Pro:src suntongmian$ gn gen out/ios --args='target_os="ios" target_cpu="arm64" is_debug=true'
Warning: Multiple codesigning identities match "iPhone Developer"
Warning: - D78B0B7AF39CEFA4D0F673B4D3AA517D312C97CC (selected)
Warning: - 5634EAED50D1AD95ED76F6AC8298E06590FE476B
Warning: - 2843CD233EB6A93C79C2332E4F4FC601BEDA13BC
Warning: Please use either ios_code_signing_identity or
Warning: ios_code_signing_identity_description variable to
Warning: control which identity is selected.Done. Made 1378 targets from 189 files in 2200ms
suntongmiandeMacBook-Pro:src suntongmian$

产生的工程文件在目录 /src/out/ios 下。通过命令查看下改目录下有哪些文件,在终端执行命令

1
ls out/ios
1
2
3
4
5
6
7
8
9
suntongmiandeMacBook-Pro:src suntongmian$ ls out/ios
args.gn
build.ninja
build.ninja.d
clang_x64
low_bandwidth_audio_perf_test.runtime_deps
obj
toolchain.ninja
suntongmiandeMacBook-Pro:src suntongmian$

step 2

编译 APP 工程,在终端执行命令

1
ninja -C out/ios AppRTCMobile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
suntongmiandeMacBook-Pro:src suntongmian$ ninja -C out/ios AppRTCMobile
ninja: Entering directory `out/ios'
[1/2732] CXX obj/api/audio_codecs/audio_codecs_api/audio_codec_pair_id.o
FAILED: obj/api/audio_codecs/audio_codecs_api/audio_codec_pair_id.o
../../third_party/llvm-build/Release+Asserts/bin/clang++ -MMD -MF obj/api/audio_codecs/audio_codecs_api/
/bin/sh: ../../third_party/llvm-build/Release+Asserts/bin/clang++: No such file or directory.../bin/sh: ../../third_party/llvm-build/Release+Asserts/bin/clang++: No such file or directory...isystem../../buildtools/third_party/libc++abi/trunk/include -fvisibility-inlines-hidden -Wnon-virtual-dtor -Woverloaded-virtual -c ../../api/audio_codecs/ilbc/audio_encoder_ilbc.cc -o obj/api/audio_codecs/ilbc/audio_encoder_ilbc/audio_encoder_ilbc.o
/bin/sh: ../../third_party/llvm-build/Release+Asserts/bin/clang++: No such file or directory
ninja: build stopped: subcommand failed.
suntongmiandeMacBook-Pro:src suntongmian$

出现错误 “/bin/sh: ../../third_party/llvm-build/Release+Asserts/bin/clang++: No such file or directory”。原因是 /src/third_party/llvm-build 目录下找不到可执行文件 clang++。

先查看 /src/third_party/llvm-build 目录下的文件,在终端执行命令

1
ls third_party/llvm-build
1
2
3
suntongmiandeMacBook-Pro:src suntongmian$ ls third_party/llvm-build
cr_build_revision
suntongmiandeMacBook-Pro:src suntongmian$

发现确实没有可执行文件 clang++。 那就手动下载文件包,放置到对应的目录下。根据 “二、下载 WebRTC 源码”的 step 2 命令执行结果中提到的的下载地址 https://commondatastorage.googleapis.com/chromium-browser-clang/Mac/clang-359912-2.tgz,在终端执行命令

1
curl https://commondatastorage.googleapis.com/chromium-browser-clang/Mac/clang-359912-2.tgz -o third_party/llvm-build/clang.tgz
1
2
3
4
5
suntongmiandeMacBook-Pro:src suntongmian$ curl https://commondatastorage.googleapis.com/chromium-browser-clang/Mac/clang-359912-2.tgz -o third_party/llvm-build/clang.tgz% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100 27.9M  100 27.9M    0     0  1167k      0  0:00:24  0:00:24 --:--:-- 1469k
suntongmiandeMacBook-Pro:src suntongmian$

将下载的 clang.tgz 压缩包解压并根据报错信息重命名为 Release+Asserts,在终端执行命令

1
2
3
ls third_party/llvm-build
mkdir third_party/llvm-build/Release+Asserts
tar zxvf third_party/llvm-build/clang.tgz -C third_party/llvm-build/Release+Asserts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
suntongmiandeMacBook-Pro:src suntongmian$ ls third_party/llvm-build
clang.tgz   cr_build_revision
suntongmiandeMacBook-Pro:src suntongmian$
suntongmiandeMacBook-Pro:src suntongmian$ mkdir third_party/llvm-build/Release+Asserts
suntongmiandeMacBook-Pro:src suntongmian$
suntongmiandeMacBook-Pro:src suntongmian$ tar zxvf third_party/llvm-build/clang.tgz -C third_party/llvm-build/Release+Asserts
x bin/
x bin/clang
x bin/clang++
x bin/clang-cl...x include/c++/v1/ios
x include/c++/v1/iosfwd
x include/c++/v1/iostream...x include/c++/v1/support/android/
x include/c++/v1/support/android/locale_bionic.h...x include/c++/v1/version
x include/c++/v1/wchar.h
x include/c++/v1/wctype.h
suntongmiandeMacBook-Pro:src suntongmian$
suntongmiandeMacBook-Pro:src suntongmian$ ls third_party/llvm-build/Release+Asserts/
bin     buildlog.txt    include     lib
suntongmiandeMacBook-Pro:src suntongmian$
suntongmiandeMacBook-Pro:src suntongmian$ ls third_party/llvm-build/Release+Asserts/bin
clang       clang-cl    llvm-symbolizer
clang++     llvm-pdbutil    llvm-undname
suntongmiandeMacBook-Pro:src suntongmian$

为什么要将下载的 clang.tgz 压缩包解压并根据报错信息重命名为 Release+Asserts 这是依据 “二、下载 WebRTC 源码” 的 step 2 命令执行结果中提到的信息 src/tools/clang/scripts/update.py,在终端执行命令查看该脚本的信息

1
cat tools/clang/scripts/update.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
suntongmiandeMacBook-Pro:src suntongmian$ cat tools/clang/scripts/update.py
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file."""This script is used to download prebuilt clang binaries. It runs as a
"gclient hook" in Chromium checkouts.It can also be run stand-alone as a convenient way of installing a well-tested
near-tip-of-tree clang version:$ curl -s https://raw.githubusercontent.com/chromium/chromium/master/tools/clang/scripts/update.py | python - --clang-dir=.
"""# TODO: Running stand-alone won't work on Windows due to the dia dll copying.from __future__ import print_function... try:import urllib2 as urllib
except ImportError: # For Py3 compatibilityimport urllib.request as urllibimport urllib.error as urllibimport zipfile# Do NOT CHANGE this if you don't know what you're doing -- see
# https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md
# Reverting problematic clang rolls is safe, though.
CLANG_REVISION = '359912'
CLANG_SUB_REVISION = 2PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION)
RELEASE_VERSION = '9.0.0'CDS_URL = os.environ.get('CDS_CLANG_BUCKET_OVERRIDE','https://commondatastorage.googleapis.com/chromium-browser-clang')# Path constants. (All of these should be absolute paths.)
THIS_DIR = os.path.abspath(os.path.dirname(__file__))
CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
LLVM_BUILD_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build','Release+Asserts')STAMP_FILE = os.path.normpath(os.path.join(LLVM_BUILD_DIR, '..', 'cr_build_revision'))
FORCE_HEAD_REVISION_FILE = os.path.normpath(os.path.join(LLVM_BUILD_DIR, '..','force_head_revision'))def DownloadUrl(url, output_file):"""Download url into output_file."""CHUNK_SIZE = 4096TOTAL_DOTS = 10num_retries = 3retry_wait_s = 5  # Doubled at each retry.while True:try:sys.stdout.write('Downloading %s ' % url)sys.stdout.flush()response = urllib.urlopen(url)total_size = int(response.info().getheader('Content-Length').strip())bytes_done = 0dots_printed = 0     ...except urllib.URLError as e:sys.stdout.write('\n')print(e)if num_retries == 0 or isinstance(e, urllib.HTTPError) and e.code == 404:raise enum_retries -= 1print('Retrying in %d s ...' % retry_wait_s)...def DownloadAndUnpack(url, output_dir, path_prefix=None):"""Download an archive from url and extract into output_dir. If path_prefix def DownloadAndUnpackClangPackage(platform, output_dir, runtimes_only=False):cds_file = "clang-%s.tgz" %  PACKAGE_VERSION...def UpdateClang():GCLIENT_CONFIG = os.path.join(os.path.dirname(CHROMIUM_DIR), '.gclient')...DownloadAndUnpackClangPackage(sys.platform, LLVM_BUILD_DIR)...if args.llvm_force_head_revision:print('--llvm-force-head-revision can only be used for --print-revision')return 1if args.clang_dir:global LLVM_BUILD_DIR, STAMP_FILELLVM_BUILD_DIR = os.path.abspath(args.clang_dir)STAMP_FILE = os.path.join(LLVM_BUILD_DIR, 'cr_build_revision')return UpdateClang()if __name__ == '__main__':sys.exit(main())
suntongmiandeMacBook-Pro:src suntongmian$

从该脚本的注释信息 This script is used to download prebuilt clang binaries 可以得知该脚本作用就是下载 clang 可执行文件。其中 clang 的版本信息为 CLANG_REVISION = '359912' CLANG_SUB_REVISION = 2 RELEASE_VERSION = '9.0.0'llvm-build 的目录信息为 LLVM_BUILD_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build', 'Release+Asserts')

再次在终端执行命令

1
ninja -C out/ios AppRTCMobile
1
2
3
4
5
6
7
8
suntongmiandeMacBook-Pro:src suntongmian$ ninja -C out/ios AppRTCMobile
ninja: Entering directory `out/ios'
[2735/2736] CODE SIGNING //examples:Ap...//build/toolchain/mac:ios_clang_arm64)
FAILED: AppRTCMobile.app/AppRTCMobile AppRTCMobile.app/_CodeSignature/CodeResources AppRTCMobile.app/embedded.mobileprovision AppRTCMobile.app/Info.plist
python ../../build/config/ios/codesign.py code-sign-bundle -t=iphoneos -i=D78B0B7AF39CEFA4D0F673B4D3AA517D312C97CC -b=obj/examples/AppRTCMobile -e=../../build/config/ios/entitlements.plist AppRTCMobile.app -P=../../build/config/mac/plist_util.py -p=gen/examples/AppRTCMobile_generate_info_plist.plist -p=gen/examples/AppRTCMobile_partial_info.plist
Error: no mobile provisioning profile found for "com.google.AppRTCMobile".
ninja: build stopped: subcommand failed.
suntongmiandeMacBook-Pro:src suntongmian$

至此,编译 APP 的过程结束了。虽然出现了 “Error: no mobile provisioning profile found for “com.google.AppRTCMobile”.” 的报错,但这并不是太重要,我只关心编译过程的其它环节正确无误。这个 Error 信息表示 APP 的包名 “com.google.AppRTCMobile” 没有与之对应的苹果开发者证书的配置文件,将该 APP 安装到手机上后,会因证书配置文件的问题无法使用。这个问题很好解决,就是改 APP 的包名,在编译的时候选择对应的苹果开发者证书的配置文件后,重新编译就行了。

进入目录 /src/out/ios 可以看下编译后产生了哪些文件。在终端执行命令

1
ls out/ios
1
2
3
4
5
6
7
8
9
10
11
12
13
suntongmiandeMacBook-Pro:src suntongmian$ ls out/ios
AppRTCMobile.app
WebRTC.framework
args.gn
build.ninja
build.ninja.d
clang_x64
gen
low_bandwidth_audio_perf_test.runtime_deps
obj
pyproto
toolchain.ninja
suntongmiandeMacBook-Pro:src suntongmian$

在这一步,其实可以得到我想要的 WebRTC 库文件了,即 WebRTC.framework

step 3

虽然上一步,在编译 WebRTC 的演示 APP 时,可以得到 WebRTC.framework 库文件,但这不是正常获取库文件的路子。编译 WebRTC 库文件的方法有2种,分别为 ninja 命令行,python 脚本。

方法 1

使用 ninja 命令行编译,在终端执行命令

1
ninja -C out/ios framework_objc
1
2
3
4
suntongmiandeMacBook-Pro:src suntongmian$ ninja -C out/ios framework_objc
ninja: Entering directory `out/ios'
ninja: no work to do.
suntongmiandeMacBook-Pro:src suntongmian$

可以看到 “ninja: no work to do.”,为什么会提示这条信息呢?原因在于上一步骤中已经编译产生了 WebRTC.framework 库文件。如果想看看只编译库文件的过程,那可以不执行上一步骤中编译 APP 的环节,即不执行命令 ninja -C out/ios AppRTCMobile,现在的情况是我们已经执行了该条命令,那直接删掉已经存在的 WebRTC.framework 库文件就行了。在终端执行命令

1
rm -rf out/ios/WebRTC.framework
1
2
3
4
5
6
7
8
9
10
11
12
13
14
suntongmiandeMacBook-Pro:src suntongmian$ rm -rf out/ios/WebRTC.framework
suntongmiandeMacBook-Pro:src suntongmian$
suntongmiandeMacBook-Pro:src suntongmian$ ls out/ios
AppRTCMobile.app
args.gn
build.ninja
build.ninja.d
clang_x64
gen
low_bandwidth_audio_perf_test.runtime_deps
obj
pyproto
toolchain.ninja
suntongmiandeMacBook-Pro:src suntongmian$

再次在终端执行命令

1
ninja -C out/ios framework_objc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
suntongmiandeMacBook-Pro:src suntongmian$ ninja -C out/ios framework_objc
ninja: Entering directory `out/ios'
[97/97] STAMP obj/sdk/framework_objc.stamp
suntongmiandeMacBook-Pro:src suntongmian$
suntongmiandeMacBook-Pro:src suntongmian$ ls out/ios
AppRTCMobile.app
WebRTC.framework
args.gn
build.ninja
build.ninja.d
clang_x64
gen
low_bandwidth_audio_perf_test.runtime_deps
obj
pyproto
toolchain.ninja
suntongmiandeMacBook-Pro:src suntongmian$

生成的 WebRTC.framework 库文件在 out/ios 目录下。

方法 2

使用 python 脚本 /src/tools_webrtc/ios/build_ios_libs.py 编译,在终端执行命令

1
python tools_webrtc/ios/build_ios_libs.py --bitcode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
suntongmiandeMacBook-Pro:src suntongmian$ python tools_webrtc/ios/build_ios_libs.py --bitcode
INFO:root:Building WebRTC with args: target_os="ios" ios_enable_code_signing=false use_xcode_clang=true is_component_build=false is_debug=false target_cpu="arm64" ios_deployment_target="10.0" rtc_libvpx_build_vp9=false enable_ios_bitcode=true use_goma=false enable_stripping=true
Done. Made 1376 targets from 189 files in 1727ms
INFO:root:Building target: framework_objc
ninja: Entering directory `/Users/suntongmian/Documents/develop/webrtc/src/out_ios_libs/arm64_libs'
[2614/2614] STAMP obj/sdk/framework_objc.stamp
INFO:root:Building WebRTC with args: target_os="ios" ios_enable_code_signing=false use_xcode_clang=true is_component_build=false is_debug=false target_cpu="arm" ios_deployment_target="10.0" rtc_libvpx_build_vp9=false enable_ios_bitcode=true use_goma=false enable_stripping=true
Done. Made 1377 targets from 189 files in 1953ms
INFO:root:Building target: framework_objc
ninja: Entering directory `/Users/suntongmian/Documents/develop/webrtc/src/out_ios_libs/arm_libs'
[2656/2656] STAMP obj/sdk/framework_objc.stamp
INFO:root:Building WebRTC with args: target_os="ios" ios_enable_code_signing=false use_xcode_clang=true is_component_build=false is_debug=false target_cpu="x64" ios_deployment_target="10.0" rtc_libvpx_build_vp9=false enable_ios_bitcode=true use_goma=false enable_stripping=true
Done. Made 1402 targets from 192 files in 5101ms
INFO:root:Building target: framework_objc
ninja: Entering directory `/Users/suntongmian/Documents/develop/webrtc/src/out_ios_libs/x64_libs'
[2777/2777] STAMP obj/sdk/framework_objc.stamp
INFO:root:Building WebRTC with args: target_os="ios" ios_enable_code_signing=false use_xcode_clang=true is_component_build=false is_debug=false target_cpu="x86" ios_deployment_target="10.0" rtc_libvpx_build_vp9=false enable_ios_bitcode=true use_goma=false enable_stripping=true
Done. Made 1402 targets from 192 files in 1754ms
INFO:root:Building target: framework_objc
ninja: Entering directory `/Users/suntongmian/Documents/develop/webrtc/src/out_ios_libs/x86_libs'
[2771/2771] STAMP obj/sdk/framework_objc.stamp
INFO:root:Merging framework slices.
INFO:root:Done.
suntongmiandeMacBook-Pro:src suntongmian$
suntongmiandeMacBook-Pro:src suntongmian$ ls out_ios_libs
WebRTC.framework    arm_libs        x86_libs
arm64_libs      x64_libs
suntongmiandeMacBook-Pro:src suntongmian$

生成的库文件在 out_ios_lib 目录下。脚本 tools_webrtc/ios/build_ios_libs.py 默认编译的架构是 DEFAULT_ARCHS = ENABLED_ARCHS = ['arm64', 'arm', 'x64', 'x86'],编译出来的库为动态库。查看库支持的架构,以及是静态库还是动态库,在终端执行命令

1
2
lipo -info out_ios_libs/WebRTC.framework/WebRTC
file out_ios_libs/arm64_libs/WebRTC.framework/WebRTC
1
2
3
4
5
6
7
8
9
10
suntongmiandeMacBook-Pro:src suntongmian$ lipo -info out_ios_libs/WebRTC.framework/WebRTC
Architectures in the fat file: out_ios_libs/WebRTC.framework/WebRTC are: x86_64 i386 armv7 arm64
suntongmiandeMacBook-Pro:src suntongmian$
suntongmiandeMacBook-Pro:src suntongmian$ file out_ios_libs/WebRTC.framework/WebRTC
out_ios_libs/WebRTC.framework/WebRTC: Mach-O universal binary with 4 architectures: [x86_64:Mach-O 64-bit dynamically linked shared library x86_64] [arm64]
out_ios_libs/WebRTC.framework/WebRTC (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
out_ios_libs/WebRTC.framework/WebRTC (for architecture i386):   Mach-O dynamically linked shared library i386
out_ios_libs/WebRTC.framework/WebRTC (for architecture armv7):  Mach-O dynamically linked shared library arm_v7
out_ios_libs/WebRTC.framework/WebRTC (for architecture arm64):  Mach-O 64-bit dynamically linked shared library arm64
suntongmiandeMacBook-Pro:src suntongmian$

提示:使用了动态库的 APP 在上架 APP Store 时,会报错不支持模拟器架构 ['x64', 'x86'],所以,需要剔除动态库中的模拟器架构,只使用真机架构 [‘arm64’, ‘arm’]。

可以修改脚本 tools_webrtc/ios/build_ios_libs.py 中的参数,将编译的架构改成 DEFAULT_ARCHS = ENABLED_ARCHS = ['arm64']。为什么去掉了 arm?因为现在人们使用的苹果设备几乎都是 arm64 架构了,arm 架构的苹果设备几乎绝迹,去掉 arm,也可以减轻 WebRTC 库的体积。

四、总结

编译 WebRTC 库的步骤就那么几步,但实际我们在编译的过程中会遇到各种各样的问题,看似简单的事情变得很是折磨人。出现问题并不可怕,根据报错的信息,耐心仔细检查、搜集资料、寻求帮助、反复尝试,是可以解决问题的。解决问题的过程中,切忌浮躁,没有一个平稳的心态,事情会变得一波多折。

本文篇幅很长,详细记录了每一步操作,可以方便自己以后回顾,也能给看该文的同行一些启发。为方便浏览,总结编译步骤如下:

第一步:安装 depot_tools,配置环境变量

1
2
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=$PATH:/Users/suntongmian/Documents/develop/webrtc/depot_tools

第二步:下载 WebRTC 源码

1
2
fetch --nohooks webrtc_ios
gclient sync

第三步:编译 WebRTC

方法 1

1
2
gn gen out/ios --args='target_os="ios" target_cpu="arm64" is_debug=true'
ninja -C out/ios framework_objc

方法 2

1
2
gn gen out/ios --args='target_os="ios" target_cpu="arm64" is_debug=true'
python tools_webrtc/ios/build_ios_libs.py --bitcode

WebRTC 开发(二)源码下载与编译相关推荐

  1. 从零开始成为GStreamer专家——基于Windows的GStreamer从源码下载、编译到开发

    基于Windows的GStreamer从源码下载.编译到开发 本文介绍了在GStreamer下载方法, 使用过程中的部分依赖,以及在Windows上编译配置GStreamer 过程,为学习GStrea ...

  2. WebRTC源码下载与编译

    WebRTC源码编译 1 几种源码下载方案对比 1.1 拉别人下好的代码 1.2云服务器 1.3 国内镜像 1.4 挂代理(推荐) 2 源码编译环境准备 2.1 环境要求 2.2 代理服务器配置 2. ...

  3. VLC for Android源码下载和编译

    Project Hosting on 点击打开链接 最受欢迎的开源项目 点击打开链接 由Android的核心开发团队提供了15个优秀的示例项 目,包含了游戏.图像处理.时间显示.开始菜单快捷方式等. ...

  4. Android12 源码下载、编译、刷机、单编调试Framework

    文章目录 说明 1. 代码下载 1.1 下载Repo工具 1.2 安装和配置Git 1.3 创建工程目录 1.4 初始化Repo仓库 1.5 同步代码 2. 驱动下载 2.1 下载对应机型的驱动 2. ...

  5. 《深入理解Android内核设计思想(第2版)(上下册)》之Android源码下载及编译

    本文摘自人民邮电出版社异步社区<深入理解Android内核设计思想(第2版)(上下册)> 购书地址:http://item.jd.com/12212640.html 试读地址:http:/ ...

  6. 《深入理解Android内核设计思想(第2版)(上下册)》之Android源码下载及编译...

    本文摘自人民邮电出版社异步社区<深入理解Android内核设计思想(第2版)(上下册)> 购书地址:item.jd.com/12212640.ht- 试读地址:www.epubit.com ...

  7. SELinux零知识学习四、Audit应用层源码下载、编译和安装

    接前一篇文章:SELinux零知识学习三.SELinux应用层源码下载.编译和安装 在前篇文章中编译SELinux源码时,出现了如下错误: seusers_local.c:11:10: 致命错误:li ...

  8. Centos7下RTL8188eu USB无线网卡(TP WN725N) 驱动源码下载和编译步骤

    Centos7下RTL8188eu USB无线网卡TP WN725N 驱动源码下载和编译步骤 一 准备编译环境 二 下载源代码 三 编译和安装 四 启用8188euko Centos7下RTL8188 ...

  9. 新版SQLite源码下载与编译

    概述 "最新版GDAL源码下载 "一文中,我们为大家分享了最新版本的GDAL源码,而GDAL是需要依赖PROJ投影转换库的. 因此,在最新版投影转换工具PROJ源码 "一 ...

最新文章

  1. Scrum项目1.0
  2. spring4声明式事务--01注解方式
  3. dos批处理命令详解
  4. Sonya and Informatics
  5. java list过滤完赋给自己_Java8对list集合进行排序、过滤、分组、去重、转map、遍历赋值等操作...
  6. idea打印sql的插件_[Mybatis]-[基础支持层]-插件-自定义简易SQL打印插件
  7. 计算机导论sql试题,sql语句查询 练习题
  8. 初步使用github,并上传下载文件
  9. 将游戏成绩传到排名页面html,用野狗开发实时游戏排行榜
  10. UMEditor调整文本编辑器的组件位置的方法
  11. Repeater内部排序
  12. Java与微信不得不说的故事——消息的接收与发送
  13. 理解Java虚拟机体系结构
  14. 《数据结构题集(C语言版)》第2章(线性表)习题自解答
  15. 电子专业的学生必看的文章
  16. html是什么简答题,网页设计与制作简答题.doc
  17. 微信公众平台开发教程第20篇-新手解惑40则
  18. YC2440+wiggler小板+H-JATG+PCI转并口卡开发环境的搭建
  19. 如何学习 C++ 如何学习一门较复杂的编程语言 【转】
  20. uniapp简单搞定支付传统的开发支付需要前后端做很多工作,各种参数的处理,签名,秘钥的验证校验等,尤其是涉及到多种不同的平台支付,更是繁琐;而且以往的支付是由后端主导的,如果后端是个菜鸡,那么做这

热门文章

  1. 使用Selenium中的webdriver出现浏览器闪退的原因
  2. oracle中member,Oracle数据库通过定义TYPE及Member对象来实现日志信息的分级管理
  3. php表白情话,表白情话短语 美到哭五个字
  4. python colorbar范围_python – colorbar中的奇怪范围值,matplotlib
  5. Spring项目log4j配置
  6. CC2530之按键与LED
  7. activemq搭建MQTT服务器
  8. C语言实现扫雷 附带源代码
  9. linux重要开源软件
  10. 中国石化竞得首批页岩气矿业权