增量构建¶
概述¶
CCGO 提供智能增量构建检测,自动只重新构建发生变化的文件及其依赖项。这通过避免不必要的重新编译,显著缩短重建时间。
收益¶
- ⚡ 更快的重建 —— 仅重新编译变更文件(10-50 倍加速)
- 🎯 智能检测 —— 跟踪文件、配置和依赖变化
- 🔍 变更分析 —— 精确显示自上次构建以来的变化
- 🚀 零配置 —— 自动生效,无需任何设置
- 💾 持久化状态 —— 构建状态可跨终端会话保留
工作原理¶
构建状态跟踪¶
CCGO 为每个平台和链接类型维护构建状态:
cmake_build/release/linux/
├── .ccgo_build_state.json # 构建状态(文件哈希、元信息)
└── CMakeCache.txt # CMake 构建缓存
构建状态跟踪以下内容: - 文件哈希 —— 所有源文件/头文件的 SHA256 校验和 - 配置哈希 —— CCGO.toml 配置的变化 - 选项哈希 —— 构建标志和选项的变化 - CMake 缓存 —— CMake 配置的变化 - 上次构建时间 —— 最近一次成功构建的时间戳
变更检测¶
每次构建时,CCGO:
- 加载历史状态 —— 若存在则读取
.ccgo_build_state.json - 扫描当前文件 —— 对所有源文件/头文件进行哈希
- 比较哈希 —— 检测修改、新增和删除的文件
- 检查配置 —— 检测 CCGO.toml 或构建选项的变化
- 决定构建策略:
- 增量构建 —— 若可行,仅构建变更文件
- 完全重建 —— 若配置/选项变化或 CMake 缓存缺失
使用方法¶
自动增量构建¶
增量构建无需配置即可自动生效:
# 首次构建(完整)
ccgo build linux
# ✓ Build completed in 45.2s
# 修改一个源文件
echo "// comment" >> src/mylib.cpp
# 第二次构建(增量)
ccgo build linux
# 📊 Incremental build - 1 files changed:
# Modified: 1
# ✓ Build completed in 3.8s (11.9x faster!)
构建输出示例¶
无变化¶
增量构建¶
$ ccgo build linux
📊 Incremental build - 3 files changed:
Modified: 2
Added: 1
⚡ Rebuilding affected files...
✓ Build completed in 4.2s
需要完全重建¶
$ ccgo build linux
🔄 Full rebuild required: CCGO.toml configuration changed
⚡ Building all files...
✓ Build completed in 42.8s
何时触发完全重建¶
配置变更¶
任何对 CCGO.toml 的修改都会触发完全重建:
构建选项变更¶
不同的构建选项需要完全重建:
# 首次构建使用 4 个 jobs
ccgo build linux --jobs 4
# 第二次构建使用 8 个 jobs → 完全重建
ccgo build linux --jobs 8
# 不同架构 → 完全重建
ccgo build linux --arch x86_64
ccgo build linux --arch arm64 # 完全重建
# Feature 变化 → 完全重建
ccgo build linux --features networking
ccgo build linux --features advanced # 完全重建
CMake 缓存变更¶
CMake 重新配置时会触发完全重建:
新增/删除文件¶
新增或删除源文件会触发 CMake 重新配置:
# 新增源文件
touch src/new_feature.cpp
# 下次构建检测到新增
ccgo build linux
# 📊 Incremental build - 1 files changed:
# Added: 1
# 🔧 CMake reconfiguration needed
构建状态文件¶
位置¶
构建状态按平台和构建模式分别存储:
cmake_build/
├── release/
│ ├── linux/.ccgo_build_state.json
│ ├── macos/.ccgo_build_state.json
│ └── windows/.ccgo_build_state.json
└── debug/
└── linux/.ccgo_build_state.json
状态文件格式¶
.ccgo_build_state.json 包含:
{
"project": "myproject",
"platform": "linux",
"link_type": "static",
"last_build_time": 1737433200,
"config_hash": "a1b2c3...",
"options_hash": "d4e5f6...",
"cmake_cache_hash": "g7h8i9...",
"file_hashes": {
"src/mylib.cpp": "sha256_hash...",
"src/utils.cpp": "sha256_hash...",
"include/mylib.h": "sha256_hash..."
}
}
手动管理状态¶
# 查看构建状态
cat cmake_build/release/linux/.ccgo_build_state.json
# 通过删除状态强制完全重建
rm cmake_build/release/linux/.ccgo_build_state.json
ccgo build linux
# 或使用 clean 命令
ccgo clean
性能对比¶
增量构建的典型加速效果:
| 场景 | 变更文件数 | 完全构建 | 增量构建 | 加速比 |
|---|---|---|---|---|
| 无变更 | 0 | 45s | 0.5s | 快 90 倍 |
| 单文件变更 | 1 | 45s | 3.8s | 快 11.9 倍 |
| 少量变更(5%) | 10/200 | 45s | 8.2s | 快 5.5 倍 |
| 较多变更(25%) | 50/200 | 45s | 18.5s | 快 2.4 倍 |
| 头文件变更 | 1(影响 50 个) | 45s | 22.1s | 快 2.0 倍 |
| 全部变更 | 200/200 | 45s | 44s | ~1x(完全重建) |
说明:加速比取决于: - 项目规模和复杂度 - 变更文件数量 - 依赖关系(头文件) - 编译器缓存(ccache/sccache)的有效性 - 硬件(CPU、磁盘速度)
最佳实践¶
推荐做法¶
✅ 交给 CCGO 决策 —— 增量构建是自动且智能的
✅ 配合编译器缓存使用 —— 与 --cache sccache 组合可获得最大速度
✅ 频繁提交 —— 变更越小,重建越快
✅ 隔离头文件变更 —— 头文件变更会触发更多重建
✅ 信任系统 —— CCGO 保证正确性
应避免¶
❌ 不要手动修改构建状态 —— 文件由系统自动生成 ❌ 不要共享构建状态 —— 状态依赖具体机器 ❌ 不要禁用 —— 无法禁用(始终有益) ❌ 不要修改构建目录 —— 让 CCGO 管理
CI/CD 集成¶
GitHub Actions¶
name: Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# 缓存 CMake 构建目录以支持增量构建
- name: Cache CMake Build
uses: actions/cache@v3
with:
path: cmake_build/
key: ${{ runner.os }}-cmake-${{ hashFiles('CCGO.toml', 'src/**') }}
restore-keys: |
${{ runner.os }}-cmake-
# 缓存命中时增量构建生效
- name: Build
run: ccgo build linux
CI 中的收益: - 🚀 更快的 PR 构建 —— 仅重建变更文件 - 💰 降低 CI 成本 —— 减少计算时间 - ⚡ 更快的反馈 —— 开发者更快拿到结果
GitLab CI¶
build:
image: rust:latest
cache:
paths:
- cmake_build/
key:
files:
- CCGO.toml
- src/**/*.cpp
script:
- ccgo build linux
故障排查¶
增量构建未生效¶
症状:每次构建都是完全重建
原因与解决方法:
-
构建状态文件缺失
-
配置或选项发生变化
-
CMake 缓存被清除
增量构建结果异常¶
症状:构建成功但变更未反映在产物中
解决方法:理论上不会发生 —— 增量系统采取保守策略。如怀疑存在问题:
# 强制完全重建
ccgo clean
ccgo build linux
# 或仅删除构建状态
rm cmake_build/release/linux/.ccgo_build_state.json
ccgo build linux
构建状态损坏¶
症状:增量构建期间出现意外错误
解决方法:
实现细节¶
变更检测算法¶
// 伪代码
fn can_incremental_build() -> bool {
// 加载历史构建状态
let old_state = load_build_state()?;
// 检查配置
if old_state.config_hash != current_config_hash() {
return false; // 配置已变化
}
// 检查构建选项
if old_state.options_hash != current_options_hash() {
return false; // 选项已变化
}
// 检查 CMake 缓存
if !cmake_cache_exists() || old_state.cmake_cache_hash != current_cmake_cache_hash() {
return false; // CMake 需要重新配置
}
true // 可以进行增量构建
}
fn analyze_changes() -> ChangeAnalysis {
let mut changes = ChangeAnalysis::new();
// 扫描当前源文件
for file in scan_source_files() {
let current_hash = hash_file(file);
match old_state.file_hashes.get(file) {
Some(old_hash) if old_hash != current_hash => {
changes.modified_files.push(file);
}
None => {
changes.added_files.push(file);
}
_ => {} // 未变化
}
}
// 检测删除的文件
for old_file in old_state.file_hashes.keys() {
if !current_files.contains(old_file) {
changes.removed_files.push(old_file);
}
}
changes
}
文件哈希¶
CCGO 使用 SHA256 对文件内容进行哈希:
use sha2::{Digest, Sha256};
fn hash_file(path: &Path) -> String {
let content = std::fs::read(path)?;
let mut hasher = Sha256::new();
hasher.update(&content);
format!("{:x}", hasher.finalize())
}
为何选择 SHA256? - 对源文件足够快(每个文件 < 1ms) - 抗碰撞(无误报) - 标准且久经验证 - Rust 标准库即可获得
CMake 集成¶
增量构建借助 CMake 内置的增量编译能力:
- CMake 检测文件变化 —— 检查修改时间
- CCGO 检测配置变化 —— 防止陈旧构建
- 组合方案 —— 兼顾两者优势
CCGO 的变更检测保守 —— 一旦存疑,就完全重建。
进阶主题¶
多平台¶
每个平台拥有独立的构建状态:
平台之间的变更互不影响。
Debug 与 Release¶
Debug 与 Release 构建拥有独立状态:
链接类型¶
静态与动态构建共用同一份构建状态:
两种链接类型使用同一组源文件,因此变更可相互传播。
未来规划¶
后续版本计划的特性:
- 用于头文件变化的依赖图跟踪
- 并行增量编译
- 远程构建缓存(团队共享)
- 构建时间预测
- 旧构建状态的自动清理
- 可视化依赖图
- 单文件级别的构建时间跟踪
另请参阅¶
变更日志¶
v3.0.12 (2026-01-21)¶
- ✅ 实现增量构建检测
- ✅ 基于文件哈希(SHA256)的构建状态跟踪
- ✅ 配置和选项变更检测
- ✅ CMake 缓存跟踪
- ✅ 包含修改/新增/删除文件的变更分析
- ✅ 自动持久化构建状态
- ✅ 按平台、按链接类型分别管理状态
- ✅ 保留最近 100 次构建以供分析
增量构建只重建发生变化的部分,让开发流程显著更快。