WebRTC 外部 OpenSSL 构建指南
本指南详细说明如何构建使用外部 OpenSSL 库而非 BoringSSL 的 WebRTC 库,适用于 macOS 15.0 环境。
概述
WebRTC 默认使用 BoringSSL 作为 SSL/TLS 库,但在某些场景下需要使用外部 OpenSSL 库。本指南解决了以下问题:
- macOS 15.0 兼容性问题
- 桌面捕获 API 废弃问题
- BoringSSL 与外部 OpenSSL 的符号冲突问题
- gRPC 依赖导致的 BoringSSL 强制链接问题
环境要求
- macOS 15.0+
- Xcode 16.0+
- WebRTC 源码
- 外部 OpenSSL 库(针对 macOS 15.0 编译)
步骤详解
1. 切换 WebRTC 分支
选择支持 macOS 15.0 的 WebRTC 分支:
bash
cd /path/to/webrtc/src
git checkout branch-heads/7381
export PATH="$PWD/../depot_tools:$PATH"
gclient sync
说明:
branch-heads/6477不支持 macOS 15.0branch-heads/7381包含了 macOS 15.0 的支持补丁- 更高版本如
branch-heads/7432也可以使用
2. 修改 WebRTC 源码文件
2.1 禁用桌面捕获功能
编辑 src/webrtc.gni 文件:
gn
# 原代码(第 340-342 行):
# Desktop capturer is supported only on Windows, OSX and Linux.
rtc_desktop_capture_supported =
(is_win && current_os != "winuwp") || is_mac ||
((is_linux || is_chromeos) && (rtc_use_x11_extensions || rtc_use_pipewire))
# 修改为:
# Desktop capturer is supported only on Windows, OSX and Linux.
# Force disable desktop capture for macOS 15.0 compatibility
rtc_desktop_capture_supported = false
原因: macOS 15.0 废弃了桌面捕获相关的 Core Graphics API,强制禁用可避免编译错误。
2.2 添加外部 OpenSSL 库路径支持
编辑 src/BUILD.gn 文件,在第 508 行添加:
gn
# 原代码:
declare_args() {
rtc_ssl_lib_path = ""
}
if (!rtc_build_ssl) {
config("external_ssl_library") {
if (rtc_ssl_root != "") {
include_dirs = [ rtc_ssl_root ]
}
if (rtc_ssl_lib_path != "") {
libs = [
rtc_ssl_lib_path + "/libcrypto.a",
rtc_ssl_lib_path + "/libssl.a",
]
} else {
libs = [
"crypto",
"ssl",
]
}
}
}
说明:
- 添加了
rtc_ssl_lib_path参数声明 - 当指定库路径时,直接链接静态库文件
- 否则使用系统默认的动态链接方式
3. 配置构建脚本
创建或修改 build_webrtc_macos_arm64.sh 脚本:
bash
#!/bin/bash
# WebRTC macOS ARM64 构建脚本
# 使用方法: ./build_webrtc_macos_arm64.sh
set -e
echo "开始构建 WebRTC macOS ARM64 版本..."
# 检查是否在正确的目录
if [ ! -d "src" ]; then
echo "错误: 请在 webrtc 目录下运行此脚本"
exit 1
fi
# 设置环境变量
export PATH="$PWD/depot_tools:$PATH"
# 进入源码目录
cd src
# 清理之前的构建
echo "清理之前的构建..."
# rm -rf out/Release
# 生成构建配置
echo "生成构建配置..."
gn gen out/Release --args='
is_debug = false
is_component_build = false
rtc_use_h264 = true
ffmpeg_branding = "Chrome"
use_custom_libcxx = false
use_custom_libcxx_for_host = false
libcxx_is_shared = false
rtc_include_tests = false
rtc_build_examples = false
target_os = "mac"
target_cpu = "arm64"
mac_deployment_target = "15.0"
rtc_include_pulse_audio = false
rtc_use_x11 = false
rtc_use_dummy_audio_file_devices = true
rtc_include_desktop_capture = false
rtc_desktop_capture_supported = false
rtc_include_internal_audio_device = false
use_rtti = true
symbol_level=2
# 禁用 gRPC 来避免 BoringSSL 依赖
rtc_enable_grpc = false
# SSL 配置 - 使用 OpenSSL 而不是 BoringSSL
rtc_build_ssl = false
rtc_ssl_root = "xxx/third_party/openssl/include"
rtc_builtin_ssl_root_certificates = true
# libsrtp SSL 配置 - 与 WebRTC 保持一致
libsrtp_build_boringssl = false
libsrtp_ssl_root = "xxx/third_party/openssl/include"
# 忽略 OpenSSL 3.0 废弃函数警告
treat_warnings_as_errors = false
# OpenSSL 库路径 - WebRTC 会自动处理链接
rtc_ssl_lib_path = "xxx/openssl/lib/macosx/arm64"
'
# 开始编译
echo "开始编译 WebRTC..."
ninja -C out/Release
echo "编译完成!"
echo "库文件位置: out/Release/obj/libwebrtc.a"
echo "头文件位置: src/"
4. 关键配置参数说明
4.1 SSL 相关配置
| 参数 | 值 | 说明 |
|---|---|---|
rtc_build_ssl |
false |
禁用 WebRTC 内置的 BoringSSL |
rtc_ssl_root |
外部 OpenSSL include 路径 | 指定 OpenSSL 头文件路径 |
rtc_ssl_lib_path |
外部 OpenSSL lib 路径 | 指定 OpenSSL 库文件路径 |
libsrtp_build_boringssl |
false |
禁用 libsrtp 的 BoringSSL |
libsrtp_ssl_root |
外部 OpenSSL include 路径 | libsrtp 使用的 SSL 头文件路径 |
4.2 兼容性配置
| 参数 | 值 | 说明 |
|---|---|---|
mac_deployment_target |
"15.0" |
匹配 OpenSSL 编译目标 |
rtc_include_desktop_capture |
false |
禁用桌面捕获功能 |
rtc_desktop_capture_supported |
false |
强制禁用桌面捕获支持 |
treat_warnings_as_errors |
false |
忽略 OpenSSL 3.0 废弃警告 |
4.3 依赖控制配置
| 参数 | 值 | 说明 |
|---|---|---|
rtc_enable_grpc |
false |
关键: 禁用 gRPC 避免 BoringSSL 依赖 |
rtc_include_tests |
false |
禁用测试以减少依赖 |
rtc_build_examples |
false |
禁用示例以减少依赖 |
5. 问题解决方案详解
5.1 BoringSSL 冲突问题
问题: 即使设置 rtc_build_ssl = false,WebRTC 仍然链接 BoringSSL,导致符号冲突。
根因: gRPC 组件硬编码依赖于 BoringSSL,无法通过 SSL 配置参数禁用。
解决方案: 设置 rtc_enable_grpc = false 完全禁用 gRPC 组件。
5.2 macOS 15.0 API 废弃问题
问题: 桌面捕获模块使用的 Core Graphics API 在 macOS 15.0 中被废弃。
解决方案:
- 修改
webrtc.gni强制设置rtc_desktop_capture_supported = false - 构建脚本中设置
rtc_include_desktop_capture = false
5.3 OpenSSL 库路径问题
问题: WebRTC 的 external_ssl_library 配置只支持头文件路径,不支持库文件路径。
解决方案:
- 在
BUILD.gn中添加rtc_ssl_lib_path参数支持 - 直接指定
.a静态库文件的完整路径
6. 验证构建结果
6.1 检查库文件
bash
ls -la out/Release/obj/libwebrtc.a
# 应该显示约 400MB 的库文件
6.2 检查 BoringSSL 依赖
bash
# 检查是否还有 BoringSSL 依赖(应该返回空或错误)
gn refs out/Release //third_party/boringssl
# 检查库中的 SSL 符号(应该只有未定义的外部引用)
nm out/Release/obj/libwebrtc.a | grep SSL_ctrl
# 应该显示 "U _SSL_ctrl"(U 表示未定义,需要外部链接)
6.3 检查目标数量
成功的构建应该显示:
csharp
Done. Made 2121 targets from 334 files
而不是包含 gRPC 的版本:
csharp
Done. Made 2271 targets from 363 files
7. 目录结构要求
bash
webrtc/
├── depot_tools/ # WebRTC 构建工具
├── src/ # WebRTC 源码
│ ├── webrtc.gni # 需要修改
│ └── BUILD.gn # 需要修改
└── build_webrtc_macos_arm64.sh # 构建脚本
third_party/openssl/
├── include/
│ └── openssl/ # OpenSSL 头文件
│ ├── ssl.h
│ └── crypto.h
└── lib/macosx/arm64/
├── libssl.a # SSL 静态库
└── libcrypto.a # Crypto 静态库
8. 常见问题与解决方案
Q1: 构建时仍然出现 BoringSSL 符号冲突
A: 确保 rtc_enable_grpc = false 已正确设置,并且清理了之前的构建缓存。
Q2: 找不到 OpenSSL 头文件
A: 检查 rtc_ssl_root 路径是否正确指向 OpenSSL 的 include 目录。
Q3: 链接时找不到 OpenSSL 库文件
A: 确保 rtc_ssl_lib_path 路径正确,且库文件存在。
Q4: macOS 版本兼容性问题
A: 确保 mac_deployment_target 与 OpenSSL 库的编译目标版本一致。
9. 构建验证清单
- WebRTC 分支已切换到 7381 或更高版本
-
webrtc.gni中rtc_desktop_capture_supported已强制设为false -
BUILD.gn中已添加rtc_ssl_lib_path参数支持 - 构建脚本中已设置
rtc_enable_grpc = false - OpenSSL 头文件和库文件路径正确
- 构建成功且目标数量为 2121 个(不包含 gRPC)
- 生成的
libwebrtc.a大小约 400MB - 库中只包含 OpenSSL 的外部符号引用,无 BoringSSL 实现
10. 技术细节
10.1 WebRTC SSL 配置机制
WebRTC 通过以下机制处理 SSL 库:
rtc_build_ssl = true:使用内置 BoringSSLrtc_build_ssl = false:使用外部 SSL 库external_ssl_library配置:处理外部 SSL 的头文件和库文件
10.2 gRPC 依赖分析
gRPC 组件的依赖关系:
bash
rtc_tools/data_channel_benchmark → gRPC → BoringSSL
即使设置 rtc_build_ssl = false,gRPC 仍然会强制链接 BoringSSL。
10.3 构建目标分析
- 启用 gRPC:2271 个构建目标
- 禁用 gRPC:2121 个构建目标
- 差异:150 个目标(主要是 gRPC 相关组件)
11. 故障排除
11.1 符号冲突问题
如果遇到类似错误:
shell
duplicate symbol: CRYPTO_malloc
>>> defined in obj/third_party/boringssl/libboringssl.a(mem.o)
>>> defined in /path/to/openssl/lib/libcrypto.a(mem.o)
解决方案: 检查 rtc_enable_grpc 是否已设为 false。
11.2 API 废弃警告
如果遇到类似错误:
csharp
error: 'CGDisplayCreateImage' is deprecated
解决方案: 确保桌面捕获功能已完全禁用。
12. 最终配置总结
关键的 GN 构建参数配置:
gn
# 基础配置
is_debug = false
is_component_build = false
target_os = "mac"
target_cpu = "arm64"
mac_deployment_target = "15.0"
# 功能禁用
rtc_include_tests = false
rtc_build_examples = false
rtc_include_desktop_capture = false
rtc_include_internal_audio_device = false
rtc_enable_grpc = false # 关键:避免 BoringSSL
# SSL 配置
rtc_build_ssl = false # 禁用内置 BoringSSL
rtc_ssl_root = "/path/to/openssl/include" # OpenSSL 头文件路径
rtc_ssl_lib_path = "/path/to/openssl/lib" # OpenSSL 库文件路径
# libsrtp 配置
libsrtp_build_boringssl = false
libsrtp_ssl_root = "/path/to/openssl/include"
# 其他
treat_warnings_as_errors = false
use_rtti = true
这个配置确保 WebRTC 完全使用外部 OpenSSL 库,不包含任何 BoringSSL 代码。
附录:Demo 编译兼容性修复
如果您有现有的 WebRTC demo 代码,可能需要进行以下 API 兼容性修复:
A.1 命名空间变化
在新版本的 WebRTC 中,很多类型从 rtc 命名空间移动到了 webrtc 命名空间:
cpp
// 旧版本 (6477 及更早)
rtc::scoped_refptr<webrtc::RTCStatsReport>
rtc::Thread::Create()
rtc::LogMessage::LogToDebug()
rtc::make_ref_counted<>()
// 新版本 (7381 及以后)
webrtc::scoped_refptr<webrtc::RTCStatsReport>
webrtc::Thread::Create()
webrtc::LogMessage::LogToDebug()
webrtc::make_ref_counted<>()
A.2 必需的头文件
对于 demo 编译,需要添加以下头文件:
cpp
#include "api/video_codecs/video_codec.h" // 视频编解码器常量
#include "modules/video_coding/include/video_error_codes.h" // 错误码
#include "api/scoped_refptr.h" // scoped_refptr
#include "api/make_ref_counted.h" // make_ref_counted
#include "api/media_types.h" // MediaType::VIDEO
A.3 CMakeLists.txt 配置
Demo 的 CMakeLists.txt 需要正确链接 OpenSSL 库:
cmake
target_link_libraries(your_demo
webrtc
# 必须链接外部 OpenSSL 库
/path/to/openssl/lib/macosx/arm64/libssl.a
/path/to/openssl/lib/macosx/arm64/libcrypto.a
# 其他库...
)
A.4 编译验证
成功编译后,demo 可执行文件应该:
- 大小约 16MB
- 架构为 arm64
- 能够正常运行
最后更新: 2025年9月26日
WebRTC 版本: branch-heads/7381
适用平台: macOS 15.0+ ARM64
状态: ✅ 完全测试通过 - WebRTC 库和 demo 都成功编译