You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在GitHub Actions中优化Rust项目CI编译缓存方案

解决Rust项目GitHub Actions分层缓存优化问题

核心思路

针对你的嵌套依赖结构和无Cargo.lock的场景,要实现分层缓存复用+精准触发缓存失效,核心是:

  • 给每个子模块(core、lib_A、lib_A1等)生成独立缓存键,包含「依赖变更哈希」+「自有代码哈希」+「目标平台」+「Rust版本」
  • 共享全局Cargo registry缓存,避免第三方依赖重复编译
  • 子模块缓存键继承父模块标识,实现父模块编译结果的复用

具体实现步骤

1. 生成依赖变更哈希(替代Cargo.lock哈希)

因为未存储Cargo.lock,直接基于各模块的Cargo.toml和Cargo.toml.orig(如果存在)生成哈希,同时加入Rust版本和目标平台,确保依赖更新或环境变化时缓存失效:

- name: Generate dependency hash
  id: dep-hash
  run: |
    # 生成core模块的依赖哈希
    core_dep_hash=$(find core -name "Cargo.toml" -o -name "Cargo.toml.orig" | sort | xargs sha256sum | sha256sum | cut -d' ' -f1)
    # 生成lib_A模块的依赖哈希(包含core的依赖文件)
    lib_a_dep_hash=$(find core lib_A -name "Cargo.toml" -o -name "Cargo.toml.orig" | sort | xargs sha256sum | sha256sum | cut -d' ' -f1)
    # 生成lib_A1模块的依赖哈希
    lib_a1_dep_hash=$(find core lib_A lib_A1 -name "Cargo.toml" -o -name "Cargo.toml.orig" | sort | xargs sha256sum | sha256sum | cut -d' ' -f1)
    # 输出到环境变量供后续步骤使用
    echo "core_dep_hash=$core_dep_hash" >> $GITHUB_OUTPUT
    echo "lib_a_dep_hash=$lib_a_dep_hash" >> $GITHUB_OUTPUT
    echo "lib_a1_dep_hash=$lib_a1_dep_hash" >> $GITHUB_OUTPUT

2. 生成自有代码哈希(控制代码变更时的缓存失效)

针对每个模块的Rust源码生成哈希,只有代码变动时才触发该模块重编译:

- name: Generate source code hash
  id: src-hash
  run: |
    core_src_hash=$(find core/src -type f -name "*.rs" | sort | xargs sha256sum | sha256sum | cut -d' ' -f1)
    lib_a_src_hash=$(find lib_A/src -type f -name "*.rs" | sort | xargs sha256sum | sha256sum | cut -d' ' -f1)
    lib_a1_src_hash=$(find lib_A1/src -type f -name "*.rs" | sort | xargs sha256sum | sha256sum | cut -d' ' -f1)
    echo "core_src_hash=$core_src_hash" >> $GITHUB_OUTPUT
    echo "lib_a_src_hash=$lib_a_src_hash" >> $GITHUB_OUTPUT
    echo "lib_a1_src_hash=$lib_a1_src_hash" >> $GITHUB_OUTPUT

3. 分层配置缓存

每个模块的缓存键由「目标平台」+「依赖哈希」+「代码哈希」组成,同时通过restore-keys实现缓存回退,复用父模块或依赖相同的缓存:

# 缓存core模块
- uses: actions/cache@v4
  with:
    path: |
      core/target
      ~/.cargo/registry/index/
      ~/.cargo/registry/cache/
    key: ${{ env.TARGET }}-core-${{ steps.dep-hash.outputs.core_dep_hash }}-${{ steps.src-hash.outputs.core_src_hash }}
    restore-keys: |
      ${{ env.TARGET }}-core-${{ steps.dep-hash.outputs.core_dep_hash }}-

# 缓存lib_A模块,继承core的缓存标识
- uses: actions/cache@v4
  with:
    path: |
      lib_A/target
      ~/.cargo/registry/index/
      ~/.cargo/registry/cache/
    key: ${{ env.TARGET }}-lib_A-${{ steps.dep-hash.outputs.lib_a_dep_hash }}-${{ steps.src-hash.outputs.lib_a_src_hash }}
    restore-keys: |
      ${{ env.TARGET }}-lib_A-${{ steps.dep-hash.outputs.lib_a_dep_hash }}-
      ${{ env.TARGET }}-core-${{ steps.dep-hash.outputs.core_dep_hash }}-

# 缓存lib_A1模块,继承lib_A和core的缓存标识
- uses: actions/cache@v4
  with:
    path: |
      lib_A1/target
      ~/.cargo/registry/index/
      ~/.cargo/registry/cache/
    key: ${{ env.TARGET }}-lib_A1-${{ steps.dep-hash.outputs.lib_a1_dep_hash }}-${{ steps.src-hash.outputs.lib_a1_src_hash }}
    restore-keys: |
      ${{ env.TARGET }}-lib_A1-${{ steps.dep-hash.outputs.lib_a1_dep_hash }}-
      ${{ env.TARGET }}-lib_A-${{ steps.dep-hash.outputs.lib_a_dep_hash }}-
      ${{ env.TARGET }}-core-${{ steps.dep-hash.outputs.core_dep_hash }}-

关键说明

  • 依赖哈希的层级性:lib_A的依赖哈希包含core的Cargo文件,确保core依赖更新时lib_A缓存自动失效,符合依赖链逻辑
  • 回退规则:restore-keys让缓存找不到精确匹配时,优先复用依赖相同但代码不同的缓存,代码变动时只需重编译当前模块,无需重新编译依赖和父模块
  • 全局Cargo缓存:每个缓存步骤都包含~/.cargo/registry路径,确保第三方依赖在所有模块间共享,避免重复下载编译
  • 灵活性:依赖哈希仅基于Cargo文件,宽松版本约束下只要依赖版本更新,哈希就会变动,不会错过依赖更新,同时不会像rust-cache那样因锁文件全量哈希导致缓存频繁失效

额外优化建议

  • 若矩阵构建包含多个Rust版本,可将Rust版本加入缓存键(如${{ matrix.rust-version }}-${{ env.TARGET }}-...)
  • 不要忽略target目录下的incremental文件夹,增量编译文件能大幅减少后续编译时间
  • lib_B和lib_B1模块可按照相同逻辑复制配置

内容的提问来源于stack exchange,提问作者Jury

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 13:40:17