rust绿卡名称_Rust学习笔记5 属性与Cargo配置

5.1 属性

属性(Attribute)是一种通用的用于表达元数据的特性。

在rust中大量使用属性,对于go程序员而言,属性的大量使用很容易造成困惑。

属性有些类似与spring boot中的注解,但又有很大不同。首先java就是一门平台无关性的语言。

属性只能用于修饰rust中的item。

rust中的item包括:

extern crate声明

use声明

模块(模块是一个Item的容器)

函数

type定义

结构体定义

枚举类型定义

常量定义

静态变量定义

Trait定义

实现(Impl)

这些Item是可以互相嵌套的,比如在一个函数中定义一个静态变量、在一个模块中使用use声明或定义一个结构体。

5.1 属性

5.1.1 属性的语法

Rust 包括两种 attribute :

![attribute属性描述]

第一种的含义是:

这种#后面有一个!的形式,表示这个属性值应用在当前的对象。通常,这样的attribute是针对当前文件设置的。当前文件可能包括两种对象,一个是crate,另一个可能是module。需要根据文件的上下文来判断。

判断的依据是,如果是src/mod.rs 或者 src/lib.rs 那么这个设置就是针对 crate 的,因为这两个文件是crate的root module。

[attribute属性描述]

第二种含义是:

这种前面只有#号的属性,表示属性的设置应用到属性下面的紧挨着的元素,即item上。

Rust attribute 正则表达式语法:

attribute : '#' '!' ? '[' meta_item ']' ;

meta_item : ident [ '=' literal | '(' meta_seq ')' ] ? ;

meta_seq : meta_item [ ',' meta_seq ] ? ;

meta可以进行无限嵌套。

参看一些rust attribute的例子去理解它的语法:

#[cfg(not(target_feature = "crt-static"))]

#[derive(PartialEq, Clone)]

#![crate_name = "mycrate"]

#[target_feature(enable = "avx2")]

#[link(name = "CoreFoundation", kind = "framework")]

#![allow(clippy::filter_map)]

#[cfg_attr(linux, path = "linux.rs")]

#[cfg_attr(windows, path = "windows.rs")]

按照语法可以写出一个这样例子:

#[target(windows,not(config=”true”,ubuntu(“config”=false,sixteen)))]

翻译过来的语法规则描述如下:

1.单个标识符代表的属性名,如#[unix]

2.单个标识符代表属性名,后面紧跟着一个=,然后再跟着一个Value,组成一个键值对,如#[link(name = "openssl")]

3.单个标识符代表属性名,后面跟着一个逗号隔开的子属性的列表,如#[cfg(and(unix, not(windows)))]

5.1.2 几种常见的属性

官方的attribute文档:

RustPrimer文档:

几种常用的attribute如下:

5.1.2.1.应用于crate的属性

• crate_name - 指定Crate的名字。如#[crate_name = "my_crate"]则可以让编译出的库名字为libmy_crate.rlib。

• crate_type - 指定Crate的类型,有以下几种选择

o "bin" - 编译为可执行文件;

o "lib" - 编译为库;

o "dylib" - 编译为动态链接库;

o "staticlib" - 编译为静态链接库;

o "rlib" - 编译为Rust特有的库文件,它是一种特殊的静态链接库格式,它里面会含有一些元数据供编译器使用,最终会静态链接到目标文件之中。

• feature - 可以开启一些不稳定特性,只可在nightly版的编译器中使用。

• no_builtins - 去掉内建函数。

• no_main- 不生成main这个符号,当你需要链接的库中已经定义了main函数时会用到。

• no_start - 不链接自带的native库。

• no_std - 不链接自带的std库。

• plugin - 加载编译器插件,一般用于加载自定义的编译器插件库。

5.1.2.2 应用于函数的属性

• main - 把这个函数作为入口函数,替代fn main,会被入口函数(Entry Point)调用。

• plugin_registrar - 编写编译器插件时用,用于定义编译器插件的入口函数。

• start - 把这个函数作为入口函数(Entry Point),改写 start language item。

• test - 指明这个函数为单元测试函数,在非测试环境下不会被编译。

• should_panic - 指明这个单元测试函数必然会panic。

• cold - 指明这个函数很可能是不会被执行的,因此优化的时候特别对待它。

5.1.2.3 应用于FFI的属性

extern块可以应用以下属性

• link_args - 指定链接时给链接器的参数,平台和实现相关。

• link - 说明这个块需要链接一个native库,它有以下参数:

o name - 库的名字,比如libname.a的名字是name;

o kind - 库的类型,它包括

 dylib - 动态链接库

 static - 静态库

 framework - OS X里的Framework

5.1.2.4 条件编译

有时候,我们想针对不同的编译目标来生成不同的代码,比如在编写跨平台模块时,针对Linux和Windows分别使用不同的代码逻辑。

