Rust-reference/crates-and-source-files
crate 和源文件
commit: 277587a55aa24d8f6a66ddb43493e150c916ef43
本章译文最后维护日期:2020-11-8
句法
Crate :
UTF8BOM?
SHEBANG?
InnerAttribute*
Item*
词法
UTF8BOM :
\uFEFF
SHEBANG :#!
~\n
+†
注意:尽管像任何其他语言一样,Rust 也都可以通过解释器和编译器实现,但现在唯一存在的实现是编译器,并且该语言也是一直被设计为可编译的。因为这些原因,所以本章节所有的讨论都是基于编译器这条路径的。
Rust 的语义有编译时和运行时之间的阶段差异(phase distinction)。[1] 其中静态解释的语义规则控制编译的成败,而动态解释的语义规则控制程序在运行时的行为。
编译模型以 crate 为中心。每次编译都以源码的形式处理单个的 crate,如果成功,将生成二进制形式的单个 crate:可执行文件或某种类型的库文件。[2]
crate 是编译和链接的单元,也是版本控制、版本分发和运行时加载的基本单元。一个 crate 包含一个嵌套的带作用域的模块树。这个树的顶层是一个匿名的模块(从模块内部路径的角度来看),并且一个 crate 中的任何程序项都有一个规范的模块路径来表示它在 crate 的模块树中的位置。
Rust 编译器总是使用单个源文件作为输入来开启编译过程的,并且总是生成单个输出 crate。对输入源文件的处理可能导致其他源文件作为模块被加载进来。源文件的扩展名为 .rs
。
Rust 源文件描述了一个模块,其名称和(在当前 crate 的模块树中的)位置是从源文件外部定义的:要么通过引用源文件中的显式模块(Module)项,要么由 crate 本身的名称定义。每个源文件都是一个模块,但并非每个模块都需要自己的源文件:多个模块定义可以嵌套在同一个文件中。
每个源文件包含一个由零个或多个程序项定义组成的代码序列,并且这些源文件都可选地从应用于其内部模块的任意数量的属性开始,大部分这些属性都会会影响编译器行为。匿名的 crate 根模块可附带一些应用于整个 crate 的属性。
// 指定 crate 名称.
#![crate_name = "projx"]
// 指定编译输出文件的类型
#![crate_type = "lib"]
// 打开一种警告
// 这句可以放在任何模块中, 而不是只能放在匿名 crate 模块里。
#![warn(non_camel_case_types)]
Byte order mark
字节顺序标记(BOM)
可选的UTF8字节序标记(UTF8BOM产生式)表示该文件是用 UTF8 编码的。它只能出现在文件的开头,并且编译器会忽略它。
Shebang
源文件可以有一个shebang(SHEBANG产生式),它指示操作系统使用什么程序来执行此文件。它本质上是将源文件作为可执行脚本处理。shebang 只能出现在文件的开头(但是要在可选的 UTF8BOM 生产式之后)。它会被编译器忽略。例如:
#!/usr/bin/env rustx fn main() { println!("Hello!"); }
为了避免与属性混淆, Rust 对 shebang 句法做了一个限制:是 #!
字符不能后跟 token [
,忽略中间的注释或空白符。如果违反此限制,则不会将其视为 shebang,而会将其视为属性的开始。
Preludes and no_std
预导入包和 no_std
所有的 crate 都有一个 预导入包(prelude),它会自动将一个特定模块(预导入包模块)里的名称插入到每个模块的作用域内,并将一个 extern crate
插入到当前 crate 的根模块中。默认情况下,这个预导入包为标准预导入包(standard prelude)。它链接的 crate 是 std
,预导入模块是 std::prelude::v1
。
在根 crate 模块上使用 no_std
属性,可以将预导入包改成 核心预导入包(core prelude)。它链接的 crate 是 core
,预导入模块为 core::prelude::v1
。当 crate 的目标平台不支持标准库或有意不使用标准库的功能时,使用核心预导入包而不是标准预导入包是可行的。这么做放弃的主要功能是动态内存分配(例如:Box
和 Vec
)、文件和网络功能(例如: std::fs
和 std::io
)。
警告:使用 no_std
不会阻止主动把标准库链接进来的操作。仍然可以合法地将 extern crate std;
这条语句引入到当前 crate 中,同时其完整的依赖关系也可以成功地加载到当前 crate 中。
Main Functions
main函数
包含 main
函数的 crate 可以被编译成可执行文件。如果一个 main
函数存在,它必须不能有参数,不能对其声明任何 trait约束或生存期约束,不能有任何 where子句,并且它的返回类型必须是以下类型之一:
()
Result<(), E> where E: Error
注意: 允许哪些返回类型的实现是由暂未稳定的
Termination
trait 决定的。
The no_main
attribute
no_main
属性
可在 crate 层级使用 no_main
属性来禁止对可执行二进制文件发布 main
symbol,即禁止当前 crate 的 main 函数的执行。当链接的其他对象定义了 main
函数时,这很有用。
The crate_name
attribute
crate_name
属性
可在 crate 层级应用 crate_name
属性,并通过使用 MetaNameValueStr元项属性句法来指定 crate 的名称。
#![crate_name = "mycrate"]
crate 名称不能为空,且只能包含 [Unicode字母数字]或字符 -
(U+002D)。