Rust构建系统插件库hakari的使用:优化Cargo工作区依赖管理与构建流程

hakari 是 cargo hakari 的底层库,一个用于管理工作区 hack 包的工具。

示例

use guppy::MetadataCommand;
use hakari::{HakariBuilder, HakariOutputOptions};

// 使用此工作区的 PackageGraph 进行这些测试。
let package_graph = MetadataCommand::new()
    .build_graph()
    .expect("obtained cargo-guppy's PackageGraph");

// HakariBuilder::new 的第二个参数指定一个 Hakari(workspace-hack)包。
// 在此存储库中,该包称为 "guppy-workspace-hack"。
let hakari_package = package_graph.workspace().member_by_name("guppy-workspace-hack").unwrap().id();
let hakari_builder = HakariBuilder::new(&package_graph, Some(hakari_package))
    .expect("HakariBuilder was constructed");

// HakariBuilder 有许多配置选项。对于此示例,使用默认值。
let hakari = hakari_builder.compute();

// hakari 可用于构建构成 Cargo.toml 文件一部分的 TOML 表示。
// 可以使用 Hakari::read_toml 管理现有的 Cargo.toml 文件。
let toml = hakari.to_toml_string(&HakariOutputOptions::default()).expect("TOML output was constructed");

// toml 包含将进入 Hakari 包的 Cargo.toml [dependencies]。可以通过
// `HakariCargoToml`(由 Hakari::read_toml 返回)或手动写入。
println!("Cargo.toml contents:\n{}", toml);

cargo-guppy 存储库使用由 cargo hakari 管理的工作区 hack crate。

cargo-guppy 存储库还有许多展示 Hakari 输出的 fixture。

hakari 的工作原理

Hakari 遵循三步过程。

  1. 配置

HakariBuilder 提供选项来配置 Hakari 计算的方式。支持的选项包括:

  • 工作区 hack 包的位置
  • 模拟 Cargo 构建的平台
  • 使用的 Cargo 解析器版本
  • 计算期间要排除的包
  • 最终输出中要排除的包

通过可选的 cli-support 功能,HakariBuilder 选项可以从文件读取或写入文件为 TOML 或其他格式。

  1. 计算

一旦配置了 HakariBuilder,可以调用其 compute 方法来创建 Hakari 实例。算法运行三个步骤:

  1. 使用 guppy 为每个工作区包和每个给定平台模拟 Cargo 构建,包括无功能、默认功能和所有功能。将结果收集到按每个依赖项及其构建的不同功能集索引的映射中。
  2. 扫描映射以找出哪些依赖项使用两个或更多不同功能集构建,将它们收集到输出映射中。
  3. 如果假设输出映射将通过下面的步骤 3 写入工作区 hack 包,可能会导致一些额外的包以第二种功能集构建。查找这些包,将它们添加到输出映射中,并迭代直到达到固定点且没有新包以多种方式构建。

此计算以并行方式完成,使用 Rayon 库。

此计算的结果是一个 Hakari 实例。

  1. 序列化

最后一步是将输出映射的内容序列化到工作区 hack 包的 Cargo.toml 文件中。

  1. Hakari::read_toml 读取磁盘上现有的 Cargo.toml 文件。此文件是部分生成的:
[package]
name = "workspace-hack"
version = "0.1.0"
# 更多选项...

### BEGIN HAKARI SECTION
...
### END HAKARI SECTION

BEGIN HAKARI SECTION 和 END HAKARI SECTION 行之外的内容可以手动编辑。此部分内的内容是自动生成的。

成功时,返回 HakariCargoToml。

  1. Hakari::to_toml_string 返回自动生成部分的新内容。

  2. HakariCargoToml::write_to_file 将内容写入磁盘。

HakariCargoToml 还支持将内容序列化到内存并生成差异。

未来工作

hakari 仍然缺少一些功能:

  • 模拟交叉编译
  • 平台特定的排除
  • 仅在最终结果中包含包的子集(例如统一核心包如 syn 但不包括其他)

这些功能将在有时间时添加。

贡献

查看 CONTRIBUTING 文件了解如何提供帮助。

许可证

此项目根据 Apache 2.0 许可证或 MIT 许可证的条款提供。

完整示例代码:

use guppy::MetadataCommand;
use hakari::{HakariBuilder, HakariOutputOptions};

