当前位置: 首页 > news >正文

以Zed项目为例学习大型Rust项目的组织与管理

说明

  • Zed项目代码:https://github.com/zed-industries/zed.git
  • 本文项目代码:https://github.com/VinciYan/zed_workspace.git

Zed是一款由Atom创始人开发的高性能、协作友好的现代开源代码编辑器,使用Rust编写,集成AI辅助功能,旨在结合传统编辑器的速度和现代IDE的智能特性

Zed项目的组织和管理非常值得学习和研究。下面我将通过我总结后的得出一个精简版例子来说明Zed项目的结构,my_project对应Zed项目的crates文件夹下的zed文件夹

workspace_root/
├── Cargo.toml
└── crates/├── foo/│   ├── Cargo.toml│   └── src/│       └── lib.rs├── bar/│   ├── Cargo.toml│   └── src/│       └── lib.rs└── my_project/├── Cargo.toml└── src/└── main.rs

工作空间根目录的Cargo.toml

[workspace]
members = ["crates/foo", "crates/bar", "crates/my_project"]
default-members = ["crates/my_project"]
resolver = "2"[workspace.dependencies]
foo = { path = "crates/foo" }
bar = { path = "crates/bar" }
rand = "0.8.5"  # 添加 rand 作为工作空间依赖[workspace.lints.rust]
unsafe_code = "forbid"
unused_variables = "warn"[workspace.lints.clippy]
enum_glob_use = "deny"

