目录
-
[1. main函数](#1. main函数)
-
- [1.1 未捕获的外部展开(这部分内容主要在std::panic模块展开)](#1.1 未捕获的外部展开(这部分内容主要在std::panic模块展开))
- [1.2 no_main属性](#1.2 no_main属性)
-
[2. crate_name属性(cargo管理时不用)](#2. crate_name属性(cargo管理时不用))
-
Syntax
Crate ->
InnerAttribute*
Item*
Crate(匿名的顶层模块)以零个或多个InnerAttribute开头,以零个或多个Item结尾。
Rust的语义遵循编译时与运行时的阶段区分。具有静态解释的语义规则决定编译的成功,具有动态解释的语义规则决定程序运行时的行为。
编译模型以称为crate的产物为中心。每次编译处理单个源码形式的crate,若成功,则产出单个二进制i形式的crate:可执行文件或库。
crate是编译与链接的单元,同时也是版本管理、分发和运行时加载的单元。crate包含一棵由嵌套的模块作用域构成的树。这棵树的顶层是一个(从模块内路径的角度来看)匿名的模块。crate内部的任何项都有一个规范的模块路径,指明它在crate模块树中的位置。
Rust编译器被调用时总是以单个源文件作为输入,并且总是产出单个输出crate。对该源文件的处理可能导致其他源文件作为模块被加载。源文件的扩展名为.rs。
一个Rust源文件描述一个模块,而该模块在当前crate模块树中的名称与位置是在源文件之外定义的:要么由引用它的源文件中的显式Module项定义,要么由crate本身的名称定义。
每个源文件都是一个模块,但并非每个模块都需要自己的源文件:模块定义可以嵌套在同一个文件中。
每个源文件包含零个或多个项定义的序列,并可选地以任意数量的、作用于所属模块的属性开头,这些属性大多会影响编译器的行为。
匿名的crate模块可以拥有作用于整个crate的额外属性。
使用了Cargo之后不建议这么做。
rust
// src/lib.rs
// 指定crate名称
#![crate_name = "projx"]
// 指定输出产物的类型
#![crate_type = "lib"]
// 打开一条警告
// 这可以在任何模块中完成,而不仅限于匿名的crate模块
#![warn(non_camel_case_types)]
1. main函数
包含main函数的crate可以被编译为可执行文件。
若存在main函数,它必须:不接受任何参数,不得声明任何trait或生命周期约束、不得带有任何where子句,且其返回类型必须实现Termination trait。
rust
fn main() {}
rust
fn main() -> ! {
std::process::exit(0);
}
rust
fn main() -> impl std::process::Termination {
std::process::ExitCode::SUCCESS
}
main函数也可以是一个导入,例如来自外部crate或当前crate。
rust
mod foo {
pub fn bar() {
println!("Hello, world!");
}
}
use foo::bar as main;

标准库中实现了Termination trait的类型:
()
!
Infallible
ExitCode
Result<T, E> where T: Termination, E: Debug
1.1 未捕获的外部展开(这部分内容主要在std::panic模块展开)
当外来的unwind(例如从C++代码抛出的异常,或使用不同panic处理器的Rust代码中的panic!)传播越过main函数时,进程将被安全地终止。这可能以中止的形式进行,此时不保证会执行任何Drop调用,且错误输出所含信息可能不如运行时被原生Rust panic终止时丰富。
1.2 no_main属性
no_main属性可以在crate级别应用,用于禁止为可执行二进制文件发出main符号。当被链接的其他目标文件定义了main时,这一属性很有用。
2. crate_name属性(cargo管理时不用)
crate_name属性可以在crate级别应用,使用MetaNameValueStr(属性那一章会将)语法指定crate名称。
rust
#![crate_name = "mycrate"]
crate名称不得为空,且只能包含Unicode字母数字字符或_字符。