Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← C++ 编程 / C++ Programming

构建、测试与 ABI / Build, Testing & ABI

1. C++ 工程构建质量、ABI 与发布证据路线 / C++ Build Quality, ABI, and Release Evidence Roadmap

2. 工程级 CMake Target 设计规范 / Engineering Modern CMake Target Design

3. 测试、静态分析与 Sanitizer 门禁 / Testing, Analysis, and Sanitizer Gates

4. 包、ABI 与性能证据总账 / Packaging, ABI, and Performance Evidence Ledger

5. 链接诊断、库边界与符号证据 / Link Diagnostics, Library Boundaries, and Symbol Evidence

6. ABI 边界与兼容策略 / ABI Boundaries and Compatibility Policy

7. 依赖、CI、制品与发布流程 / Dependencies, CI, Artifacts, and Release Flow

8. 工程构建综合复习:发布 Mesh::Core / Engineering Build Review: Releasing Mesh::Core

本页目录

ABI 边界与兼容策略 / ABI Boundaries and Compatibility Policy ​

1. ABI 是编译后仍然存在的契约 ​

源码兼容不等于二进制兼容。一个头文件看起来只新增了成员函数,也可能改变类布局、inline 代码、符号、异常传播或分配边界。本篇目标是把 ABI 风险写成团队能执行的 policy。

2. 最简单心智模型 ​

ABI 是已编译代码之间的二进制契约。 C++ ABI 受编译器、标准库、运行库、异常、RTTI、布局和可见性共同影响。 稳定 ABI 的常见方法是缩小边界:C 接口、不透明句柄、PIMPL、版本协商或进程隔离。

text
public header
  -> source API
  -> generated symbols
  -> object layout / vtable
  -> runtime ownership rules
  -> binary compatibility promise
1
2
3
4
5
6

3. 核心术语 ​

C ABI:比 C++ ABI 更稳定、更容易跨编译器协作的函数调用和符号约定,常用于插件、SDK 和动态库边界。

对象布局:对象在内存中的字段顺序、对齐、填充和基类布局。它一变,旧二进制按旧偏移访问就可能出错。

vtable:虚函数调用依赖的表结构。新增、删除或重排虚函数可能改变二进制调用位置。

异常边界:异常是否允许跨动态库、编译器或语言边界传播。稳定 ABI 通常要求边界处捕获并转换成错误码或状态对象。

分配器边界:谁分配、谁释放内存的约定。跨运行库或跨模块释放对象,是 C++ SDK 里很常见的事故源。

兼容矩阵:列出旧消费者、新消费者、旧库、新库之间哪些组合必须工作,哪些组合明确不承诺。

4. 机制展开 ​

兼容承诺要写清楚 ​

库可以承诺源码兼容、二进制兼容、协议兼容或完全不承诺。

不写清楚时,使用者会默认你什么都承诺,维护者却按内部实现自由修改,冲突迟早发生。

常见 ABI 破坏 ​

公开类新增数据成员、调整虚函数顺序、改变 enum 大小、改变 inline 函数语义、跨边界抛异常、跨边界释放内存,都是高风险行为。

模板和 header-only 库常把 ABI 问题转移到源码重新编译,但仍可能受 ODR 和依赖版本影响。

old-consumer/new-library 测试 ​

ABI 兼容最实际的验证之一,是用旧版本头文件和旧 consumer 二进制,替换为新库运行。

这比只构建最新源码更接近用户升级路径。

5. 最小示例 ​

下面的示例不是完整项目,而是为了把本篇概念落到可审查文本。阅读代码时关注它暴露了哪些边界,而不是照抄每个名字。

text
extern "C" {
struct mesh_context;

using mesh_status = int;

mesh_status mesh_create(mesh_context** out, const mesh_config* config);
mesh_status mesh_run(mesh_context* ctx, const mesh_input* input, mesh_output* output);
void mesh_destroy(mesh_context* ctx);
const char* mesh_version();
}
1
2
3
4
5
6
7
8
9
10

6. 工程取舍 ​

选择收益风险需要的证据
只在本机验证反馈最快环境不可复现仅适合草稿,不适合作为发布结论
CI 快速门禁阻止常见错误覆盖不完整明确矩阵、日志和失败归属
完整发布门禁证据最强成本更高制品、符号、SBOM、ABI 和回滚记录
最小消费者测试最接近用户需要维护样例独立目录、安装包、运行输出

7. 常见错误 ​

  • 把“当前源码树能构建”误认为“安装包能被别人消费”。
  • 把 PRIVATE 实现细节通过头文件、导出符号或包配置泄漏出去。
  • 只保存最终二进制,不保存构建输入、依赖锁、调试符号和版本信息。
  • 只在 Debug 测试,不在 Release 或发布配置里测试。
  • 把 CI 缓存当成依赖管理,把绿色状态当成发布结论。
  • 遇到链接或 ABI 问题时只改 flags,不留下能够复盘的符号证据。

8. 调试与验证方法 ​

定义公开承诺 ​