fn main() {
    // 使用此工作区的 PackageGraph 进行这些测试。
    let package_graph = MetadataCommand::new()
        .build_graph()
        .expect("obtained cargo-guppy's PackageGraph");

    // HakariBuilder::new 的第二个参数指定一个 Hakari(workspace-hack)包。
    // 在此存储库中,该包称为 "guppy-workspace-hack"。
    let hakari_package = package_graph.workspace().member_by_name("guppy-workspace-hack").unwrap().id();
    let hakari_builder = HakariBuilder::new(&package_graph, Some(hakari_package))
        .expect("HakariBuilder was constructed");

    // HakariBuilder 有许多配置选项。对于此示例,使用默认值。
    let hakari = hakari_builder.compute();

    // hakari 可用于构建构成 Cargo.toml 文件一部分的 TOML 表示。
    // 可以使用 Hakari::read_toml 管理现有的 Cargo.toml 文件。
    let toml = hakari.to_toml_string(&HakariOutputOptions::default()).expect("TOML output was constructed");

    // toml 包含将进入 Hakari 包的 Cargo.toml [dependencies]。可以通过
    // `HakariCargoToml`(由 Hakari::read_toml 返回)或手动写入。
    println!("Cargo.toml contents:\n{}", toml);
}

1 回复

Rust构建系统插件库hakari的使用:优化Cargo工作区依赖管理与构建流程

介绍

hakari是Rust生态中的一个构建系统插件库,专门用于优化Cargo工作区的依赖管理和构建流程。它通过自动化处理依赖版本冲突和构建缓存,显著提升大型Rust项目的构建效率。

主要特性

  • 自动化依赖解析和冲突检测
  • 智能构建缓存管理
  • 工作区范围内的依赖优化
  • 与Cargo原生工具链无缝集成

安装方法

cargo install cargo-hakari

基本使用方法

1. 初始化hakari配置

cargo hakari init

2. 生成依赖图

cargo hakari generate

3. 运行优化构建

cargo hakari build

配置示例

Cargo.toml中添加hakari配置:

[package.metadata.hakari]
# 启用所有工作区成员的依赖优化
enable = true
# 排除特定crate
exclude = ["example-crate"]

实际使用示例

// 在工作区根目录执行以下命令

// 1. 查看依赖分析
cargo hakari analyze

// 2. 应用优化建议
cargo hakari apply

// 3. 验证依赖一致性
cargo hakari verify

// 4. 使用优化后的构建
cargo hakari build --release

高级配置

创建hakari.toml配置文件:

[hakari]
# 指定目标平台
target = "x86_64-unknown-linux-gnu"

# 构建特性配置
[features]
default = ["serde", "tokio"]
optional = ["logging", "metrics"]

常见问题解决

依赖冲突处理

# 显示依赖冲突详情
cargo hakari conflicts

# 自动解决冲突
cargo hakari resolve

缓存管理

# 清理构建缓存
cargo hakari clean

# 查看缓存统计
cargo hakari cache-stats

集成到CI/CD流程

.github/workflows/ci.yml中添加:

- name: Setup hakari
  run: cargo install cargo-hakari

- name: Run hakari optimization
  run: cargo hakari build --release

hakari通过智能的依赖管理和构建优化,能够显著减少大型Rust项目的构建时间,特别适合包含多个crate的工作区项目。

完整示例demo

以下是一个完整的hakari使用示例,展示如何在Rust工作区项目中配置和使用hakari:

项目结构:

my-workspace/
├── Cargo.toml
├── hakari.toml
├── member1/
│   └── Cargo.toml
├── member2/
│   └── Cargo.toml
└── member3/
    └── Cargo.toml

工作区根目录 Cargo.toml:

[workspace]
members = ["member1", "member2", "member3"]

[package.metadata.hakari]
enable = true
exclude = ["member3"]  # 排除member3 crate的优化

hakari.toml 配置文件:

[hakari]
target = "x86_64-unknown-linux-gnu"

[features]
default = ["serde", "tokio"]
optional = ["logging", "metrics"]

使用流程示例:

# 1. 安装hakari
cargo install cargo-hakari

# 2. 初始化配置
cargo hakari init

# 3. 生成依赖图和分析
cargo hakari generate
cargo hakari analyze

# 4. 查看和解决依赖冲突
cargo hakari conflicts
cargo hakari resolve

# 5. 应用优化配置
cargo hakari apply

# 6. 验证依赖一致性
cargo hakari verify

# 7. 执行优化构建
cargo hakari build --release

# 8. 缓存管理
cargo hakari cache-stats
cargo hakari clean

CI/CD集成示例 (.github/workflows/ci.yml):

name: CI Pipeline

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Rust
      uses: actions-rs/toolchain@v1
      with:
        toolchain: stable
        
    - name: Setup hakari
      run: cargo install cargo-hakari
      
    - name: Run hakari optimization
      run: cargo hakari build --release
      
    - name: Run tests
      run: cargo test --release

这个完整示例展示了hakari在实际项目中的完整使用流程,包括配置初始化、依赖分析、冲突解决、优化构建以及CI/CD集成。通过这种方式,可以显著提升大型Rust工作区项目的构建效率。

回到顶部