海哥 发表于 2024-12-15 10:47:19

rust学习十四.2、工作空间(workspace)

和大部分语言一样,cargo也可以创建一个工作空间,以便可以包罗多个二进制单元和库单元,从而构建较为复杂的工程。
构建这样一个空间空间主要依赖两个本领:Cargo.toml和单元之间的目录结构
从效果上看,rust的Cargo在工作空间上的管理和maven大体相似,但是还不如maven那么的人性化。
 
一、如何编写顶级Cargo.toml

我们先看看新版本的工作空间的规定:https://doc.rust-lang.org/cargo/reference/workspaces.html
https://img2024.cnblogs.com/blog/1177268/202412/1177268-20241215103444008-1763026337.png
翻译一下。
工作空间的关键点

[*]规定成员答应执行的命令
[*]所有成员共享一个Cargo.lock,看图1可以明白
[*]所有成员共享一个输出目录,看图1可以明白
[*]所有成员可以共享包元数据,这个通过定义workspace.package实现
[*]patch,replace,profile.*只能在顶级toml(工作空间)toml中定义,成员的无效
虚拟工作空间
假如你的工作空间配置(toml)不包罗package部分,那么者就是一个虚拟的工作空间。这种情况下,所有的成员的目录都是空间的子目录。
反之,就不是一个虚拟工作空间,也就是我们假如在顶级包中包罗了根包(root package),那么就不是一个虚拟工作空间。
作为一个非虚拟空间,也就意味着可以在工作空间配置中定义package有关的一些配置,详细略。
到底要不要虚拟工作空间,纯看个人喜好。
个人倾向于构建一个虚拟的工作空间,因为这个和maven工程更像。
不能做的事情
假如你定义了一个虚拟的工作空间,那么就不能在工作空间配置文件中包罗常规单元包所具有的一些配置,例如package,dependencies之类的。
否则编译通过不过
二、单元Cargo.toml

在一个工作空间中,可以有一个二进制包,多少个库单元包。
假如你执行cargo run,那么cargo会自动找到二进制包并运行。
二进制的配置和单独的一个二进制配置并没有什么区别,另有更多,主要是两点:

[*]共享工作空间的包配置(package),这个通过  xxx.workspace=true实现,这个xxx可以是name之外的一些包属性
[*]共享依赖,这也是工作空间的一个极其重要的目的,避免引入不同的外部单元包,导致版本冲突。这个通过dependencies中xxx.workspace=true实现
其它还包罗受限的命令、编译工具(lint)、外部工具元数据。
库单元配置同二进制单元配置,详细略
三、其它

工作空间所涉及的,不止本文提到的一些内容,完整的请参考 https://doc.rust-lang.org/cargo/reference/workspaces.html
四、例子

本文模仿了有关例子,并结合https://doc.rust-lang.org/cargo/reference/workspaces.html的内容,实现了一个简单的工作空间。
4.1、概述

整个空间包罗一个二进制库wsmain,以及两个库单元:teacher,student
整个目录结构如下:
图1_示例工作空间wsexample
https://img2024.cnblogs.com/blog/1177268/202412/1177268-20241215102717913-368576755.png
 
4.2、配置

共有四个配置文件,一个是工作空间的,三个是单元包的。重点看三个:
1.wsexample

members = [
    "student",
    "teacher", "wsmain",
]
resolver = "2"

version = "0.1.0"
edition = "2021"

rand = "0.9.0-beta.1"  
这个配置为所有的成员限定了包的发行版本和版本,并指定了共享的依赖rand。
2.wsmain

name = "wsmain"
version.workspace=true
edition.workspace=true


student={path="../student"}
teacher={path="../teacher"}这个配置指定了wsmain依赖的两个库包,并且包部分共享了工作的包配置(version,edition)
 
对工作空间内其它库单元依赖的定义是让我扫兴的地方,不够优雅,个人发起这样:
member.student=true
teacher.sutdent=true
 
3.student

name = "student"
version.workspace=true
edition.workspace=true

rand.workspace=true 
这个配置指定了student共享了工作空间的包配置,并指定了共享工作空间的依赖rand
 
4.3、代码

二进制单元main.rs代码
use teacher::*;
use student::*;

fn main() {
    let lml=studentinfo{
      name:String::from("lml"),
      age:18,
      gender:String::from("女"),
      no:String::from("12101")
    };
    print_student(&lml);
    lml.learn();
    lml.sleep();

    let lu=teacherinfo{
      name:String::from("lu"),
      age:46,
      gender:String::from("男"),
      position:String::from("教研组长"),
    };
    lu.teach_student(&lml);
    print_teacher(&lu);

 
4.4、运行
在一个虚拟工作空间内,无需指定包名,即可运行,例如
cargo run
https://img2024.cnblogs.com/blog/1177268/202412/1177268-20241215111855034-135334786.png
 假如硬要指定也可以,通过参数-p来指定包名,大概--package,例如:
cargo run -p wsmain
效果同cargo run 一样,详细略。
 
五、小结


[*]运用cargo也可以构建一个工作空间,以便包罗一个二进制单元和多个库单元
[*]在效果上,cargo的构建过程和效果雷同maven,但某些方面不如maven来得优雅
[*]本文所提到的知识,已经足以办理工厂常见问题:模块化、共享(配置和依赖)
[*]更到的高级特性,包罗编译,发布等等需要阅读更多相关资料
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: rust学习十四.2、工作空间(workspace)