侧边栏壁纸
博主头像
博主等级

秋风清,秋月明,落叶聚还散,寒鸦息复惊,相思相见知何日,此时此夜难为情!

  • 累计撰写 20 篇文章
  • 累计创建 32 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Rust工作空间

尘
2024-06-17 / 0 评论 / 0 点赞 / 97 阅读 / 9934 字
温馨提示:
本文最后更新于 2024-06-17,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Rust工作空间

随着项目的发展,会发现库越来越大,因此希望将包进一步拆分成多个库,Cargo提供了一个名为工作空间(workspaces)的功能。可以帮助管理多个相关的、一起开发的包。

创建工作空间

工作空间是一组共享同一个Cargo.lock文件和输出目录的包。

将有一个包含一个二进制文件和两个库的工作空间,二进制文件提供主要功能并依赖于两个库,一个库提供add_one函数,一个库提供add_two函数。

三个crate将是同一个工作空间的一部分

  1. 创建工作空间的新目录开

    mkdir add
    cd add
    
  2. 新建Cargo.toml文件,文件内容如下:

    [workspace]
    
    members = [
    ]
    
  3. 创建adder二进制crate

    cargo new adder
    

    可以运行 cargo build 来构建工作空间,此时的目录层级为:

    H:\TEMP\ADD
    │  Cargo.toml
    │
    └─adder
        │  Cargo.toml
        │
        └─src
                main.rs
    

    工作空间在顶层有一个目标目录(target directory),编译后的产物将会被放入其中,adder包本身没有自己的目标目录,即使我们在adder目录中运行cargo build,编译后的产物仍然会出现在add/target中,而不是 add/adder/target(没有这个目录)

    Cargo 在工作空间中这样组织目标目录是因为工作空间中的 crate 通常是互相依赖的。如果每个 crate 都有自己的目标目录,那么每个 crate 都必须重新编译工作空间中的其他 crate 以将产物放入自己的目标目录,通过共享一个目标目录,create可以避免不必要的重建。

  4. 在工作空间中创建第二个 package

    创建另一个成员包,并命名为add_one

    cargo new add_one --lib
    

    在add_one中的add_one/src/lib.rs添加一个add_one函数,添加测试函数

    pub fn add_one(num: i32) -> i32 {
        num + 1
    }
    
    #[cfg(test)]
    mod tests {
        use crate::add_one;
    
    
        #[test]
        fn it_works() {
            let result = add_one(2);
            assert_eq!(result, 3);
        }
    }
    

    然后需要在adder/Cargo.toml中添加一个对add_one的路径依赖,Cargo 并不默认假定工作空间中的 crate 会相互依赖,所以需要明确指定依赖关系。

    在adder crate中使用add_one函数,修改adder/src/main.rs中的代码

    use add_one;
    
    fn main() {
        let num = 10;
        println!("Hello, world! {} plus one is {}!", num, add_one::add_one(num));
    }
    

    通过在顶层的 add 目录中运行 cargo build 来构建工作空间!

    要从 add 目录运行一进制 crate,可以使用cargo run 时带上-p 参数和包名来指定工作空间中要运行的包

    cargo run -p adder
    

    执行结果

    Hello, world! 10 plus one is 11!
    
  5. 在工作空间中引入外部crate

    工作空间在顶层只有一个Cargo.lock文件,而不是在每个crate目录中都有一个Cargo.lock,如果添加一个rand包到 adder/Cargo.tomladd_one/Cargo.toml文件中,Cargo 将会解析这两个文件中的 rand 版本并记录在唯一的Cargo.lock文件中,使工作空间中的所有 crate 使用相同的依赖项,意味着这些 crate将始终彼此兼容。

    rand 添加到 add_one/Cargo.toml中的dependencies部分,以便可以在add_one中使用rand,同时在adder/Cargo.toml中的dependencies添加rand,两个地方使用不同的版本,但是最后会发现,Cargo会确保工作空间中的每个包中的每个crate使用相同版本的rand,这样既节省空间 ,又确保工作空间中的crate彼此兼容,如果工作空间中的crate 指定了不兼容版本的同一依赖项,Cargo 将分别解析每个版本,但仍将尽量解析尽可能少的版本。

    此时各个文件的改动:

    add_one/Cargo.toml

    [package]
    name = "add_one"
    version = "0.1.0"
    edition = "2021"
    
    [dependencies]
    rand = "0.8.5"
    

    add_one/src/lib.rs

    use rand::Rng;
    pub fn add_one(num: i32) -> (i32, i32) {
        let mut rng = rand::thread_rng();
        let i = rng.gen_range(0..100);
        return (num + i, i);
    }
    
    #[cfg(test)]
    mod tests {
        use crate::add_one;
    
        #[test]
        fn it_works() {
            let (result, rand_num) = add_one(2);
            assert_eq!(result, 2 + rand_num);
        }
    }
    

    adder/Cargo.toml

    [package]
    name = "adder"
    version = "0.1.0"
    edition = "2021"
    
    [dependencies]
    add_one = { path = "../add_one" }
    rand = "0.8.4"
    

    adder/src/main.rs

    use add_one;
    use rand::Rng;
    
    fn main() {
        let mut rng = rand::thread_rng();
        let num = rng.gen_range(0..10);
        let (res, rand_num) = add_one::add_one(num);
        println!("Hello, world! {} add {} is {}!", num, rand_num, res);
    }
    
  6. 在工作空间中添加测试模块

    新建add_two

    cargo new add_two --lib
    

    测试代码已添加,运行cargo test

    note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
    warning: virtual workspace defaulting to `resolver = "1"` despite one or more workspace members being on edition 2021 which implies `resolver = "2"`
    note: to keep the current resolver, specify `workspace.resolver = "1"` in the workspace root's manifest
    note: to use the edition 2021 resolver, specify `workspace.resolver = "2"` in the workspace root's manifest
    note: for more details see https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions
       Compiling add_two v0.1.0 (H:\temp\add\add_two)
       Compiling add_one v0.1.0 (H:\temp\add\add_one)
       Compiling adder v0.1.0 (H:\temp\add\adder)
        Finished `test` profile [unoptimized + debuginfo] target(s) in 0.38s
         Running unittests src\lib.rs (target\debug\deps\add_one-ebd2ec5e939dda0d.exe)
    
    running 1 test
    test tests::it_works ... ok
    
    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    
         Running unittests src\lib.rs (target\debug\deps\add_two-d92d41d98065439b.exe)
    
    running 1 test
    test tests::it_works ... ok
    
    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    
         Running unittests src\main.rs (target\debug\deps\adder-00ea61a7c623235d.exe)
    
    running 0 tests
    
    test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    
       Doc-tests add_one
    
    running 0 tests
    
    test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    
       Doc-tests add_two
    
    running 0 tests
    
    test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    
    
0

评论区