本文不是rust入门或手册,只是一些对我个人来说容易忘记或混淆的点的整理。

语言与编译器(rustc)

Edition

Edition 机制为了保证后向兼容。不同的edition可能有不兼容的修改。例如async在2018 edition变成关键字,在2015 edition可以作为普通变量名。通过在Cargo.toml中指定edition=2018,rust编译时会按照2018的语法来进行编译。

Edition机制不会保证前向兼容。比如feature在stablize后,stable channel新版本的rust可以直接使用,但是旧版本仍不能用。

官方文档

Rust Unstable Feature

rust unstable reference Unstable Feature 分为三类:

  1. compiler flags: 通过-Z<flag>指定,例如-Zcodegen-backend=<path>

  2. language features:

    这些是编译器feature,通过#![feature]指定。 feature的列表在源码的src/rustc_feature/下, accepted.rs是已经stable的feature列表, active.rs是unstable的feature列表。 随着rust的开发,有些feature会从unstable变成stable,参考https://rustc-dev-guide.rust-lang.org/stabilization_guide.html

  3. library features:

    library feature是定义在rustc standard library的feature,使用#[unstable] 等attribute 定义。 目前只支持 rust 源码树中的library定义。外部crate中的library不能自定义feature(https://github.com/rust-lang/rfcs/issues/1491)。 unstable等attribute的使用以及stabilizing library feature参考 https://rustc-dev-guide.rust-lang.org/stability.html。 在源码中使用也是通过 #![feature]指定。

    unstable feature不能用于stable channel。

cargo也有unstablefeature,可以参考下面cargo部分。

Attributes

https://doc.rust-lang.org/reference/attributes.html

attribute是一种通用的metadata,形如#[Attr](outer attributes)或#![Attr](inner attributes),在编译时处理。 可以分为四类

  • Builtin attributes, 例如cfgtestderive等。#![feature]也是一种builtin attribute。
  • Macro attrbutes,通过attribute macro定义的attribute。
  • Derive macro helper attributes,用于在Derive macro中定义额外attributes。
  • Tool attributes,外部工具如rustfmt等定义。

Derive Attribute

https://doc.rust-lang.org/reference/attributes/derive.html

derive attribute用于给数据结构自动生成item(例如方法等)。例如给struct生成Clone trait的方法。可以使用Derive macro给自己的tait定义额外的derive

Macros

https://doc.rust-lang.org/reference/macros.html

编译时扩展macro,并替换macro定义。rust中有两种方式定义macro:

  1. Macros by Example define new syntax in a higher-level, declarative way. 使用macro_rules!宏声明式来定义。by example可以理解为这种定义方式比较直观,以类似举例的方式来定义宏。
  2. Procedural Macros define function-like macros, custom derives, and custom attributes using functions that operate on input tokens. 这种定义方式直接处理TokenStream,输出新的TokenStream。分为三种:
    • Function-like macros - custom!(…)
    • Derive macros - #[derive(CustomDerive)]
    • Attribute macros - #[CustomAttribute]

条件编译

https://doc.rust-lang.org/reference/conditional-compilation.html

条件编译的选项是在编译时确定和生效的。

设置配置选项:

部分选项是编译器自动设置,其他选项是编译时传给编译器的,可以通过以下两种方式。

  • rustc 通过--cfg参数指定。 形式可以是name或者k=v对,例如unixfoo="bar" 有一些预定义的option,如target_arch等。
  • cargo.toml [feature] section中定义的feature或者可选依赖自动变成key是feature=<feature>的option。

条件编译形式

以下三种形式都是根据指定的选项来进行不同的条件编译。

  • cfg attribute
  • cfg_attr attribute
  • cfg macro

Cargo

https://doc.rust-lang.org/cargo/index.html

cargo 是rust的包管理器。用于包的依赖管理,编译,分发等。

package manifest

https://doc.rust-lang.org/cargo/reference/manifest.html

package manifest指的是包中的cargo.toml文件,包含包的信息,例如名字,版本,依赖,target等。 cargo targets是指cargo的build产物,如library, binary, example等。

除了这些target,很多时候平台相关的配置也称为target。例如平台相关的依赖,就是使用类似[target.'cfg(unix)'.dependencies]的section。 平台相关的条件也通过<cfg> expression来指定。

cargo configuration

https://doc.rust-lang.org/cargo/reference/config.html

除了cargo manifest, 还有一类配置文件,config.toml,称为configuration。cargo configuration可以定义在包级别,也可以定义在全局配置中,而cargo.toml只能定义在包级别。 其中[target] table 用于指定平台相关的设置。可以使用<cfg> expression 或者平台<triple>类进行匹配。

个人理解,cargo configuration一般是对build工具本身的配置,例如cargo的命令aliases,网络代理,环境变量等。而cargo manifest主要是对package的配置。

package feature

https://doc.rust-lang.org/cargo/reference/features.html

cargo.toml中可以定义[feature] section,定义包的feature。可以在build或者添加依赖时指定feature。根据feature可以进行条件编译。例如#[cfg(feature = "webp")]

cargo unstable feature

https://doc.rust-lang.org/cargo/reference/unstable.html

cargo unstable feature是指cargo本身的unstable feature。只有nightly channel的cargo可以使用。通过cargo 命令行 -Z 参数或者config.toml中[unstable] section指定。

profile

https://doc.rust-lang.org/cargo/reference/profiles.html

profile提供一个修改编译参数的方案,可以认为一个profile定义了一组编译选项。通过选择不同的profile,自动应用该profile代表的一组编译选项。 cargo有四个内置profile:dev, release, test, bench。默认会根据不同的cargo命令自动使用不同的profile。。

profile的配置可以在cargo.toml中修改,会被config.toml中的相应配置覆盖。依赖中定义的profile会被覆盖,只有当前root worksapce的profile配置才会使用。

Rustup

https://rust-lang.github.io/rustup/index.html

rustup 是rust release的管理工具。

rustup 管理的某个rust installation称为toolchain。可以给toolchain配置channel,component等。 cargo +nightly build 使用nightly toolchain。

可以在项目目录中通过rust-toolchainrust-toolchain.toml来指定当前项目使用的toolchain。

toolchain 和target的关系

toolchain对应的是当前机器上的rust工具链,如cargo,rustc,rust-analyzer,也就是对应的工具要在本地运行;而target是当前代码要编译的目标环境,跟本地的环境没关系。

例如x86_64的linux机器上开发要运行在aarch64的linux下的应用,那么有可能 toolchain为stable-x86_64-unknown-linux-gnu, target为aarch64-unknown-linux-gnu。

所以toolchain的完整格式虽然为<channel>[-<date>][-<host>],但一般只需指定channel为stable/nightly。