写清楚本库承诺源码兼容、二进制兼容、协议兼容还是仅内部使用。承诺越模糊,升级事故越难判责。

text
observe vtable
  -> isolate 异常边界
  -> run minimal proof
  -> store evidence
1
2
3
4

建立干净环境 ​

用全新 build directory 和最小 consumer project 验证,不依赖源码树中的 include 路径和本机缓存。

text
observe 对象布局
  -> isolate vtable
  -> run minimal proof
  -> store evidence
1
2
3
4

固定工具版本 ​

记录编译器、CMake、Ninja、包管理器、系统镜像和关键 flags,避免把偶然环境当成规则。

text
observe C ABI
  -> isolate 对象布局
  -> run minimal proof
  -> store evidence
1
2
3
4

保存失败证据 ​

失败日志、符号报告、测试输出和构建命令要能被别人复现,而不是只留一句“CI failed”。

text
observe 兼容矩阵
  -> isolate C ABI
  -> run minimal proof
  -> store evidence
1
2
3
4

区分私有与公开 ​

私有实现可以快速迭代;公开头、导出符号、包元数据和 ABI policy 必须谨慎变更。

text
observe 分配器边界
  -> isolate 兼容矩阵
  -> run minimal proof
  -> store evidence
1
2
3
4

审查跨平台差异 ​

Windows 的 DLL/import lib/PDB 与 Linux 的 so/SONAME/RPATH/debug file 不同,不能用一个平台的经验套全部。

text
observe 异常边界
  -> isolate 分配器边界
  -> run minimal proof
  -> store evidence
1
2
3
4

限制全局状态 ​

全局 include、全局 flags、隐式环境变量和手工 PATH 修改都会让构建不可解释。

text
observe vtable
  -> isolate 异常边界
  -> run minimal proof
  -> store evidence
1
2
3
4

做升级测试 ​

old consumer + new library、new consumer + package install 是比单纯编译源码更接近用户现场的测试。

text
observe 对象布局
  -> isolate vtable
  -> run minimal proof
  -> store evidence
1
2
3
4

设置回滚入口 ​

发布前准备上一稳定制品、数据库或文件格式迁移策略、插件兼容说明和符号包。

text
observe C ABI
  -> isolate 对象布局
  -> run minimal proof
  -> store evidence
1
2
3
4

写入 CI ​

能自动检查的规则不要只写在文章里;把它变成 preset、脚本、workflow 或 release checklist。

text
observe 兼容矩阵
  -> isolate C ABI
  -> run minimal proof
  -> store evidence
1
2
3
4

管理例外 ​

允许临时豁免时必须记录原因、过期时间和补偿测试,否则门禁会慢慢失去意义。

text
observe 分配器边界
  -> isolate 兼容矩阵
  -> run minimal proof
  -> store evidence
1
2
3
4

保持证据总账 ​

把构建输入、依赖锁、测试、ABI、性能、SBOM、签名和制品 hash 放在同一发布记录中。

text
observe 异常边界
  -> isolate 分配器边界
  -> run minimal proof
  -> store evidence
1
2
3
4

9. 本篇专属检查表 ​

  1. 公开类型布局是否冻结。
  2. 异常是否跨 ABI 边界。
  3. 内存由谁分配谁释放。
  4. 是否有 ABI diff baseline。
  5. 是否测试旧消费者升级。
检查点通过标准失败时优先看哪里
C ABI有可重复命令、报告或 consumer 证明target 属性、CI 日志、符号报告、包元数据
对象布局有可重复命令、报告或 consumer 证明target 属性、CI 日志、符号报告、包元数据
vtable有可重复命令、报告或 consumer 证明target 属性、CI 日志、符号报告、包元数据
异常边界有可重复命令、报告或 consumer 证明target 属性、CI 日志、符号报告、包元数据
分配器边界有可重复命令、报告或 consumer 证明target 属性、CI 日志、符号报告、包元数据
兼容矩阵有可重复命令、报告或 consumer 证明target 属性、CI 日志、符号报告、包元数据

10. 练习任务 ​

  • 建立一个只有一个库和一个 consumer 的最小工程,证明安装树可用。
  • 故意破坏一个 PUBLIC/PRIVATE 作用域,观察消费者构建失败方式。
  • 保存一次链接或 ABI 报告,并写下它能证明什么、不能证明什么。
  • 把一个手工验证命令改成 CI 步骤,并让失败消息能指向具体文件或配置。
  • 写一份 release evidence 小清单,列出制品、符号、依赖、测试和回滚入口。

12. 总结 ​

《ABI 边界与兼容策略 / ABI Boundaries and Compatibility Policy》的核心不是多记几个命令,而是把 C ABI、对象布局、vtable、异常边界、分配器边界、兼容矩阵 变成可审查、可复现、可回滚的工程证据。

返回 08 工程构建质量路线

深化问题 1:对象布局 怎样变成证据 ​

围绕 对象布局 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:用全新 build directory 和最小 consumer project 验证,不依赖源码树中的 include 路径和本机缓存。