条件编译基本上就是使用cfg这个属性,直接看例子

#[cfg(target_os = "macos")]

fn cross_platform() {

// Will only be compiled on Mac OS, including Mac OS X

}

#[cfg(target_os = "windows")]

fn cross_platform() {

// Will only be compiled on Windows

}

// 若条件`foo`或`bar`任意一个成立,则编译以下的Item

#[cfg(any(foo, bar))]

fn need_foo_or_bar() {

}

// 针对32位的Unix系统

#[cfg(all(unix, target_pointer_width = "32"))]

fn on_32bit_unix() {

}

// 若`foo`不成立时编译

#[cfg(not(foo))]

fn needs_not_foo() {

}

其中,cfg可接受的条件有

• debug_assertions - 若没有开启编译优化时就会成立。

• target_arch = "..." - 目标平台的CPU架构,包括但不限于x86, x86_64, mips, powerpc, arm或aarch64。

• target_endian = "..." - 目标平台的大小端,包括big和little。

• target_env = "..." - 表示使用的运行库,比如musl表示使用的是MUSL的libc实现, msvc表示使用微软的MSVC,gnu表示使用GNU的实现。 但在部分平台这个数据是空的。

• target_family = "..." - 表示目标操作系统的类别,比如windows和unix。这个属性可以直接作为条件使用,如#[unix],#[cfg(unix)]。

• target_os = "..." - 目标操作系统,包括但不限于windows, macos, ios, linux, android, freebsd, dragonfly, bitrig, openbsd, netbsd。

• target_pointer_width = "..." - 目标平台的指针宽度,一般就是32或64。

• target_vendor = "..." - 生产商,例如apple, pc或大多数Linux系统的unknown。

• test - 当启动了单元测试时(即编译时加了--test参数,或使用cargo test)。

还可以根据一个条件去设置另一个条件,使用cfg_attr,如

[cfg_attr(a, b)]

这表示若a成立,则这个就相当于#[cfg(b)]。

5.1.2.5 Linter参数

目前的Rust编译器已自带的Linter,它可以在编译时静态帮你检测不用的代码、死循环、编码风格等等。Rust提供了一系列的属性用于控制Linter的行为

• allow(C) - 编译器将不会警告对于C条件的检查错误。

• deny(C) - 编译器遇到违反C条件的错误将直接当作编译错误。

• forbit(C) - 行为与deny(C)一样,但这个将不允许别人使用allow(C)去修改。

• warn(C) - 编译器将对于C条件的检查错误输出警告。

编译器支持的Lint检查可以通过执行rustc -W help来查看。

5.1.2.6 编译特性

在非稳定版的Rust编译器中,可以使用一些不稳定的功能,比如一些还在讨论中的新功能、正在实现中的功能等。Rust编译器提供一个应用于Crate的属性feature来启用这些不稳定的功能,如

![feature(advanced_slice_patterns, box_syntax, asm)]

具体可使用的编译器特性会因编译器版本的发布而不同,具体请阅读官方文档。

属性较为繁琐,以官方文档为主。

5.2 cargo参数配置

5.2.1 package配置

[package]

# 软件包名称,如果需要在别的地方引用此软件包,请用此名称。

name = "hello_world"

# 当前版本号,这里遵循semver标准,也就是语义化版本控制标准。

version = "0.1.0" # the current version, obeying semver

# 软件所有作者列表

authors = ["you@example.com"]

# 非常有用的一个字段,如果要自定义自己的构建工作流,

# 尤其是要调用外部工具来构建其他本地语言(C、C++、D等)开发的软件包时。

# 这时,自定义的构建流程可以使用rust语言,写在"build.rs"文件中。

build = "build.rs"

# 显式声明软件包文件夹内哪些文件被排除在项目的构建流程之外,

# 哪些文件包含在项目的构建流程中

exclude = ["build/**/*.o", "doc/**/*.html"]

include = ["src/**/*", "Cargo.toml"]

# 当软件包在向公共仓库发布时出现错误时,使能此字段可以阻止此错误。

publish = false

# 关于软件包的一个简短介绍。

description = "..."

# 下面这些字段标明了软件包仓库的更多信息

documentation = "..."

homepage = "..."

repository = "..."

# 顾名思义,此字段指向的文件就是传说中的ReadMe,

# 并且,此文件的内容最终会保存在注册表数据库中。

readme = "..."

# 用于分类和检索的关键词。

keywords = ["...", "..."]

# 软件包的许可证,必须是cargo仓库已列出的已知的标准许可证。

license = "..."

# 软件包的非标许可证书对应的文件路径。

license-file = "..."

5.2.2依赖的详细配置:

# 注意,此处的cfg可以使用not、any、all等操作符任意组合键值对。

