这是一篇关于成功重写 C++ 代码库的指南,包含以下主要内容:
- 背景:继承了一个复杂的 C++ 代码库,团队中只有作者能进行修改,且代码存在诸多问题,如正确性、可维护性、安全性等方面不佳,同时没有招聘 C++ 开发者的计划,继续使用 C++ 是死路一条,引入新语言进行增量重写是更好的选择。
步骤:
- 改善现有代码库:确保代码在所有支持的平台上构建和运行,通过测试,并有清晰的 README 说明本地设置,同时去除无用代码。
- 获得支持:从队友和利益相关者那里获得支持至关重要,通过展示现状(如总线因子、内存泄漏、fuzzing 结果、linter 检测到的问题等),提出多种解决方案并进行比较,如有可能,制作小型原型以确认方案的可行性。最终选择 Rust 作为新语言。
- 保持支持:定期向利益相关者展示进展,展示新代码解决旧代码问题的能力,重复决策过程,与队友保持沟通,确保他们对新语言有信心。
- 准备引入新语言:创建 Git 标签以区分引入新语言前后的代码,添加新语言代码时先关注构建系统和 CI 的工作,在 README 中提供工具说明。
- 增量重写:坚持增量重写原则,每次选择一个小的组件进行重写,在同一仓库中与现有代码并行,编写测试用例,逐步替换旧代码,避免大的 PR 和长时间运行的分支,注意一些细节,如从调用图的叶子开始、迁移代码注释、使用自动化工具等,增量重写的优势是立即有用,即使未完全完成也有改进。
- fuzzing:添加 fuzzing 测试以发现代码中的角落情况,使用
cargo-fuzz
和 LLVM 工具可视化分支覆盖情况,从 C++ 测试中提取有用数据构建 fuzzing 语料库,使用 LLVM 的 corpus minimizer 优化语料库,还可以手动添加 reproducer 文件作为回归测试。 - 纯 Rust 与互操作(FFI):在 Rust 中使用
unsafe {}
块进行 FFI 开发,对 FFI 代码进行隔离和转换,以提高安全性,但 FFI 开发繁琐且容易引入内存安全问题,需要使用 Miri 进行测试,Rust 的 FFI 能力虽有效但需额外小心和测试。 - 交叉编译:Rust 有良好的交叉编译支持,通过 CMake 和
rustup
进行配置,处理各种平台的差异和编译器选项,还可以编写 Lua 脚本来交叉编译所有平台,相比之下 C++ 的交叉编译支持不佳。
- 结论:重写尚未完成,但已有较多 Rust 代码,开发者对 Rust 满意,添加单元测试在 Rust 中很简单,工具链也很完善,但 CMake/Make/Ninja 对不熟悉的开发者有难度,希望能缓解对重写 C++ 代码库的担忧,选择合适的语言,增量重写,展示进度,保持团队支持。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。