Rust学习之Features

Rust学习之Features

    • 一 什么是 Features
    • 二 默认 feature
    • 三 简单的features应用示例
    • 四 可选(optional)的依赖
    • 五 依赖的特性
      • 5.1 在依赖表中指定
      • 5.2 在features表中指定
    • 六 命令行中特性控制
    • 七 特性统一路径
    • 八 其它
      • 8.1 相互排斥特性
      • 8.2 观察启用特性
      • 8.3 [Feature resolver version 2](https://doc.rust-lang.org/cargo/reference/features.html#feature-resolver-version-2)

本文是学习Solana 程序库合约(SPL)的Rust 预先知识部分,需要有Rust基础

本文学习课程为https://doc.rust-lang.org/cargo/reference/features.html 。下面的内容为一些简单记录。

下面的内容中,feature和特性会交叉出现,但是均指同一概念。

一 什么是 Features

Features 是用来表达条件编译或者条件依赖的机制。

定义在Cargo.toml中的[features]表中的features 可以启用或者不启用。在构建时通过命令行参数--features来启用需要的特性,作为依赖启用特性时,直接在Cargo.toml中定义。

基本的features块定义为:

[features]
# Defines a feature named `webp` that does not enable any other features.
webp = []

在Rust中使用webp特性的代码示例:

// This conditionally includes a module which implements WEBP support.
#[cfg(feature = "webp")]
pub mod webp;// 下面是不启用"no-entrypoint"才包含entrypoint模块的定义
#[cfg(not(feature = "no-entrypoint"))]
mod entrypoint;

特性可以包含其它特性

[features]
bmp = []
png = []
ico = ["bmp", "png"]
webp = []// 注意,下面bmp和png的定义顺序任意,可以放在ico的下面

二 默认 feature

默认程序时不启用任何特性的,但是我们可以定义程序默认启用的features

[features]
default = ["ico", "webp"]
bmp = []
png = []
ico = ["bmp", "png"]
webp = []

三 简单的features应用示例

接着上面的Cargo.toml定义,一个简单的应用示例:

fn main() {#[cfg(feature = "webp")]println!("Hello webp!");#[cfg(not(feature = "webp"))]println!("Hello not webp!");#[cfg(feature = "ico")]println!("Hello ico!");#[cfg(feature = "gif")]println!("Hello gif!");
}

运行结果如下:

$ cargo run
Hello not webp!
Hello ico!$ cargo run --features webp
Hello webp!
Hello ico!

默认时仅启用了default未启用,所以上面cargo run输出了ico

注意:就算指定了--features参数,默认特性还是会启用。关闭它有两种方法:

  • 命令行参数使用--no-default-features
  • 作为依赖库,在定义时,设定default-features = false选项。

因此,我们如果在cargo run时不想启用默认特性,运行如下命令:

$ cargo run --features webp --no-default-features
Hello webp!

注意:原文提到了要小心默认特性设置,它通常启用了一些方便用户使用常用功能。但万一用户不想启用这些功能时,需要在所有依赖定义中限定default-features = false.特别当一个包被多处依赖时,每处定义都要指定default-features = false.

四 可选(optional)的依赖

依赖库也可以标记为optional,它意味着默认情况下不会被编译。例如如下定义:

[dependencies]
gif = { version = "0.11.1", optional = true }

默认时gif依赖是未启用的,那怎么启用它呢?其实上面的定义同时隐式定义了一个gif特性,类似如下定义:

[features]
gif = ["dep:gif"]

当然,我们无需手动写出上面的定义,但是如果你不想使用默认名称(和库名相同),就得手写一个了,如果你手写了,那么隐式特性就不存在了。例如如下示例:

[dependencies]
ravif = { version = "0.6.3", optional = true }
rgb = { version = "0.8.25", optional = true }[features]
avif = ["dep:ravif", "dep:rgb"]

上面的定义中,用户只能选择avif特性,阻止用户单独选择ravif或者rgb,因为也许这两者是必须同时启用的。

切记,采用上面的方式时,依赖必须是optional

五 依赖的特性

5.1 在依赖表中指定

在定义外部依赖的同时还可以同时指定启用的特性,例如:

[dependencies]
# Enables the `derive` feature of serde.
serde = { version = "1.0.118", features = ["derive"] }
flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] }

