# 怎么读这套源码 · 构建、约定与按图索骥

> 导论收尾，给一套实用的「读码方法论」：怎么拿到并构建（其实你不必构建）、header guard 与线程注解等路标、.h/.cc/_unittest.cc/BUILD.gn/g3doc 的分工、abseil 与引用计数等风格约定，以及怎么对照本教程按图索骥地读下去。

- 作者：David（道雾轩）
- 专栏：音视频与 WebRTC 详解（https://daiw.org/manual/webrtc.md）
- 最后更新：2026-07-14
- 原文：https://daiw.org/manual/webrtc/reading-the-source
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 怎么读这套源码 · 构建、约定与按图索骥

导论的最后一章，不讲架构，讲**方法**：面对 5000 多个文件，怎么高效地读进去、怎么跟着本教程按图索骥。掌握这套约定，后面 100 多篇你都能对着真实源码逐行印证。

## 拿到源码（你其实不必构建）

WebRTC 用 Google 的 **depot_tools** 拉取，`gclient` 管理依赖：

```bash
fetch --nohooks webrtc      # 拉取源码(很大,含第三方依赖)
gclient sync                # 同步依赖
```

构建用 **GN + Ninja**（根目录有 `.gn` 与 `BUILD.gn` 为证）：

```bash
gn gen out/Default          # GN 生成 Ninja 构建文件
ninja -C out/Default        # Ninja 编译
```

<Callout type="info">
  **好消息：跟本教程，你完全不必构建 WebRTC。** 它的完整构建很重（拉取几个 GB、编译半天）。我们的目的是**读懂它怎么设计与实现**，而读源码只需要一份源码树 + 一个能跳转的编辑器 / 代码搜索。想动手实验的读者再去构建不迟；只想读懂的，把源码摊开对照即可。
</Callout>

## 三个路标（复习）

