System & Services 进阶 20m
认识可合并库
Meet mergeable libraries
2023年6月5日
一句话判断
Mergeable Libraries 让你同时获得动态库的构建速度和静态库的启动性能——Xcode 15 中一个 Build Setting 就能开启自动合并,把多个嵌入框架合并到 App 二进制中,减少 dyld 加载时间。
这场 Session 讲了什么
Session 介绍了 Xcode 15 中全新的 Mergeable Libraries 机制。
背景问题:
- 静态库:构建时复制代码到 App 二进制,启动快但构建慢(代码变更触发重新链接)。
- 动态库:构建时只记录路径,启动时 dyld 加载,构建快但启动慢(框架越多越慢)。
- 之前需要在这两者之间权衡测量。
Mergeable Libraries 的方案:
- 动态库构建时生成额外元数据(metadata),使链接器可以像静态库一样处理它们。
- 合并时链接器去重:消除冗余符号引用、Objective-C 选择器、objc_msgSend 桩代码。
- 最终输出是一个包含所有库段的单一二进制——启动时只需加载一个库。
- 保留了开发时的模块化优势(代码分离、独立编译),同时获得运行时的合并性能。
两种启用方式:
- 自动合并(Automatic Merging):一个 Build Setting 开关,自动合并所有直接依赖的嵌入框架。适合 App 目标。
- 手动合并(Manual Merging):精确控制哪些库合并、合并到哪里。适合需要精确控制的场景。
Debug 模式优化:
- Debug 模式下保持动态链接行为(构建速度快)。
- Release 模式下执行合并(启动性能好)。
- 调试和符号化完整支持。
值得深挖的点
**合并时的去重(De-duplication)**是性能提升的核心来源。当多个框架包含相同的字符串常量、符号引用或 Objective-C 选择器时,链接器只保留一份。对大型项目(几十个框架)来说,这种去重可以显著减少 App 包大小和内存占用。
Debug/Release 的自动切换消除了开发体验和用户性能之间的矛盾。Debug 模式下框架仍然是独立的动态库,增量构建速度快。Release 模式下自动合并为单一二进制,启动时 dyld 加载的框架数量大幅减少。开发者不需要维护两套配置。
导出符号的保留意味着合并后的库仍然可以导出符号,保持框架的公共 API 可用性。这对需要跨模块访问框架 API 的场景(如插件架构)很重要。
代码片段
启用自动合并(Xcode Build Setting):
// 在 Xcode 中:
// 1. 选择 App 目标
// 2. Build Settings 标签
// 3. 搜索 "Create Merged Binary" (MERGED_BINARY_TYPE)
// 4. 设置为 "Automatic"
// 效果:所有直接依赖的嵌入框架自动合并到 App 二进制中
// App 启动时不需要单独加载这些框架
手动合并配置:
// 手动控制哪些库合并、合并到哪里
// 步骤1:将库构建为 mergeable
// 在框架目标的 Build Settings 中:
// MERGEABLE_LIBRARY = YES
// 这会让链接器在库中生成元数据
// 步骤2:在目标二进制中合并指定库
// 在 App 目标的 Build Settings 中:
// MERGED_BINARY_TYPE = "Manual"
// 然后指定要合并的框架
// 底层链接器选项(Xcode 自动处理):
// -make_mergeable → 为库生成元数据
// -merge_library → 合并指定库
// -merge_framework → 合并指定框架
框架合并策略:
// 合并前:App 依赖 4 个嵌入框架
// App → FrameworkA → FrameworkB → FrameworkC
//
// 启动时 dyld 需要加载 3 个框架
//
// 合并后:创建一个合并框架
// MergedFramework = merge(A, B, C)
// App → MergedFramework
//
// 启动时 dyld 只需加载 1 个框架
// 构建时各框架仍然独立编译和调试
最佳实践
- 大型 App(10+ 嵌入框架)优先使用自动合并,一个开关就能获得显著改善。
- Debug 模式不需要改动配置——保持动态链接以确保构建速度。
- Release 构建验证合并后的包大小和启动时间是否确实改善。
- 如果框架需要被其他独立二进制(如 App Extension)使用,不要合并它。
- 符号化和崩溃报告在合并后仍然有效,不需要额外配置。
- 测试合并后的 App 确保 import 和模块访问正常工作。
还有什么值得关注
- Mergeable Libraries 是 Xcode 15 新静态链接器的能力。
- 系统框架(如 SwiftUI)不参与合并——只有你自己的嵌入框架会被合并。
- 合并后的二进制文件类型不变——App 仍然是 App,框架仍然是框架。
- 对 CocoaPods 等第三方依赖管理工具的影响需要评估——多 framework 集成的项目受益最大。
- 搭配 Session “What’s new in Xcode 15” 了解更多构建系统的改进。
WWDC 2023