注意:上面提到过,就算指定了依赖的features(不是feature,因为可以指定启用多个特性,所以为一数组,是带复数的s),其默认特性依然是开启的,因此我们必须手动关掉它,正如flate2定义。当然,如果别的地方同时也用到了flate2,那么无法保证其默认特性是关闭的,前面提到过原因。

5.2 在features表中指定

依赖的特性也可以在features表中定义(上面的是在dependencies表中定义),语法为package-name/feature-name,示例如下:

[dependencies]
jpeg-decoder = { version = "0.1.20", default-features = false }[features]
# Enables parallel processing support by enabling the "rayon" feature of jpeg-decoder.
parallel = ["jpeg-decoder/rayon"]

可以看到,这种方式定义时,关闭默认特性还是在dependencies表中进行。

注意当依赖为可选依赖时,package-name/feature-name语法还会同时启用该依赖,然而有时你却不想这么做,那么可以使用如下语法

package-name?/feature-name 。这样只有在其它别处启用该依赖后定义的特性才会被启用。示例如下:

[dependencies]
serde = { version = "1.0.133", optional = true }
rgb = { version = "0.8.25", optional = true }[features]
serde = ["dep:serde", "rgb?/serde"]

上面的定义中,启用serde特性会启用 serde 依赖库,但是只有在其它地方启用rgb依赖库了它才会启用rgbserde特性,例如我们定义了一个新的特性,其它即启用了rgb又包含了上面定义的serde特性。

(下面代码未验证,仅为个人猜想)

[features]
serde = ["dep:serde", "rgb?/serde"]
all= ["dep:rgb","serde"]

六 命令行中特性控制

  • --features FEATURES: 指定启用的特性,注意可以指定多个特性,它是一个列表,使用逗号或者空格分隔。如果使用空格分隔,注意在所有特性整体名称上加上双引号。例如我们接最初的toml及程序定义,运行示例:

    $ cargo run --features webp gif
    Hello webp!
    Hello ico!$ cargo run --features "webp gif"
    Hello webp!
    Hello ico!
    Hello gif!// 下面webp,gif中逗号前后可以有空格
    $ cargo run --features webp,gif --no-default-features 
    Hello webp!
    Hello gif!
    
  • --all-features: 启用所有特性

  • --no-default-features: 不启用默认特性

七 特性统一路径

当一个依赖在多个包中使用时,Cargo会使用所有启用特性的统一路径来标记它,从而确保只有一份单一的代码被使用(无重复代码)。

如下图所示:

在这里插入图片描述

此时,构建my-package时会启用winapi的四个特性。

特性中有一个共识是增加性,也就是启用一个特性不会关闭已有的功能,并且任意特性之间都可以联合使用。

例如 ,当你想支持no_std环境时,不要使用no_std特性(不要做减法),而是使用一个std特性来启用std库。示例代码如下:

#![no_std]#[cfg(feature = "std")]
extern crate std;#[cfg(feature = "std")]
pub fn function_that_requires_std() {// ...
}

上面的代码中,如果启用std特性,就使用std库,同时启用相应的函数。在revm (Rust EVM实现)中能见到大量这种用户,因为区块链运行环境并不一定支持std,所以统一使用#![no_std].

八 其它

8.1 相互排斥特性

通常不要这么设计(因为在确保任意特性联合都可以安全使用),但万一存在两个排斥特性时,需要进行检测并给出编译错误,例如

#[cfg(all(feature = "foo", feature = "bar"))]
compile_error!("feature \"foo\" and feature \"bar\" cannot be enabled at the same time");

