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 内核 代码中可以看到,这个属性大量的使用