# 并且此用法仅支持cargo 0.9.0(rust 1.8.0)以上版本。

# 如果是windows平台,则需要此依赖。

[target.'cfg(windows)'.dependencies]

winhttp = "0.4.0"

[target.'cfg(unix)'.dependencies]

openssl = "1.0.1"

#如果是32位平台,则需要此依赖。

[target.'cfg(target_pointer_width = "32")'.dependencies]

native = { path = "native/i686" }

[target.'cfg(target_pointer_width = "64")'.dependencies]

native = { path = "native/i686" }

# 另一种写法就是列出平台的全称描述

[target.x86_64-pc-windows-gnu.dependencies]

winhttp = "0.4.0"

[target.i686-unknown-linux-gnu.dependencies]

openssl = "1.0.1"

# 如果使用自定义平台,请将自定义平台文件的完整路径用双引号包含

[target."x86_64/windows.json".dependencies]

winhttp = "0.4.0"

[target."i686/linux.json".dependencies]

openssl = "1.0.1"

native = { path = "native/i686" }

openssl = "1.0.1"

native = { path = "native/x86_64" }

# [dev-dependencies]段落的格式等同于[dependencies]段落,

# 不同之处在于,[dependencies]段落声明的依赖用于构建软件包,

# 而[dev-dependencies]段落声明的依赖仅用于构建测试和性能评估。

# 此外,[dev-dependencies]段落声明的依赖不会传递给其他依赖本软件包的项目

[dev-dependencies]

iron = "0.2"

5.2.3 自定义编译器配置

cargo内置五种编译器调用模板,分别为dev、release、test、bench、doc,分别用于定义不同类型生成目标时的编译器参数,如果我们自己想改变这些编译模板,可以自己定义相应字段的值.

# 开发模板, 对应`cargo build`命令

[profile.dev]

opt-level = 0 # 控制编译器的 --opt-level 参数,也就是优化参数

debug = true # 控制编译器是否开启 `-g` 参数

rpath = false # 控制编译器的 `-C rpath` 参数

lto = false # 控制`-C lto` 参数,此参数影响可执行文件和静态库的生成,

debug-assertions = true # 控制调试断言是否开启

codegen-units = 1 # 控制编译器的 `-C codegen-units` 参数。注意,当`lto = true`时,此字段值被忽略

# 发布模板, 对应`cargo build --release`命令

[profile.release]

opt-level = 3

debug = false

rpath = false

lto = false

debug-assertions = false

codegen-units = 1

# 测试模板,对应`cargo test`命令

[profile.test]

opt-level = 0

debug = true

rpath = false

lto = false

debug-assertions = true

codegen-units = 1

# 性能评估模板,对应`cargo bench`命令

[profile.bench]

opt-level = 3

debug = false

rpath = false

lto = false

debug-assertions = false

codegen-units = 1

# 文档模板,对应`cargo doc`命令

[profile.doc]

opt-level = 0

debug = true

rpath = false

lto = false

debug-assertions = true

codegen-units = 1

5.2.4 feature段落

[features]段落中的字段被用于条件编译选项或者是可选依赖。例如:

[package]

name = "awesome"

[features]

# 此字段设置了可选依赖的默认选择列表,

# 注意这里的"session"并非一个软件包名称,

# 而是另一个featrue字段session

default = ["jquery", "uglifier", "session"]

# 类似这样的值为空的feature一般用于条件编译,

# 类似于`#[cfg(feature = "go-faster")]`。

go-faster = []

# 此feature依赖于bcrypt软件包,

# 这样封装的好处是未来可以对secure-password此feature增加可选项目。

secure-password = ["bcrypt"]

# 此处的session字段导入了cookie软件包中的feature段落中的session字段

session = ["cookie/session"]

[dependencies]

# 必要的依赖

cookie = "1.2.0"

oauth = "1.1.0"

route-recognizer = "=2.1.0"

# 可选依赖

jquery = { version = "1.0.2", optional = true }

uglifier = { version = "1.5.3", optional = true }

bcrypt = { version = "*", optional = true }

civet = { version = "*", optional = true }

如果其他软件包要依赖使用上述awesome软件包,可以在其描述文件中这样写:

[dependencies.awesome]

version = "1.3.5"

default-features = false # 禁用awesome 的默认features

features = ["secure-password", "civet"] # 使用此处列举的各项features

使用features时需要遵循以下规则:

1.feature名称在本描述文件中不能与出现的软件包名称冲突

2.除了default feature,其他所有的features均是可选的

3.features不能相互循环包含

4.开发依赖包不能包含在内

features组只能依赖于可选软件包

features的一个重要用途就是,当开发者需要对软件包进行最终的发布时,在进行构建时可以声明暴露给终端用户的features,这可以通过下述命令实现:

$ cargo build --release --features "shumway pdf"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值