三种替代方案为:

  • 分离不同功能到不同的包
  • 使用其中一个包替换另一个
  • 重构代码消除排斥性特性。

8.2 观察启用特性

cargo tree命令可以观察哪些特性被启用了,主要有这么几种用法

  • cargo tree -e features: 待研究
  • cargo tree -f "{p} {f}": 待研究
  • cargo tree -e features -i foo: 待研究

8.3 Feature resolver version 2

特研究

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/662679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从源码角度透视QTcpServer:解构QTcpServer的底层原理与技术细节

深入了解QTcpServer的底层原理和技术细节 一、背景二、QTcpServer的基本原理2.1、TCP协议简介2.2、QTcpServer的概念 三、QTcpServer源码解析3.1、QTcpServer的构造函数3.2、调用listen函数启动tcpserver3.3、QSocketNotifier的实现 总结 一、背景 QTcpServer是Qt网络模块中的…

docker 容器指定主机网段

docker 容器指定主机网段。 直接连接到物理网络:使用macvlan技术可以让Docker容器直接连接到物理网络,而不需要通过NAT或端口映射的方式来访问它们。可以提高网络性能和稳定性,同时也可以使容器更加透明和易于管理。 1、首先需要查询网卡的…

vuex store,mutations,getters,actions

文章目录 1.vuex概述2.构建vuex【多组件数据共享】环境Son1.vueSon2.vueApp.vue 3.创建一个空仓库4.如何提供&访问vuex的数据①核心概念 - state状态1.通过store直接访问2.通过辅助函数简化代码 ②核心概念 - mutations(粗略) 5.核心概念 - mutation…

Leetcode29-最大频率元素计数(3005)

1、题目 给你一个由 正整数 组成的数组 nums 。 返回数组 nums 中所有具有 最大 频率的元素的 总频率 。 元素的 频率 是指该元素在数组中出现的次数。 示例 1: 输入:nums [1,2,2,3,1,4] 输出:4 解释:元素 1 和 2 的频率为 …

python3基础学习一

打印print()函数 R 主要的原因是为防止转义,保证r后面的内容全文输出f “主要作用就是格式化字符串,加上f以后,{“变量/表达式”},花括号里的变量和表达式就可以使用了” def ptSubstr():msg "hello,world!"print(msg[0:-1]);prin…

在Django Admin添加快捷方式django-admin-shortcuts

