crate

经过上一个小节的学习,我们相信 模块 这个概念已经深入人心了, 而且我们也可以熟练掌握了

这一节让我们简单介绍一下包的概念

我们可以简单理解为包是一个 项目(虽然有一点不准确),但是包是有明确的边界的:

  • 一个独立的库 可以成为一个包
  • 工具包(一般情况下,同一个项目可能提供一组二进制文件,典型的比如ssh/sshd),可以成为一个包
  • 一个独立的库和工具包 可以成为一个包

从包的构成上看,其实也能感觉到,包一般是有明确独立的项目/功能属性

包根

我们已经知道 包是一个树形结构 ,那就必然需要一个根节点,在RUST 的项目中(在cargo 使用会介绍) 如果构建的是一个二进制程序,则会使用 main.rs 作为 模块树的起点,如果构建库文件则 会使用 lib.rs 作为 模块树的起点

  • 包(模块)根 在RUST 中 是一个匿名模块(不是 main 也不是 lib) 一般 使用 crate 关键字表示(使用会在use小节看到)

Shebang

源文件可以有一个shebang(SHEBANG产生式),它指示操作系统使用什么程序来执行此文件。它本质上是将源文件作为可执行脚本处理。 shebang 只能出现在文件的开头(但是要在可选的 UTF8BOM 生产式之后)。它会被编译器忽略。例如:

#!/usr/bin/env rustx

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

为了避免与属性混淆, Rust 对 shebang 句法做了一个限制: 是 #!字符不能后跟 token [,忽略中间的注释或空白符。如果违反此限制, 则不会将其视为 shebang,而会将其视为属性的开始。

导入外部库

我们可能已经发现,之前我们已经使用过 use std::xx:xx 这类语法, std 并非我们的源码,本质上也很简单, 我们可以想象,有一个std crate,他是外部提供的,他在他自己代码中定义了 模块树,如果我的项目希望使用外部模块 我可以在我的代码中任何一个地方 使用外部crate 提供的模块树,而这都依赖于 一种叫做 预导入包的功能

  • 标注库的包:标准库预导入包包含了std::prelude::v1模块中的名称。

     如果使用no_std属性,那么它将使用core::prelude::v1模块中的名称。
    
  • 导入外部包: 在根模块中 使用 exter crate xxxx 或者直接给编译器 提供 参数 rustc --extern crate_name 使用

如果使用cargo,cargo 会根据项目依赖,自动帮我们导入包

no_std

作为内核开发人员,我们一般情况下 不需要用到 标准库包,可以使用no_std属性拒绝 标注库导入到当前包 在linux 内核 代码中可以看到,这个属性大量的使用

Screenshot