Rust 之一 基本环境搭建、各组件工具的文档、源码、配置
概述
Rust 是一种强调性能、类型安全和并发性的通用编程语言。它强制执行内存安全,使用其特有的所有权机制,而无需传统的垃圾收集器。Rust 不强制执行编程范式,但受到函数式编程思想的影响。
- 最初是由 Mozilla 员工 Graydon Hoare 在 2006 年作为个人项目创建的
- Mozilla 于 2009 年正式赞助了该项目
- Rust 是一门编译型的语言。最初,其编译器是用大约 38000 行 OCaml 编写,在 2009 年之后,开始用 Rust 语言基于 LLVM 编写自托管编译器
- 在 2015 年 5 月发布第一个稳定版
Rust 环境
一门新的编程语言,除了有自己的词法与语法、类型系统、执行模型等基本语义与核心特性之外,通常还得有配套的工具链(编译器、标准库、链接器)或解释器、包管理器、构建工具等配套的开发工具。
通常,根据编译型语言与解释型语言而不同所包含的工具不同,Rust 是一种预编译静态类型(ahead-of-time compiled)的编程语言,因此,它有一套自己的编译工具链以及相关工具。(实际上,还有一种混合型语言,例如,Angular ,这两种方式都支持)
许多古老的编程语言,例如,C 语言,其诞生之初就只有语言标准与编译器,而不是一开始就设计有其他一些工具。然后,在以后的其逐渐变为流行的过程中,才诞生了一些配套的开源或者商业的构建工具,编译工具链等等!
Rust 组件
Rust 是一种预编译静态类型(ahead-of-time compiled)的编程语言,除了有基本的 Rust 编程语言标准之外,Rust 官方还提供了一系列适用于各个平台的开发辅助工具以及编译工具链来帮助我们处理 Rust 代码。
所有的这些工具都是由一个名为 rustup
的命令行工具来统一管理!并且,rustup
引入了 component
、profile
、proxy
等基本概念来组织和管理所有相关工具的发布!我们在后续搭建 Rust 开发环境以及开发过程中都需要用到这些概念,因此,我们先来来看看这些概念!
Proxies
Rust 官方提供了分别适用于 Windows、Linux、MacOS 等目前主流操作系统平台的工具,即使是在同一个操作系统平台下,也有不同的版本,为了统一不同版本的工具的区别,Rust 采用了使用统一的代理程序来作为对外工具,从而屏蔽不同版本工具的差异的方法。
当我们安装了 Rust 之后,安装目录的 .cargo/bin
目录中的这些可执行程序(rustup
除外)实际上是 .rustup/toolchains/发行版/bin
中真实工具的包装器,官方称其为 Proxies。 他们都是通过调用 .rustup/toolchains/发行版/bin
目录中的对应工具来实现功能的!
.cargo/bin
中包含了所有可用工具的代理,.rustup/toolchains/发行版/bin
却不一定包含所有实际的工具,安装时的 Profiles 实际表示的是要安装到 .rustup/toolchains/发行版/bin
中的组件的多少。
仔细观察 .cargo/bin
中的各个可执行文件就会发现他们的大小是一模一样的,这是因为他们(包括安装时使用的 rustup-init
)实际上都是 rustup
改成了不同的名字,rustup
程序会根据名字的不同执行不同的操作,后文 Rustup 章节详细介绍。
Components
Rust 官方将其提供的开发辅助工具、编译工具链、其他一些库等组织为了 Components 的形式的集合。组件是属于编译工具链,增减组件都是指的增减当前编译工具链中的组件。组件位于 .rustup/toolchains/发行版/
下对应的子目录中,其中 .rustup/toolchains/发行版/lib/rustlib/components
文件中就记录了针对当前编译工具链安装的组件。
组件名 | 包含的工具 | 介绍 |
---|---|---|
rustc | rustc 、rustdoc | 编译工具链、文档工具 |
cargo | cargo | 包管理器 |
rustfmt | rustfmt 、cargo-fmt | 代码格式化工具 |
rust-std | 无 | 这是 Rust 标准库。对于 rustc 支持的每个目标平台,都有一个单独的 rust-std 组件。例如安装了 rustc-x86_64-pc-windows-msvc,就会同步安装 rust-std-x86_64-pc-windows-msvc |
rust-docs | 无 | Rust 文档的本地版本(静态 HTML 格式),位于 .rustup/toolchains/发行版/share/doc/rust 目录中 1. 使用命令 rustup doc 就可以在浏览器中打开 2. 这里的文档主要是 https://github.com/rust-lang/rust 这个仓库中的 src/doc (现在,很多文档被移到了子仓库维护)下的文档,很多独立工具的文档不在其中 |
rust-analyzer | rust-analyzer | Rust 语言服务器协议的实现,用于配合 VS Code、Emacs 等实现 Rust 语言的编辑功能。 1. 这个工具通常会以编辑器插件的形式提供,并不会单独安装 2. 官方也不建议单独安装,它会覆盖编辑器插件中集成的 rust-analyzer,而导致出错 |
clippy | cargo-clippy 、clippy-driver | 代码检查工具 |
miri | 无 | Miri 是一个实验性的 Rust 解释器,可用于检查未定义的行为 1. 目前不提供给 Stable 通道 |
rust-src | 无 | Rust 标准库源代码的本地副本,位于 .rustup/toolchains/发行版/lib/rustlib/src 目录中,某些工具,例如 rust-analyzer 会使用源码来提供一些功能 1. https://github.com/rust-lang/rust 这个仓库中的 library 目录中的内容2. 此外还包括 LLVM 的 libunwind 的源码3. 默认不会安装该组件,需要使用 rustup component add rust-src 来手动安装 |
rust-mingw | ld | 它包含一个用于构建在 x86_64-pc-windows-gnu 平台上的链接器和平台库,位于 .rustup/toolchains/发行版/lib/rustlib/x86_64-pc-windows-gnu 目录中1. 默认安装 x86_64-pc-windows-gnu 后就包含了 rust-mingw |
llvm-tools | LLVM 官方的那些工具 | 包含 LLVM 工具的集合,位于 .rustup/toolchains/发行版/lib/rustlib/x86_64-pc-windows-gnu 目录中 |
rustc-dev | 无 | 此组件将编译器包含为库,用于开发 Rust 的编译器,一般用不到 |
rls | rls | RLS 是一种语言服务器,已被废弃,并被 rust-analyzer 所取代。 |
rust-analysis | 无 | RLS 使用的标准库的元数据 |
- 有些组件是区分不同的架构平台的,全名是
组件名-编译工具链名
,例如,cargo-x86_64-pc-windows-gnu
,通过rustup component list
可以看到所有的组件及当前安装情况
- 使用
rustup component xxx
相关命令来查看、添加或者删除组件,当我们使用rustup component add 上表中的组件名
时,就会从 Rust 官方网站下载对应的组件放到.rustup/toolchains/发行版/
中。
- 组件并不是提供到所有发布通道的,有些通道没有某些组件。例如,上面的
miri
只提供给 Nightly 通道
Profiles
Profiles 代表了要安装的 Rust 开发辅助工具的集合,不同的 Profiles 包含的组件不同,共有 minimal、default、complete 三种 profile 可选。如果选了 minimal 后续也可以使用 rustup component add xxx
命令手动安装需要的工具。
- minimal 包含 rustc、rust-std、cargo;default 则在 minimal 基础上添加了 rust-docs、rustfmt、clippy,是官方推荐的;complete 包含所有组件,官方强烈不推荐使用,因为会出错
- 使用
rustup set profile minimal
可以更改默认的 Profile - 使用
rustup install --profile <name>
可以在安装工具链时指定 Profile
版本发布
随着对 Rust 了解的逐渐深入,就会发现 Rust 的发布有版本(Version)、发行版(Release)、版次(Edition)这三个不同维度概念,对于初学者来说比较难以理解这三者的具体区别。官方也没有一个简单明了的解释来说明三者之间的具体含义或区别。
版本
版本这个概念对应于 Version 这个词,Rust 采用语义化版本号来表示不同的版本,格式为 x.y.z
,例如,Rust 1.79.0。这个语义化版本号即是 Rust 语言的版本号又同时是 Rust 工具链的版本号,我们通常说使用特定版本的 Rust,实际上就是指的使用特定版本的 Rust 工具链。
- Rust 的工具链总是与 Rust 语言一同发布,通过 https://github.com/rust-lang/rust 这个源码仓库来维护,他们的版本号都是语义化版本号
- Rust 中的软件包也使用语义化版本号,其项目管理工具 Cargo 以语义化版本号的相关规则来判断包版本兼容,详见后文说明
发行版
发行版这个概念指的是 Rust 版本(Version)的交付方式。Rust 版本(Version)的交付采用了 Nightly、Beta、Stable 三个不同的 Channels 来进行发布。采用不同 Channels 这种交付模式被称为 Release Train Model,这是一种需求收集、分析、决策、发布、问题反馈的产品开发模型。
每一个 Rust 版本(Version)都会依次经过这三个 Channels 而进行发布。Nightly 是正在开发的版本、每晚自动构建、自动发布;Beta 是测试版本,每 6 周从 Nightly 生成一次,包含新特性;Stable 是稳定版本,每 6 周从 Beta 生成一次。如下是目前各个 Channel 中发布的 Rust 版本(Version):
-
Rust 语言与编译工具链是密切相关的,因此,发行版通常是指的编译工具(及相关工具)的交付方式
-
发布情况可以从 Rust Forge 上获取
-
用户通过官方提供的
rustup
工具就可以非常方便的安装及使用不同的发行版 -
Rust 的很多特性只在特定的 Channels 中发布,例如,当前 unstable 的特性,只提供给 Nightly 通道!
版次
版次这个概念对应官方的 Edition 的概念,直接使用一个年份来表示,例如,Rust 2021 Edition,中文翻译为版次主要是为了与版本(Version)来进行区分。这个概念侧重于 Rust 这门编程语言的版本,就类似于 C99、C++11、C++17 等标准,不同的版次之间往往会出现很多不兼容的特性!
-
每个 crate 在其
Cargo.toml
文件中使用edition = xxx
指定其使用的版次
-
版次不是周期性发布的,只有 Rust 项目组认为确有必要时才会发布。目前可用的版次是 2015、2018、2021、2024 这四个
-
发布情况在 The Rust Edition Guide 中有详细记录
开发环境
我们说使用一门编程语言,一方面是根据语法编写源代码,另一方面就是使用各种工具处理代码。因此,要使用 Rust 语言开发,首先就要下载安装官方提供的各种工具来搭建 Rust 的开发环境。
对于使用 Rust 进行开发,官方并没有一个统一的 IDE,用户可以任意选择。不过,官方推荐了一些常用代码编辑器,这些编辑器通过搭配官方提供的开发辅助工具中的 rust-analyzer
就可以完美实现 Rust 代码的开发。
工具安装
代码编辑器(推荐是 VSCode)使用者根据自己的喜好选择安装即可,而开发辅助工具及编译工具链则需要单独进行安装。Rust 官方提供了预编译好的工具可执行程序,并通过名为 rustup
的工具统一安装及管理。
打开 Rust 的官方网站会自动侦测我们使用的操作系统,并给出对应的安装方法。对于 Windows 系统,我们需要下载运行官网的 rustup-init.exe
来安装 Rust 相关工具,而对于 Linux 或 macOS 系统,则需要在自己系统命令终端中使用命令 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
来进行安装。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
实际上就是下载名为 rustup-init.sh
的 Shell 脚本并执行,而 rustup-init.sh
脚本中就会下载 rustup-init
可执行程序来进行安装,因此,不同的平台下的安装过程基本一致!
-
实际上,
rustup-init
本身就是rustup
改了一个名字,rustup
实现了根据自身名字的不同来执行不同的功能,详见后文rustup
章节! -
rustup-init
总是默认下载安装最新版。下载源位于国外,因此下载速度会很慢,偶尔还会下载失败,多试几次即可!此外,还可以通过定义如下环境变量(例如,在 Linux 的~/.bashrc
中增加)来将 Rustup 切换为国内的镜像源export RUSTUP_DIST_SERVER="https://rsproxy.cn" export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup"
-
使用 MSVC 作为 ABI 的工具链(仅限于 Windows 系统)时,需要安装 Visual Studio 或 Visual C++ Build Tools,如果当前系统没有安装,安装过程中会提示下载;使用 GNU 作为 ABI 的工具链(无论是 Windows 还是类 Unix 系统)时则需要安装 GCC。
-
根本原因是 Rust 编译工具链需要使用他们提供的链接器,详见博文 Rust 之三 编译工具链、构建过程 中的介绍
-
Windows 系统
- MSVC:现在 Visual Studio 是通过 Visual Studio Installer 在线组件化安装,对于 Rust,需要 MSVC 和 Windows SDK,例如:
- MSVC v143 - VS 2022 C++ x64/x86 build tools (Latest)
- Windows 11 SDK (10.0.22621.0)
- 注意,由于 Visual Studio 默认会使用本地编码(中文就是 GBK),可能会导致 Rust 会出现乱码,通常通过切换语言就可以解决!
- GCC:通常是采用 MinGW-w64 或类似于 MSYS2、Cygwin 这类包含 MinGW-w64 环境。不推荐,会出现一些问题需要自行解决!
- MSVC:现在 Visual Studio 是通过 Visual Studio Installer 在线组件化安装,对于 Rust,需要 MSVC 和 Windows SDK,例如:
-
类 Unix 系统
- 直接使用系统命令安装系统官方提供的 GCC 工具链即可
-
-
host triple 就是我们要安装的编译工具链,格式基本类似于 GNU 的
<arch>-<vendor>-<sys>-<abi>
。对于 Windows 平台,可以用 MSVC 或 GNU 作为 ABI 的工具链,默认采用 MSVC 版,而对于类 Unix 系统,则只有 GNU 作为 ABI 的工具链。关于编译工具链,参见博文 Rust 之三 编译工具链、构建过程 中的详细介绍
-
default toolchain 这个就对应编译工具链的 Stable、Beta、Nightly 三个不同 Channel 的发行版,默认安装 Stable 通道中最新版本的发行版。实际上这里也可以指定一个版本号,例如 1.79,来安装特定版本的!
-
profile 就是上文 Profiles 章节介绍的
安装目录
通过上面的安装过程可以看到,开发辅助工具及编译工具链被安装到了当前用户目录下的 .cargo
和 .rustup
目录中。其中,.cargo
目录中包含了 Rust 所有开发工具的统一接口,还包括我们下载的各种第三方包;而 .rustup
目录中则包含了特定于平台的编译工具链以及相关辅助工具!
detected conflict
有时候,我们在使用 Rust 时会收到如下所示的错误 error: failed to install component: 'rustc-x86_64-unknown-linux-gnu', detected conflict: 'lib/rustlib/x86_64-unknown-linux-gnu/bin/llc'
,目前需要等等官方解决,详见 https://github.com/rust-lang/rustup/issues/2417!
rustup
rustup 是 Rust 官方提供的相关实用工具以及编译工具链的安装及管理器,使用 rustup
这个工具就可以自动为我们下载安装官方的 Rust 各工具的发行版,并且可以在不同的发行版之间自由切换。
rustup
是一个命令行工具,对应的可执行程序名为 rustup
,详细的使用方法见上图中的命令行参数说明即可。rustup
本身就是代理的原型,它自身没有代理!
源码
rustup 的源码仓库为 https://github.com/rust-lang/rustup,源码本身就是一个 Rust 项目工程,因此,我们可以使用 cargo build
命令一键编译出名为 rustup-init
可执行程序,这个是 rustup-init
实际上就是 rustup
,详见下面的说明。
-
rustup
源码中实现了根据名字的不同而实现不一样的功能,.cargo/bin
中的各个工具以及我们安装使用的rustup-init
实际上都是它改成了不同名字。 详见src\bin\rustup-init.rs
中函数main()
➜run_rustup()
➜run_rustup_inner()
的内容
-
对于类 Unix 系统,官方推荐的
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安装方法实际上就是下载并执行源码中的rustup-init.sh
这个脚本 -
rustup 是 multirust 的继承者。Rustup 最初是 multiust-rs,由 Diggory Blake 将 multirust 从 shell 脚本改写为 Rust,现在由 Rust 项目维护。
文档
- 官方在线文档有如下两个
- The rustup book!
- The Rustup developer guide
- 文档的源码位于 rustup 源码的 doc 目录下,使用的是 mdBook 文档系统,详细介绍参见后文的 mdBook 章节的介绍
配置
rustup
(rustup-init
) 会自动读取 CARGO_HOME
和 RUSTUP_HOME
这两个环境变量的值,其中,CARGO_HOME
指定了 Cargo 相关工具以及缓存的存放位置, 而 RUSTUP_HOME
则指定了编译工具链的位置。
RUSTUP_DIST_SERVER
(之前叫RUSTUP_DIST_ROOT
,现已弃用 )指定了编译工具链的下载的地址,默认是 https://static.rust-lang.orgRUSTUP_UPDATE_ROOT
指定了rustup
自更新的地址,默认值是 https://static.rust-lang.org/rustup- 其他配置项见 https://rust-lang.github.io/rustup/environment-variables.html
Cargo
Cargo 是 Rust 的包管理器,可以用于依赖包的下载、编译、更新、分发等操作。同时, Cargo 还是一个命令行项目管理工具,它有一套自己的项目结构,可以帮助我们自动调用编译工具链来编译 Rust 项目源码。
cargo
是一个命令行工具,对应的可执行程序名为 cargo
,详细的使用方法见上图中的命令行参数说明即可。当我们使用时实际上是通过 .cargo/bin/cargo
这个代理来调用 .rustup/toolchains/发行版/bin/cargo
这个真正的可执行程序。
-
Cargo 默认的工作目录为
$HOME/.cargo
,其中的目录说明如下:
bin
:包含了通过cargo install
(只有拥有二进制目标文件的包能够被安装,并会被安装到$HOME/.cargo/bin
中) 或rustup
下载的包编译出的可执行文件。可以(默认)将该目录加入到$PATH
环境变量中,以实现对这些可执行文件的直接访问registry
:这个是 Cargo 下周的各种 Crate 的缓存目录,包含了注册中心(例如 crates.io)的元数据和 Packagesindex
: 包含了注册中心中所有可用包的元数据( 版本、依赖等 )cache
: 保存了已下载的依赖,这些依赖包以 gzip 的压缩档案形式保存,后缀名为.crate
src
: 若一个已下载的.crate
被一个 package 所需要,该档案会被解压缩到此目录下,最终 rustc 可以在其中找到所需的 .rs 文件
-
Cargo 管理的项目的基本单位被称为
Package
。一个 Package 中至少包含一个 Crate;一个 Package 中最多只能包含一个库 Library Crate;一个 Package 中可以包含任意多个 Binary Crate,详见之后的博文 Rust 之二 项目管理、文档规范、编码规范。 -
Cargo 内置的子命令只有
build
、check
、doc
、run
、test
、remove
等几个,当输入其他子命令时,它支持自动查找cargo-xxx
的其他可执行文件,详见后文源码章节的说明! -
绝大多数情况下,我们都是使用
cargo
命令来编译项目,而不是直接使用rustc
。
cargo-binutils
cargo-binutils 是由 Rust 官方的嵌入式工作组(Rust on Embedded Devices Working Group)中的工具组(Embedded WG Tools team)维护的一个非官方项目,这个项目可以为我们的 cargo
命令增加一些子命令,使用这些子命令可以直接调用指定编译工具链对应的 LLVM 的相关工具。
安装
cargo install cargo-binutils
rustup component add llvm-tools
示例
cargo objcopy
用于将 ELF 转换为 BINcargo nm
输出符号表cargo objdump
反汇编
cargo build
cargo build
会编译我们的项目代码,结果会被放入项目根目录下的 target
文件夹中,target 目录的结构取决于是否使用 --target
标志为特定的平台构建。target
的位置可以通过设置 CARGO_TARGET_DIR
环境变量、build.target-dir
配置项以及 --target-dir
命令行参数这三种方式来更改。
cargo build --verbose
可以看到调用rustc
的详细参数- 编译库时,Cargo 会自动使用
rustc
的--crate-type lib
选项,进而生成.rlib
的库文件;编译可执行程序时,Cargo 会自动使用rustc
的--crate-type bin
,进而生成可执行文件 - 对于每个 Crate 的编译,Cargo 都会为
rustc
指定--extern
选项,给出当前 crate 将使用的每个库的文件名,Rust 会将代码静态链接到最终的可执行文件中
不使用 --target
若不使用 --target 标志,则 Cargo 会根据宿主机架构进行构建,构建结果会放入项目根目录下的 target 目录中,target 下每个子目录中包含了相应的发布配置 profile 的构建结果,例如 release、debug 是自带的 profile,前者往往用于生产环境,因为会做大量的性能优化,而后者则用于开发环境,此时的编译效率和报错信息是最好的。
目录 | 描述 |
---|---|
target/debug/ | 包含了 dev profile 的构建输出(cargo build 或 cargo build --debug) |
target/release/ | release profile 的构建输出,cargo build --release |
target/foo/ | 自定义 foo profile 的构建输出,cargo build --profile=foo |
除此之外我们还可以定义自己想要的 profile ,例如用于测试环境的 profile: test,用于预发环境的 profile :pre-prod 等。出于历史原因:
- dev 和 test profile 的构建结果都存放在 debug 目录下
- release 和 bench profile 则存放在 release 目录下
- 用户定义的 profile 存在同名的目录下
使用 --target
当使用 --target XXX
为特定的平台编译后,输出会放在 target/XXX/
目录下:
target 子目录说明
在 profile 文件夹中(例如 debug 或 release)包含编译后的最终成果:
目录 | 描述 |
---|---|
target/debug/ | 包含编译后的输出,例如二进制可执行文件、库对象( library target ) |
target/debug/examples/ | 包含示例对象( example target ) |
还有一些命令会在 target 下生成自己的独立目录:
目录 | 描述 |
---|---|
target/doc/ | 包含通过 cargo doc 生成的文档 |
target/package/ | 包含 cargo package 或 cargo publish 生成的输出 |
Cargo 还会创建几个用于构建过程的其它类型目录,它们的目录结构只应该被 Cargo 自身使用,因此可能会在未来发生变化:
目录 | 描述 |
---|---|
target/debug/deps | 依赖和其它输出成果 |
target/debug/incremental | rustc 增量编译的输出,该缓存可以用于提升后续的编译速度 |
target/debug/build/ | 构建脚本的输出 |
源码
Cargo 的源码仓库为 https://github.com/rust-lang/cargo,源码本身就是一个 Rust 项目工程,因此,我们可以使用 cargo build
命令一键编译出名为 cargo
可执行程序。
Cargo 会自动查找 cargo-
开头的其他可执行文件,并把他们作为子命令来使用!
文档
- 官方在线文档
- The Cargo Book
- 文档的源码位于 Cargo 源码的
/src/doc
目录下,使用的是 mdBook 文档系统,详细介绍参见后文的 mdBook 章节的介绍
配置
Cargo 在工作时会自动读取 Windows 平台下的 %USERPROFILE%\.cargo\config.toml
或者类 Unix 系统下的 $HOME/.cargo/config.toml
或者当前项目目录下的 .cargo/config.toml
中的配置信息(在 cargo 1.38 及以前的配置版本使用文件名 config
)。其中,当前项目目录下的 .cargo/config.toml
优先级高于系统用户目录下的配置文件!config.toml
中的内容最常用的就是更改软件包的镜像源地址。
-
在 crates.io 之外添加新的注册服务,配置如下:
[registries] ustc = { index = "https://mirrors.ustc.edu.cn/crates.io-index/" }
对于这种方式,我们的项目的 Cargo.toml 中的依赖包引入方式也得对应的改
[dependencies] time = { registry = "ustc" }
-
直接使用新注册服务来替代默认的 crates.io,配置如下
[source.crates-io] replace-with = 'ustc' [source.ustc] registry = "sparse+https://mirrors.ustc.edu.cn/crates.io-index/"
示例:
[source.crates-io] registry = "https://github.com/rust-lang/crates.io-index" replace-with = "ustc" # 或 rustcc、sjtu、tuna # 根据 replace-with 配置的镜像源,以下只需配置一个对应的源即可 # 中国科大 [source.ustc] registry = "git://mirrors.ustc.edu.cn/crates.io-index" # rustcc 社区 [source.rustcc] registry = "https://code.aliyun.com/rustcc/crates.io-index.git" # 上海交通大学 [source.sjtu] registry = "https://mirrors.sjtug.sjtu.edu.cn/git/crates.io-index" # 清华大学 [source.tuna] registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"
-
CARGO_TARGET_DIR
定义了构建输出目录,默认是target
-
CARGO_HOME
这个环境变量定义了 Cargo 默认所在的目录,其中包含了 Cargo 可执行程序、配置文件、缓存文件等等,我们通过修改这个环境变量就可以重定位 Cargo 的位置。-
Windows 平台下默认值是
%USERPROFILE%\.cargo
;Unix 类系统下默认值是$HOME/.cargo
-
当我们使用 Cargo 构建项目时,下载的各种 crates 就位于
.cargo/registry
目录中
-
Clippy
Clippy 是Rust 官方开发的一个基于 LLVM 的 Rust 代码检测及优化工具(类似于 PC-lint 这类工具),它可以自动检测 Rust 代码中的潜在问题,并提供相应的建议。Clippy 使用 Lint 规则来检查代码,这些规则基于 Rust 的编译器插件系统。
cargo-clippy
是一个命令行工具,对应的可执程序为 cargo-clippy
。当我们使用时实际上是通过 .cargo/bin/cargo-clippy
这个代理来调用 .rustup/toolchains/发行版/bin/cargo-clippy
这个真正的可执行程序。
cargo clippy
通常,cargo-clippy
是作为 cargo
命令的一个子命令 cargo clippy
来间接使用
clippy-driver
Clippy 可以抛开 Cargo 来独立使用,此时需要使用 clippy-driver
命令,其参数则需要与 rustc
的参数相同,例如 clippy-driver --edition 2018 -Cpanic=abort foo.rs
。
配置
默认情况下,cargo-clippy
会自动查找名为 clippy.toml
或 .clippy.toml
的文件,搜索的位置优先级由高到低为 CLIPPY_CONF_DIR
、CARGO_MANIFEST_DIR
、当前项目目录,并执行其中的规则。
-
除了配置文件中存放的部分 Lint 规则外,还可以直接在
cargo-clippy
的命令行中指定一些规则。 -
目前,Clippy 中包含了超过 700 条 lints,这些 lints 被划分为了多个类别,每个类别都对应一个默认的 lint level。在
rustc
中,Lint 被分为了 allow、warn、force-warn、deny、forbid 这 5 level。
-
Cargo.toml
中的[lints.clippy]
中也可以指定一些规则 -
在源代码中也可以使用特定的属性,例如
#![allow(clippy::all)]
来指定规则
源码
Clippy 的源码仓库为 https://github.com/rust-lang/rust-clippy,源码本身就是一个 Rust 项目工程,因此,我们可以使用 cargo build
命令一键编译出名为 cargo-clippy
和 clippy-driver
的可执行程序。
文档
-
官方文档 Clippy Documentation
-
文档的源码位于 Clippy 源码的 book 目录下,使用的是 mdBook 文档系统,详细介绍参见后文的 mdBook 章节的介绍
Rustfmt
Rustfmt 是 Rust 官方提供的格式化 Rust 代码的工具(类似于 LLVM 的 clang-format
这类工具),它根据一些预定义的规则(括号的使用、缩进的级别、空格的添加等)来自动将 Rust 代码格式化为统一的风格。
rustfmt
是一个命令行工具,对应的可执程序为 rustfmt
,使用命令 rustfmt [options] <file>...
来对指定的源码文件来进行格式化。当我们使用时实际上是通过 .cargo/bin/rustfmt
这个代理来调用 .rustup/toolchains/发行版/bin/rustfmt
这个真正的可执行程序。
cargo fmt
通常 rustfmt 会被作为 cargo
命令的一个子命令 cargo fmt
来间接使用,完整格式是 cargo fmt [OPTIONS] [-- <rustfmt_options>...]
,其中的 [-- <rustfmt_options>...]
会直接传递给 rustfmt
来进行使用,因此它的取值就是 rustfmt 的选项。
cargo-fmt
此外,rustfmt 默认还会提供一个名为 cargo-fmt
的可执行程序,这个工具的作用于 cargo fmt
类似,不过它不依赖于 Cargo 这个工具进而实现类似的功能,因此,在不用 Cargo 时,我们可以直接使用 cargo-fmt
来一键格式化整个项目的源文件。
配置
在默认情况下,rustfmt
会自动读取当前项目各级目录下的 rustfmt.toml
或 .rustfmt.toml
文件,并根据其中的规则来进行格式化配置文件所在的目录的代码。如果子目录下没有配置文件,但是它的父级目录有,则根据父级目录的配置文件格式化。
- 如果项目目录下不存在
rustfmt.toml
或.rustfmt.toml
,则会尝试读取用户目录 - 如果用户目录下也没有,则读取 rustfmt 全局配置目录下的全局配置文件
- 配置文件中的各种规则直接查看源码中的
Configurations.md
或者使用在线 https://rust-lang.github.io/rustfmt/ 版本,两者是一样的!
源码
Rustfmt 的源码仓库为 https://github.com/rust-lang/rustfmt,源码本身就是一个 Rust 项目工程,因此,我们可以使用 cargo build
命令一键编译出名为 cargo-fmt
和 rustfmt
的可执行程序。
文档
目前,Rustfmt 的文档就是源码里的 Configurations.md
,源码目录的 docs
中的 index.thml
中就是通过 JavaScript 调用的 Configurations.md
的内容!
rust-analyzer
rust-analyzer 是 Rust 编程语言的语言服务器协议的实现。它为许多代码编辑器(VS Code、 Emacs 和 Vim)提供了代码完成、语法高亮和转到定义等特性。它也是一个命令行工具,不过,我们通常不会直接使用它,而是由代码编辑器插件来帮我们调用。
-
由于 rust-analyzer 通常不会由我们直接使用,所以,默认安装 Rust 后没有 rust-analyzer
-
实际上就是一个模块化编译器前端或者说一个动态分析库,通过 LSP(Language Server Protocol)与 VS Code、 Emacs 和 Vim 等通信
-
rust-analyzer 依赖 Rust 标准库的源码,通常需要手动执行
rustup component add rust-src
来安装,安装后的位置为.rustup\toolchains\toolchain_name\lib\rustlib\src\rust
-
rust-analyzer 提供的功能都是通过调用其他 Rust 工具来实现的,例如,代码格式就会调用
rustfmt
源码
rust-analyzer 的源码仓库为 https://github.com/rust-lang/rust-analyzer,源码本身就是一个 Rust 项目工程,因此,我们可以使用 cargo build
命令一键编译出名为 rust-analyzer
和 rust-analyzer-proc-macro-srv
的可执行程序。
文档
官方在线文档 。
- 官方在线文档
- https://rust-analyzer.github.io/manual.html
- 文档的源码位于 rust-analyzer 源码的 docs 目录下,,使用的是 mdBook 文档系统,详细介绍参见后文的 mdBook 章节的介绍
配置
配置项众多,参见 https://rust-analyzer.github.io/manual.html#configuration 即可。
mdBook
mdBook 是一个使用 Markdown 创建出在线文档网站的命令行工具。它是创建产品或 API 文档、教程、课程材料或任何需要简洁、易于导航和可定制的演示文稿的理想工具。Rust 提供的绝大多数文档都是使用 mdBook 来构建的!
安装
默认安装 Rust 后比不会安装 mdbook
,我们需要使用 cargo install mdbook
手动进行安装,mdbook
可执行文件会被放到 .cargo/bin
目录中。也可以直接在 https://github.com/rust-lang/mdBook/releases 上下载预编译好的可执行文件来使用!或者直接从源码构建出可执行程序!
目录结构
使用 mdbook init xxx
命令就会创建出名为 xxx 的文档目录结构,自动生成如下所示的目录结构
-
book.toml
文件按是配置文件 -
新增的 Markdown文章都要放到 src 目录下,可以自行创建子目录来进行分类存放
-
src/SUMMARY.md
是所有文章的目录,新增的 Markdown文章都需要在这里面写一下 -
book
文件夹用于存放 mdBook 构建后产生的 HTML 的文档
发布文档
在文档目录中,执行 mdbook build
就可以一键生成 HTML 格式的静态网页文档,默认存到当前目录的 book
文件夹中。在编写时,可以使用 mdbook serve
命令可以启动本地 Web 服务器,我们可以直接在浏览器中以 localhost 进行预览
源码
mdBook 的源码仓库为 https://github.com/rust-lang/mdBook,源码本身就是一个 Rust 项目工程,因此,我们可以使用 cargo build
命令一键编译出名为 mdbook
的可执行程序。
文档
- 官方在线文档
- mdBook Documentation!
- 文档的源码位于 mdBook 源码的 guide 目录下,本身也是使用的 mdBook 文档系统。首先安装
cargo install mbook
或者自己构建后,在doc\guide
中执行mbook build
或者在mbook build 指定路径
就可以构建出上面的官方在线文档
rustdoc
rustdoc 是 Rust 官方提供的随附编译工具链发布的文档处理工具,这个工具主要是用来自动收集当前项目源码文件中的各种注释来生成对应文档,它接受一个 crate root 文件或者一个 Markdown 文件作为参数,然后生成 HTML,CSS 和 JavaScript 文件等称为一套以静态网页为主的文档。
rustdoc 是一个命令行工具,对应的可执程序为 rustdoc
,使用命令 rustfmt [options] <input>
自动收集源码中的注释形成文档。当我们使用时实际上是通过 .cargo/bin/rustdoc
这个代理来调用 .rustup/toolchains/发行版/bin/rustdoc
这个真正的可执行程序。
- rustdoc 以 crate root 文件为入口自动遍历所以使用到的源码文件,不用我们手动指定所有源码文件。
- 默认的文档名字是 Crate 的名字,可以使用
--crate-name xxx
来进行更改 - 文档将存放到
target\doc
目录下,每个 Crate 一个子目录,他们之间会互相引用
cargo doc
通常 rustdoc
会被作为 cargo 命令的一个子命令 cargo doc
来间接使用,完整格式是 cargo doc [OPTIONS]
。这个命令需要在我们的 Package 目录下执行,Cargo 将自动查找所有源代码文件(包括我们依赖的 Crate 的源码文件)。
-
使用
cargo doc --verbose
可以看到调用rustdoc
的详细参数
-
cargo doc
目前不支持独立的 Markdown 文件 -
cargo doc
命令不止处理我们自己的源码文件,还会处理依赖的 Crate 的源码文件,进而形成一整套的文档。运行cargo doc --open
命令来构建所有本地依赖项提供的文档,并在浏览器中打开,这样就方便了我们查找需要的接口
源码
rustdoc 稍微有点特殊,它是作为 Rust 的编译工具链中的一个标准组件来发布的。因此,它没有一个单独的源码仓库,而是在 Rust 编译工具链的仓库 https://github.com/rust-lang/rust 中的一个部分
文档
-
官方文档 The rustdoc book
-
文档的源码位于 Rust 源码的
src\doc\rustdoc
目录下,可以使用命令x.py doc src/doc/rustdoc
来构建,使用的是 mdBook 文档系统,详细介绍参见后文的 mdBook 章节的介绍
文档注释
rustdoc 会提取源码文件中特定格式的注释(官方称为文档注释)来生成文档,rustdoc 规定了用于生成的文档的注释必须以 ///
或者 //!
开头,并且注释的内容主要使用 Markdown 语法来进行编写。
///
用于放在函数、结构体、变量等代码前面以对代码进行注释,称为 outer documentation,示例如下:
//!
用于放到一个源码文件的开头给一个源码文件注释,称为 inner documentation。示例如下:
- 当它位于 root crate 文件时,那么它就是文档主页的注释
- 其最后面需要加一个空行
- 可以在自己的
src/lib.rs
或main.rs
的开头添加#![warn(missing_docs)]
,而如果是一个要共享的库则可添加#![deny(missing_docs)]
- 使用
#[doc(hidden)]
可以屏蔽将之后的内容提取到文档中
参考
- https://cloud.tencent.com/developer/article/1477262
- https://blog.csdn.net/fj_Author/article/details/132594546
- https://www.andy-pearce.com/blog/posts/2023/May/uncovering-rust-build-and-packaging/
- https://www.prodyna.com/insights/rust-apps