在Django管理主页上添加简单漂亮的快捷方式。 1.安装 pip install django-admin-shortcuts 2在settings.py注册django-admin-shortcuts INSTALLED_APPS [admin_shortcuts,django.contrib.admin,....... ] 3.添加ADMIN_SHORTCUTS设置 ADMIN_SHORTCUTS [ { ti…

k8s二进制及负载均衡集群部署详解

目录 常见部署方式 二进制部署流程 环境准备 操作系统初始化配置 关闭防火墙 配置SELinux 关闭SWAP 根据规划设置主机名 在master添加hosts,便于主机名解析 调整内核参数 配置时间同步 部署docker引擎 在所有node节点部署docker引擎 部署etcd集群 签发…

合约短线高胜率策略-扭转乾坤指标使用说明

扭转乾坤指标使用说明 行情判断 双绿线 多趋势双红线 空趋势大绿线 小红线 多震荡大红线 小绿线 空震荡 进场条件 趋势行情进场 多趋势 多信号 底金叉 做多空趋势 空信号 顶死叉 做空 震荡行情进场 多震荡 多信号 底金叉 做多多震荡 空信号 顶死叉 做空空…

idea docker 镜像生成太慢太大问题

文章目录 前言一、更小的jdk基础镜像二、服务瘦包(thin jar)2.1 maven2.2 修改dockerfile2.3 container run options 三、 基础jdk镜像入手?总结 前言 idea docker 内网应用实践遗留问题 idea docker插件 build 服务镜像太慢服务镜像太大 …

【Java程序设计】【C00223】基于Springboot+vue的图书购物商城(论文)

基于Springbootvue的图书购物商城(论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springbootvue的前后端分离的图书商城购物系统 本系统分为用户以及管理员2个角色。 用户:用户登录后、可以查看新上架的书籍和新闻等…

npm ERR! reason: certificate has expired(淘宝镜像过期)

npm ERR! request to https://registry.npm.taobao.org/yauzl/-/yauzl-2.4.1.tgz failed, reason: certificate has expired 今天在执行npm install命令时,报错百度了下是淘宝证书过期原因 解决方法一 执行下面两个命令再进行npm install即可 npm cache clean --…

【深度学习】从0完整讲透深度学习第2篇:TensorFlow介绍和基本操作(代码文档已分享)

本系列文章md笔记(已分享)主要讨论深度学习相关知识。可以让大家熟练掌握机器学习基础,如分类、回归(含代码),熟练掌握numpy,pandas,sklearn等框架使用。在算法上,掌握神经网络的数学原理,手动实…

02链表:19、删除链表的倒数第N个节点

19、删除链表的倒数第N个节点 文章目录 19、删除链表的倒数第N个节点方法一:快慢指针 思路:使用虚拟头节点快慢指针,fast指针先走n1,直到为null,slow节点刚好在删除元素前一个位置,方便操作 重点&#xff1…

2024美赛数学建模B题思路源码

赛题目的 赛题目的: 问题描述: 解题的关键: 问题一. 问题分析 问题解答 问题二. 问题分析 问题解答 问题三. 问题分析 问题解答 问题四. 问题分析 问题解答 问题五. 问题分析 问题解答

云计算基础(云计算概述)

目录 一、云计算概述 1.1 云计算的概念 1.1.1 云计算解决的问题 1.1.2 云计算的概念 1.1.3 云计算的组成 1.2 云计算主要特征 1.2.1 按需自助服务 1.2.2 泛在接入 1.2.3 资源池化 1.2.4 快速伸缩性 1.2.5 服务可度量 1.3 云计算服务模式 1.3.1 软件即服务(Softwar…

老师罚学生钱违法吗

在教师岗位上耕耘了近十年,我遇到过无数的学生和无数的教学情境。其中,有一个问题始终困扰着我:在某些情况下,我能否用“罚钱”的方式来纠正学生的行为?当然,这还涉及到许多复杂的因素:学校的规…

Pandas快问快答1-15题

如果你是一名使用python进行过数据处理的程序员,那你对Pandas必然不陌生。pandas是一个开源的第三方Python库,旨在提供快速、灵活和富有表现力的数据结构,以便能够简单、直观地处理关系型和标记型数据。它的名字来源于面板数据(Pa…

Linux项目的挂起与结束

后台挂起 nohup java -jar java_gobang.jar & 结束项目 先查询pid ps -ef | grep java_gobang 结束: kill -9 23183

Ruoyi-Cloud-Plus_Nacos配置服务漏洞CVE-2021-29441_官方解决方法以及_修改源码解决---SpringCloud工作笔记199

CVE-2021-29441 这个漏洞是Nacos的,通过使用postman,直接访问接口: 就可以直接添加nacos的用户 Nacos是Alibaba的一个动态服务发现、配置和服务管理平台。攻击者通过添加Nacos-Server的User-Agent头部将可绕过(nacos.core.auth.enabled=true)鉴权认证,从而进行API操作。 …

工业智能网关构建智慧污水处理远程监测及管理

污水处理厂是为了处理生活污水和工业废水而建立的设施。为了监测和控制污水处理过程,现代污水处理厂采用了智能工业网关物联网技术。智慧污水系统能够通过工业网关远程监测厂内各个环节的运行情况,提高处理效率和管理水平。 智能工业网关能够将不同设备…