members字段指定了属于该工作空间的所有crate(包)

  • 作用:

    • 定义工作空间结构:告诉Cargo哪些项目是这个工作空间的一部分
    • 允许集中管理:可以在工作空间级别管理依赖和构建设置
    • 启用共享编译:成员之间可以共享编译产物,提高构建效率
  • 灵活性:

    • 可以使用相对路径指定成员
    • 支持glob模式,如members = [“crates/*”] 可以包含crates目录下的所有crate

default-members指定了在没有明确指定目标的情况下,默认要构建、测试或运行的工作空间成员(crate)

  • 当你在工作空间根目录运行cargo build、cargo test或cargo run等命令时,如果没有指定具体的crate,Cargo会默认对default-members中列出的crate执行操作
  • 在配置中,default-members = [“crates/my_project”]意味着默认情况下,只有my_project会被构建或运行
  • 设置my_project为默认成员意味着你可以直接在根目录运行cargo run,而不需要指定–package my_project
  • 可以指定多个默认成员,例如:default-members = [“crates/my_project”, “crates/foo”]

resolver = "2"在工作空间的Cargo.toml文件中是一个重要的配置项,它指定了Cargo使用的依赖解析器版本

  • 版本

    • “1”: 旧版解析器(默认用于2015和2018版本的Rust)
    • “2”: 新版解析器(默认用于2021版本的 Rust)

注意到rand指定项目版本信息,这样的好处包括:

  • 在工作空间级别管理依赖版本,确保所有项目使用相同版本的rand
  • 简化了各个项目的Cargo.toml文件,使其更加清晰
  • 方便统一升级所有项目的依赖版本

需要注意的是,这种方式要求所有使用rand的项目都使用相同的版本。如果某个项目需要使用不同版本的rand,你可以在那个项目的Cargo.toml中明确指定版本,覆盖工作空间中定义的版本

例如,如果bar项目需要使用不同版本的rand:

[dependencies]
foo.workspace = true # 也可写成旧版本的Cargo中出现的foo = { workspace = true }
rand = "0.7.3"  # 使用特定版本,而不是工作空间版本

这种配置方式既灵活又统一,非常适合管理包含多个相关项目的工作空间

lint设置用于定义整个工作空间的代码质量和样式规则。好处:

  • 一致性:确保工作空间中所有项目遵循相同的代码规范
  • 安全性:通过禁止不安全代码提高项目的安全性
  • 代码质量:帮助开发者编写更清晰、更高质量的代码
  • 维护性:通过统一的规则,使代码更容易维护和理解

my_project项目

Cargo.toml

[package]
name = "my_project"
version = "0.1.0"
edition = "2021"[[bin]]
name = "my_project"
path = "src/main.rs"[dependencies]
foo.workspace = true
bar.workspace = true[lints]
workspace = true

src/main.rs

use bar::bar_function;
use foo::generate_random_number;fn main() {let num = 10;println!("Hello, world! {num} plus one is {}!", bar::add_one(num));bar_function();let random_number = generate_random_number();println!("Random number generated in bar: {}", random_number);
}

foo项目

Cargo.toml

[package]
name = "foo"
version = "0.1.0"
edition = "2021"[dependencies]
rand.workspace = true[lints]
workspace = true[lib]
path = "src/lib.rs"
doctest = false

src/lib.rs

use rand::Rng;pub fn add(left: u64, right: u64) -> u64 {left + right
}pub fn foo_function() {println!("This is a function from foo");
}pub fn generate_random_number() -> i32 {let mut rng = rand::thread_rng();rng.gen_range(1..=100)
}#[cfg(test)]
mod tests {use super::*;#[test]fn it_works() {let result = add(2, 2);assert_eq!(result, 4);}
}

bar项目

Cargo.toml

[package]
name = "bar"
version = "0.1.0"
edition = "2021"[lints]
workspace = true[lib]
path = "src/lib.rs"[dependencies]
foo.workspace = true

src/lib.rs

use foo::foo_function;pub fn bar_function() {println!("This is a function from bar library");foo_function(); // 调用 foo 中的函数
}pub fn add(left: u64, right: u64) -> u64 {left + right
}pub fn add_one(x: i32) -> i32 {x + 1
}#[cfg(test)]
mod tests {use super::*;#[test]fn it_works() {let result = add(2, 2);assert_eq!(result, 4);}
}

bar项目依赖foo项目,调用foo项目的foo_function函数

执行“Cargo run”,项目运行结果如下

Hello, world! 10 plus one is 11!
This is a function from bar library
This is a function from foo
Random number generated in bar: 13

最后,我还给出另一种项目代码组织方式,将my_project项目放到crates文件夹之外的版本,感兴趣的话,详见我的项目仓库

参考

  1. Announcing Rust 1.74.0 | Rust Blog (rust-lang.org)
  2. Workspaces - The Cargo Book (rust-lang.org)

相关文章:

以Zed项目为例学习大型Rust项目的组织与管理

说明 Zed项目代码:https://github.com/zed-industries/zed.git本文项目代码:https://github.com/VinciYan/zed_workspace.git Zed是一款由Atom创始人开发的高性能、协作友好的现代开源代码编辑器,使用Rust编写,集成AI辅助功能&a…...

正点原子imx6ull-mini-Linux驱动之Linux RS232/485/GPS 驱动实验(23)

错误1:我一直找不到为什么我的minicom用不了,编译啥的都通过了,原来是我的密码文件命名错了,我就习以为常的命名为password,谁知道应该是passwd,所以以后该复制的还是复制,不然就容易找不到源头…...

用户上下文打通+本地缓存Guava

文章目录 🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)🌟 亮点功能📦 spring cloud模块概览常用工具 🔗 更多信息1.设计1.链路流程2.详细设计 2.网关过滤器获取唯一标识放到Hea…...

Windows图形界面(GUI)-MFC-C/C++ - 树形视图(Tree Control) - CTreeCtrl

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 树形视图(Tree Control) - CTreeCtrl 创建和初始化 添加和删除项 获取和设置项属性 操作项 项选择变化 项双击 项展开 示例代码 树形视图(Tree Control) - CTreeCtrl 创建和初始…...

C语言 --- 枚举、位运算

(一)枚举 1.概念:枚举是指将变量的值一一列举出来,变量的值只限于列举出来的值的范围 2.作用:a.提高代码可读性;b.提高代码的安全性 3.枚举类型: enum 枚举名 { 列举各种值 //枚举元素或枚…...

12322222222

当您和老王不在同一个网段时,您们之间的通信需要通过路由器来实现。这是因为不同的网段被视为不同的网络,而路由器的作用之一就是连接不同的网络并负责数据包的转发。下面是详细的通信流程: 本地网络通信尝试:您的设备&#xff0…...

知识改变命运:Java 语言 【可变参数】

可变参数 概念:Java允许一个类中多个同名同功能但是参数不同的方法,封装为一个方法。 基本语法: 访问修饰符 返回值 方法名 (数据类型...参数名) { ...... }案例:写一个类名DyMethod 方法名sum 计算两个整数和,三个整…...

Spring及相关框架的重要的问题

Java框架 问题一:Spring框架中的单例bean是线程安全的吗? 看下图,不能被修改的成员变量就是无状态的类,无状态的类没有线程安全问题,所以在开发中尽量避免可修改的成员变量。 回答:不是线程安全的&#xf…...

Linux Vim教程

Linux Vim 教程 Vim(Vi IMproved)是一个强大的文本编辑器,广泛用于编程和系统管理。本文将带你全面了解 Vim 的基础使用、常用命令、高级功能等。 1. 安装 Vim 在大多数 Linux 发行版中,Vim 已经预装。如果没有,可以…...

【学习笔记】多进程信号量控制

目录 1、CreateSemaphore 2、ReleaseSemaphore 3、CreateEvent 4、SetEvent 5、WaitForSingleObject 程序案例1: 程序案例2: 1、CreateSemaphore 创建一个计数信号量对象,成功时返回信号量对象的句柄;失败时返回NULL&…...

Redis与Memorycache的区别

Redis与Memorycache主要是持久线程和持久化的区别 1、从性能方面来说: Redis是单线程的,优点是CPU开销小,省去多线程线程之间切换的开销,但是相对于Memorycache来说海量数据的相对较低 Memorycache使用了多线程技术,数…...

docker和Helm Chart的基本命令和操作

一、docker基本命令和操作 1. docker login【登录】 登录 docker client,登录成功之后会显示 Login Succeeded。 docker login登陆到指定的镜像仓库,docker pull 和 docker push 操作都需要预先执行 docker login 操作; 指令:&a…...

Node中的CSRF攻击和防御

Node中的CSRF攻击和防御 假设有一个网上银行系统,用户可以通过该系统进行转账操作。转账功能的URL可能是这样的: https://www.bank.com/transfer?toAccount123456&amount1000当用户登录到银行系统,并在浏览器中访问这个URL时&#xff…...

CSS 多按钮根据半圆弧度排列

需求 多个按钮根据弧度&#xff0c;延边均匀排列。 实现 HTML 分两级&#xff1b;第一级&#xff0c;外层定义按钮的 compose-container 宽度&#xff1b;第二级&#xff0c;按钮集合&#xff0c;使用方法 styleBtn(index)&#xff0c;根据索引计算&#xff1b; <div c…...

【Linux】网络编程套接字Scoket:UDP网络编程

目录 一、了解UDP协议 二、了解端口和IP地址 三、套接字概述与Socket的概念 四、Socket的类型 五、 Socket的信息数据结构 六、网络字节序与主机字节序的互相转换 七、地址转换函数 八、UDP网络编程流程及相关函数 socket函数 bind函数 recvfrom函数 sendto函数 …...

基于模糊PID控制器的puma560机器人控制系统的simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 PUMA 560机器人的数学模型 4.2 PID控制原理 4.3 模糊PID控制器的设计 5.完整工程文件 1.课题概述 基于模糊PID控制器的puma560机器人控制系统的simulink建模与仿真&#xff0c;对比传统的PID控制器…...

C语言文件操作超详解

文章目录 1. 为什么使用文件2. 什么是文件2. 1 程序文件2. 2 数据文件2. 3 文件名3. 二进制文件和文本文件? 4. 文件的打开和关闭4. 1 流和标准流4. 1. 1 流4. 1. 2 标准流 4. 2 文件指针4. 3 文件的打开和关闭 5. 文件的顺序读写5. 1 顺序读写函数介绍5. 2 对比一组函数: 6. …...

表字段显示tip

需求背景&#xff1a; 生成的报表&#xff0c;前端只展示字段名称&#xff0c;计算逻辑没有解释&#xff0c;使用方频繁“骚扰”&#xff0c;实在受不了&#xff0c;增加一个字段tip&#xff0c;实现效果&#xff08;下图&#xff09;&#xff1a; 代码 结合使用el-table-colu…...

十二、享元模式

文章目录 1 基本介绍2 案例2.1 Digit 接口2.2 Color 枚举2.3 BigDigit 类2.4 DigitFactory 类2.5 Client 类2.6 Client 类的测试结果2.7 总结 3 各角色之间的关系3.1 角色3.1.1 Flyweight ( 抽象享元 )3.1.2 ConcreteFlyweight ( 具体享元 )3.1.3 UnsharedFlyweight ( 非享元 )…...

黑马Java零基础视频教程精华部分_18_Arrays各种方法

系列文章目录 文章目录 系列文章目录Arrays简介Arrays各种方法toString代码示例binarySearch代码示例copyOf代码示例copyOfRange和fill代码示例sort代码示例 Arrays简介 操作数组的工具类。 Arrays各种方法 toString代码示例 int[]arr{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; //to…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...

React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾&#xff1a; 在上一篇《React核心概念&#xff1a;State是什么&#xff1f;》中&#xff0c;我们学习了如何使用useState让一个组件拥有自己的内部数据&#xff08;State&#xff09;&#xff0c;并通过一个计数器案例&#xff0c;实现了组件的自我更新。这很棒&#…...

五、jmeter脚本参数化

目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …...