学习Rust,认识Cargo!

查理谈科技 2024-05-10 00:15:05

学Rust,进华为!

这是学习Rust的第二篇文章, 主要是学习Cargo, 这是Rust的包管理工具和构建工具。

在 Rust 中,库或可执行程序称为 crate。 包是使用 Rust 编译器 rustc 编译的。 当开始使用 Rust 时,大多数人遇到的第一个源代码是古老的“hello world”程序的源代码,他们通过直接调用 rustc 来编译该程序。

大多数的执行某些商业业务的Rust程序可能会依赖于外部库,因此也会传递地依赖于它们的依赖项。 如果手动完成这些依赖,获取所有必要依赖项的正确版本并使其保持最新将非常费力且容易出错。

对于Rust,可以通过引入更高级别的“包”抽象并使用包管理器来避免执行上述任务所涉及的手动繁琐工作,而不是仅使用 crates 和 rustc。

首先,来创建一个最基本的Rust Cargo 项目。

Hello, Cargo!

Cargo 是 Rust 的构建系统和包管理器。 大多数 Rust开发者都使用这个工具来管理他们的 Rust 项目,因为 Cargo 会处理很多任务,例如构建代码、下载代码所依赖的库以及构建这些库。

在终端中输入以下内容来检查 Cargo 是否已安装:

$ cargo --version

结果:

如果看到版本号,则说明Cargo已经成功安装! 如果看到错误,例如找不到命令,请查看安装方法的文档,以确定如何单独安装 Cargo。

☞☞使用 Cargo 创建项目

让我们使用 Cargo 创建一个新项目,看看它与我们原来的“Hello, world!”有何不同。

在命令行输入以下命令:

$ cargo new hello_cargo$ cd hello_cargo

结果:

第一个命令创建一个名为 hello_cargo 的新目录和项目。 我们将项目命名为 hello_cargo,Cargo 在同名目录中创建其文件。

进入 hello_cargo 目录并列出文件。 你会看到 Cargo 为我们生成了两个文件和一个目录:一个 Cargo.toml 文件和一个 src 目录,里面有一个 main.rs 文件。

它还初始化了一个新的 Git 存储库以及一个 .gitignore 文件。 如果您在现有的 Git 存储库中运行 Cargo new,则不会生成 Git 文件; 您可以使用 Cargo new --vcs=git 覆盖此行为。

Cargo.toml:

main.rs:

在您选择的文本编辑器中打开 Cargo.toml。 它应该类似于清单 1-2 中的代码。

文件名:Cargo.toml

[package]name = "hello_cargo"version = "0.1.0"edition = "2021"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]

该文件采用 TOML(Tom’s Obvious,Minimal Language)格式,这是 Cargo 的配置格式。

第一行 [package] 是节标题,指示以下语句正在配置包。 当我们向此文件添加更多信息时,我们将添加其他部分。

接下来的三行设置 Cargo 编译程序所需的配置信息:名称、版本和要使用的 Rust 版本。 我们将在附录 E 中讨论版本密钥。

最后一行 [dependencies] 是一个部分的开始,用于列出项目的任何依赖项。 在 Rust 中,代码包被称为 crate。 这个项目不需要任何其他 crate,但我们会在第 2 章的第一个项目中使用,所以我们将使用这个依赖项部分。

现在打开 src/main.rs 看看:

文件名:src/main.rs

fn main() {println!("Hello, world!");}

Cargo 生成了“Hello, world!” 为您准备的程序。 到目前为止,之前编写的Helloworld 项目和 Cargo 生成的项目之间的区别在于 Cargo 将代码放在 src 目录中,并且在顶层目录中有一个 Cargo.toml 配置文件。

Cargo 希望源文件位于 src 目录中。 顶级项目目录仅用于 README 文件、许可证信息、配置文件以及与代码无关的任何其他内容。 使用 Cargo 可以帮助开发人员组织项目。原则是: 一切都有一个地方,一切都在它的位置上。

如果启动一个不使用 Cargo 的项目,就像之前对“Hello, world!”所做的那样的项目,也可以将其转换为使用 Cargo 的项目。 将项目代码移至 src 目录并创建适当的 Cargo.toml 文件就可以了。

☞☞构建和运行Cargo项目

现在让我们看看使用Cargo构建和运行的应用,和之前的“Hello, world!”例子有什么不同。

在 hello_cargo 目录中,输入以下命令来构建项目:

$ cargo build

结果:

此命令在 target/debug/hello_cargo (或 Windows 上的 target\debug\hello_cargo.exe)而不是在当前目录中创建可执行文件。 由于默认构建是调试构建,因此 Cargo 将二进制文件放在名为 debug 的目录中。

可以使用以下命令运行可执行文件:

$ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows

可以看到,"Hello, World" 被打印到终端。 第一次运行 Cargo build 还会导致 Cargo 在顶层创建一个新文件:Cargo.lock。 该文件跟踪项目中依赖项的确切版本。 该项目没有依赖项,因此文件有点稀疏。 作为开发者,我们无需手动更改此文件; Cargo 会自动管理这个文件内容。

我们刚刚使用cargo build构建了一个项目,并使用./target/debug/hello_cargo运行它,但我们也可以使用cargo run来编译代码,然后在一个命令中运行生成的可执行文件:

我们首先修改一下代码:

fn main() {     println!("你好,Rust Cargo!");}

然后运行:

cargo run

结果:

值得注意的是, 如果不修改代码直接运行cargo run, 则target/debug 目录下的文件不会改变;当我们修改了main.rs代码,再次运行cargo run的时候, target/debug 下的文件的时间戳发生了变化:

Cargo还提供了一个名为cargo check的命令。 此命令快速检查您的代码以确保它可以编译但不会生成可执行文件:

我们再次修改源文件:

fn main() { println!("你好,欢迎学习Rust Cargo!");}

然后运行:

cargo check

结果:

为什么你不想要一个可执行文件? 通常,cargo check比cargo build快得多,因为它跳过了生成可执行文件的步骤。 如果在编写代码时不断检查您的代码,那么使用cargo check将加快让您知道项目是否仍在编译的过程! 因此,许多 Rust开发者 在编写程序时会定期运行cargo check以确保其编译。 然后,当他们准备好使用可执行文件时,他们会运行Cargo build。

回顾一下到目前为止我们所了解的有关 Cargo 的知识:

使用cargo new 创建一个项目。使用cargo build 来构建一个项目。可以使用cargo run一步构建并运行一个项目。可以构建一个项目,而无需生成二进制文件来使用cargo check来检查错误。

Cargo 没有将构建结果保存在与我们的代码相同的目录中,而是将其存储在 target/debug 目录中。

使用 Cargo 的另一个优点是,无论使用哪种操作系统,命令都是相同的。

☞☞构建发布

当您的项目最终准备好发布时,您可以使用 Cargo build --release 对其进行优化编译。 此命令将在 target/release 而不是 target/debug 中创建可执行文件。

如果需要对代码的运行时间进行基准测试,请务必运行 Cargo build --release 并使用 target/release 中的可执行文件进行基准测试。

回顾

Cargo 是 Rust 包管理器。 它是一个允许 Rust 包声明其各种依赖项并确保您始终获得可重复构建的工具。

为了实现这一目标,Cargo 做了四件事:

引入两个元数据文件,其中包含各种包信息。获取并构建包的依赖项。使用正确的参数调用 rustc 或其他构建工具来构建您的包。引入约定,使 Rust 包的使用更加容易。

在很大程度上,Cargo 标准化了构建给定程序或库所需的命令; 这是上述公约的一方面,相同的命令可以用于构建不同的工件,无论它们的名称是什么。

作为Rust开发者,可以不直接调用 rustc,而是调用一些通用的东西,例如 Cargo build,并让 Cargo 负责构建正确的 rustc 调用。

此外,Cargo 会自动从注册表中获取我们为工件定义的任何依赖项,并根据需要将它们合并到我们的构建中。可以稍微夸张地说,一旦您知道如何构建一个基于 Cargo 的项目,您就知道如何构建所有这些项目。

使用现有的Cargo 包

在开发中,合理引用 Cargo 的现有软件包,那么开发会非常容易。

首先,我们需要从某个地方获取包裹。 在这里,我们将使用从 GitHub 上的克隆一个正则表达式的项目:

$ git clone https://github.com/rust-lang/regex.git$ cd regex

目前regex目录内容如下:

作为一个正式项目,Cargo.toml内容比较丰富:

Cargo 依赖项示例:

要构建,请使用货物构建:

$ cargo build

这将获取所有依赖项,然后将它们与包一起构建。

可以看到, Cargo 会自动分析依赖项,并从crates.io中下载对应项。

在项目中增加依赖项

下面我们创建一个新的Cargo项目,增加依赖项:

$ cargo new hello_dependency

打开Cargo.toml,增加time和regex 依赖:

[package]name = "hello_dependency"version = "0.1.0"edition = "2021"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]time = "0.3.30"regex = "1.10.0"

注意, toml 编辑器会很仔细地帮你检查依赖项的版本信息, 并给出错误提示:

下面我们开始在代码中使用这些依赖:

use regex::Regex;fn main() {let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();println!("日期是否匹配?{}",re.is_match("2024-01-07"));}

运行cargo build,Cargo 将获取新的依赖项及其所有依赖项,编译它们,并更新 Cargo.lock:

$ cargo build

我们的 Cargo.lock 包含有关我们使用的所有这些依赖项的哪个版本的确切信息。

现在,如果正则表达式更新,我们仍然会使用相同的修订版本进行构建,直到我们选择进行更新。

$ cargo run

结果:

cargo build 之后, 目录结构如下:

Cargo.toml 和 Cargo.lock 存储在包的根目录(包根)中。源代码位于 src 目录中。默认库文件是 src/lib.rs。默认的可执行文件是 src/main.rs。其他可执行文件可以放置在 src/bin/ 中。基准测试位于 benches 目录中。示例位于示例目录中。集成测试位于测试目录中。

如果二进制、示例、基准或集成测试由多个源文件组成,请将 main.rs 文件与额外模块一起放置在 src/bin、示例、基准或测试目录的子目录中。 可执行文件的名称将是目录名称。

Cargo.toml 和 Cargo.lock

Cargo.toml 和 Cargo.lock 有两个不同的用途。 在讨论它们之前,先做一个总结:

Cargo.toml 是关于广义上描述您的依赖关系,并且由开发者编写。Cargo.lock 包含有关依赖项的准确信息。 它由 Cargo 维护,不应手动编辑。

在项目中,请将 Cargo.lock 检查到版本控制系统(例如 Git)中。

0 阅读:0

查理谈科技

简介:感谢大家的关注