text
rule: 对象布局
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 2:vtable 怎样变成证据 ​

围绕 vtable 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:记录编译器、CMake、Ninja、包管理器、系统镜像和关键 flags,避免把偶然环境当成规则。

text
rule: vtable
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 3:异常边界 怎样变成证据 ​

围绕 异常边界 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:失败日志、符号报告、测试输出和构建命令要能被别人复现,而不是只留一句“CI failed”。

text
rule: 异常边界
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 4:分配器边界 怎样变成证据 ​

围绕 分配器边界 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:私有实现可以快速迭代;公开头、导出符号、包元数据和 ABI policy 必须谨慎变更。

text
rule: 分配器边界
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 5:兼容矩阵 怎样变成证据 ​

围绕 兼容矩阵 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:Windows 的 DLL/import lib/PDB 与 Linux 的 so/SONAME/RPATH/debug file 不同,不能用一个平台的经验套全部。

text
rule: 兼容矩阵
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 6:C ABI 怎样变成证据 ​

围绕 C ABI 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:全局 include、全局 flags、隐式环境变量和手工 PATH 修改都会让构建不可解释。

text
rule: C ABI
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 7:对象布局 怎样变成证据 ​

围绕 对象布局 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:old consumer + new library、new consumer + package install 是比单纯编译源码更接近用户现场的测试。

text
rule: 对象布局
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 8:vtable 怎样变成证据 ​

围绕 vtable 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:发布前准备上一稳定制品、数据库或文件格式迁移策略、插件兼容说明和符号包。

text
rule: vtable
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 9:异常边界 怎样变成证据 ​

围绕 异常边界 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:能自动检查的规则不要只写在文章里;把它变成 preset、脚本、workflow 或 release checklist。

text
rule: 异常边界
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 10:分配器边界 怎样变成证据 ​

围绕 分配器边界 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:允许临时豁免时必须记录原因、过期时间和补偿测试,否则门禁会慢慢失去意义。

text
rule: 分配器边界
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 11:兼容矩阵 怎样变成证据 ​

围绕 兼容矩阵 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:把构建输入、依赖锁、测试、ABI、性能、SBOM、签名和制品 hash 放在同一发布记录中。

text
rule: 兼容矩阵
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 12:C ABI 怎样变成证据 ​

围绕 C ABI 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:写清楚本库承诺源码兼容、二进制兼容、协议兼容还是仅内部使用。承诺越模糊,升级事故越难判责。

text
rule: C ABI
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 13:对象布局 怎样变成证据 ​

围绕 对象布局 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:用全新 build directory 和最小 consumer project 验证,不依赖源码树中的 include 路径和本机缓存。

text
rule: 对象布局
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 14:vtable 怎样变成证据 ​

围绕 vtable 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:记录编译器、CMake、Ninja、包管理器、系统镜像和关键 flags,避免把偶然环境当成规则。

text
rule: vtable
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 15:异常边界 怎样变成证据 ​

围绕 异常边界 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:失败日志、符号报告、测试输出和构建命令要能被别人复现,而不是只留一句“CI failed”。

text
rule: 异常边界
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 16:分配器边界 怎样变成证据 ​

围绕 分配器边界 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:私有实现可以快速迭代;公开头、导出符号、包元数据和 ABI policy 必须谨慎变更。

text
rule: 分配器边界
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 17:兼容矩阵 怎样变成证据 ​

围绕 兼容矩阵 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:Windows 的 DLL/import lib/PDB 与 Linux 的 so/SONAME/RPATH/debug file 不同,不能用一个平台的经验套全部。

text
rule: 兼容矩阵
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 18:C ABI 怎样变成证据 ​

围绕 C ABI 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:全局 include、全局 flags、隐式环境变量和手工 PATH 修改都会让构建不可解释。

text
rule: C ABI
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 19:对象布局 怎样变成证据 ​

围绕 对象布局 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:old consumer + new library、new consumer + package install 是比单纯编译源码更接近用户现场的测试。

text
rule: 对象布局
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 20:vtable 怎样变成证据 ​

围绕 vtable 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:发布前准备上一稳定制品、数据库或文件格式迁移策略、插件兼容说明和符号包。

text
rule: vtable
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

深化问题 21:异常边界 怎样变成证据 ​

围绕 异常边界 写一个项目规则:谁可以修改,修改后跑什么命令,失败时保存哪些输出。

对应的工程动作是:能自动检查的规则不要只写在文章里;把它变成 preset、脚本、workflow 或 release checklist。

text
rule: 异常边界
owner: module maintainer
proof: command + report + artifact
failure: block merge or require documented exception
1
2
3
4

最后更新于:

Pager
上一篇5. 链接诊断、库边界与符号证据 / Link Diagnostics, Library Boundaries, and Symbol Evidence
下一篇7. 依赖、CI、制品与发布流程 / Dependencies, CI, Artifacts, and Release Flow

持续记录,持续成长

Copyright © Tidenflow