读 WebRTC，先认这三个反复出现的路标——它们是[前几章](https://daiw.org/manual/webrtc/source-map)埋下的：

1. **header guard = canonical 路径**：`#ifndef MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_` 直接告诉你这文件的规范路径。本教程的路径都按此写。
2. **线程注解 = 谁在哪跑**：`RTC_DCHECK_RUN_ON(线程)` 和 `RTC_GUARDED_BY(线程)` 一眼标出[线程归属](https://daiw.org/manual/webrtc/threading-model)。读一个函数前先扫一眼它的注解。
3. **命名 = 角色**：`XxxInterface`（契约，在 `api/`）/ `XxxProxy`（[转发线程](https://daiw.org/manual/webrtc/proxy-pattern)）/ `Xxx`（实现）；还有 `XxxFactory`（工厂）、`XxxObserver`（回调）。看名字就知道它在架构里的位置。

## 五种文件，各司其职

一个模块目录里，文件按后缀分工清晰：

| 文件 | 是什么 | 怎么用 |
| --- | --- | --- |
| `xxx.h` | **接口 / 声明** | 想知道「这个类能干什么」，读它 |
| `xxx.cc` | **实现** | 想知道「具体怎么干」，读它 |
| `xxx_unittest.cc` | **单元测试**（全库 900+ 个） | 想知道「怎么用、边界行为」，读它 |
| `BUILD.gn` | **构建目标与依赖**（全库 140+ 个） | 想知道「这模块依赖谁、被谁用」，读它 |
| `g3doc/*.md` | **架构文档**（十多个模块自带） | **先读它**，再读代码 |

<Callout type="info">
  **两个高价值、却常被忽略的读码入口：单元测试与 g3doc。**

  - **单元测试（`_unittest.cc`）是最好的「用法说明书」**。全库有 **900 多个**。一个类怎么构造、怎么调、在边界情况下期望什么行为——测试里写得明明白白，还保证是**最新、可运行**的。读不懂一个类的契约时，翻它的测试往往比读实现更快。
  - **模块自带的 `g3doc/` 是最好的「设计导览」**。`modules/audio_coding/neteq/g3doc/`、`modules/rtp_rtcp/g3doc/`、`p2p/`、`pacing/`…… 十多个核心模块**自带架构文档**。它们由模块作者维护，讲清「为什么这么设计」。**读一个新模块，先找它的 g3doc**——本教程也大量以它们为纲。
</Callout>

## 几条风格约定

WebRTC 有自己的 C++ 风格（`style-guide.md`、`abseil-in-webrtc.md`），读代码前知道几条能少踩坑：

- **不用 C++ 异常**。错误靠返回值传递——你会常见 `RTCError`、`RTCErrorOr<T>`（要么带值、要么带错误）。断言用 `RTC_CHECK`（release 也检查、失败即崩）和 `RTC_DCHECK`（仅 debug 检查）。
- **引用计数管理生命周期**。跨线程共享的对象多是引用计数的，用 `scoped_refptr<T>` 持有（类似 `shared_ptr`）。`g3doc/peer_connection.md` 里 `ConnectionContext` 就是「只要工厂或任一 PeerConnection 还在用，它就活着」——这正是引用计数的语义。
- **精选的 abseil 工具**。`abseil-in-webrtc.md` 列出允许用的 absl 类型，如 `absl::AnyInvocable`（可移动的函数包装）、`absl::InlinedVector`（小尺寸内联的 vector）、`absl::Cleanup`（作用域退出时执行）等。见到 `absl::` 前缀不必慌，它们都是标准库的增强版。
- **`api/` 是稳定契约，其余可变**。跨版本读代码时，`api/` 的接口相对稳定，实现细节则常重构——[对照本教程](https://daiw.org/manual/webrtc/source-map)时若发现某实现类改了名，先从 `api/` 的接口和 g3doc 找回主线。

## 怎么对照本教程读

给一套可复用的「读码配方」。本教程每讲一个组件，都会给出它的 **canonical 路径 + 类名 + 关键函数**。拿到后：

1. **先读 g3doc**（若该模块有）——把握设计意图与全景。
2. **再读 `.h`**——看接口：这个类对外承诺了什么，成员上的[线程注解](https://daiw.org/manual/webrtc/threading-model)说明它活在哪条线程。
3. **然后读 `.cc` 的关键函数**——本教程会点名是哪几个，顺着[数据流](https://daiw.org/manual/webrtc/call-lifecycle)读，别一头扎进细节。
4. **卡壳了翻 `_unittest.cc`**——看它怎么被构造和调用，契约立刻清晰。

源码可在 `webrtc.googlesource.com/src/` 浏览，或用 Chromium 代码搜索 `source.chromium.org`（路径前缀 `third_party/webrtc/`）——支持全局跳转，读 WebRTC 极其顺手。

## 小结与下一部分

读 WebRTC 的方法论：**不必构建**（读懂即可）；认准三个路标（**header guard = 路径**、**线程注解 = 归属**、**命名 = 角色**）；用好五种文件（`.h` 看接口、`.cc` 看实现、**`_unittest.cc` 看用法**、`BUILD.gn` 看依赖、**`g3doc` 看设计**）；记住几条风格（无异常、`RTCErrorOr`、`scoped_refptr` 引用计数、精选 abseil）。对照本教程时，按「g3doc → `.h` → `.cc` 关键函数 → 单测」的顺序读。

**导论与全景到此结束**——你已经有了 WebRTC 的[全局观](https://daiw.org/manual/webrtc/what-is-webrtc)、[源码地图](https://daiw.org/manual/webrtc/source-map)、[通话流程](https://daiw.org/manual/webrtc/call-lifecycle)、[线程模型](https://daiw.org/manual/webrtc/threading-model)与[代理机制](https://daiw.org/manual/webrtc/proxy-pattern)，以及这套读码方法论。接下来，我们正式潜入第一个子系统——**PeerConnection 与会话建立**：从工厂造出连接，到 SDP 提议 / 应答如何把一次通话协商出来。（第 1 部分陆续更新。）

## 参考资料

- [1] libwebrtc 源码.`style-guide.md`、`abseil-in-webrtc.md`、`native-api.md`（编码风格与 API 约定）。
- [2] libwebrtc 源码.各模块 `g3doc/` 与 900+ `_unittest.cc`（设计文档与用法示例）。
- [3] WebRTC 项目.「Getting Started / depot_tools / GN build」https://webrtc.googlesource.com/src/+/main/docs/native-code/
