使用“std”和“no_std”属性与包含 WASM 之间的关系

mkl*_*mkl 5 rust blockchain substrate polkadot

我刚刚开始研究基材,添加托盘教程已经让我严重困惑:

值得注意的是,Substrate 运行时会编译为本机 Rust std 二进制文件和 WebAssembly (Wasm) 二进制文件。std有关编译和功能的更多信息no_std,请参阅 XXX。

这很好,我很熟悉stdno_std。我的印象是,您要么已std启用并编译为本机 Rust 二进制文件,要么未启用并编译为 WASM 二进制文件。

但是,当我检查运行时时lib.rs,我发现以下内容:

#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]

// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));

// ...
Run Code Online (Sandbox Code Playgroud)

std这让我很困惑:为什么 WASM 二进制文件在启用时“可用” ?我本以为情况恰恰相反。在这种情况下,“可用”到底意味着什么?

我更深入地挖掘了一下,在旧版本的教程中发现了以下内容,该版本更加详细,导致了更严重的精神混乱:

这对于使 Substrate 运行时能够编译为本机二进制文件(支持 Rust std)和 Wasm 二进制文件(不支持:)非常重要no_std

(同样,这很好,尽管我不确定他们所说的“支持”是什么意思。)然后,参考我在上面发布的第一行的文件:

您可以看到,在文件的顶部,我们定义了no_std当我们不使用该功能时将使用的std功能。在下面几行,您可以在 wasm_binary.rs 导入上方看到#[cfg(feature = "std")],这是一个标志,表示仅在启用该功能时导入 WASM 二进制文件std

什么?!

那么,如果std启用了,那么我们就使用 RuststdWASM 吗?当std未启用时,我们使用libcore? 这似乎与之前的说法完全矛盾。

我绝对确定这一切都是我犯下的一个严重愚蠢错误的结果,但我无法弄清楚。

编辑。我与 Shawn Tabrizi 就这个主题进行了一次非常有启发性的对话:https://github.com/substrate-developer-hub/substrate-docs/issues/531

h4x*_*tab 4

Substrate 运行时代码(包括 Pallet)有两个编译目标:std原生二进制文件和no_stdwasm 二进制文件。这是必要的,因为 Substrate 支持运行 wasm 运行时以实现可升级性,并支持运行本机二进制文件以提高性能(或轻松测试)。

当您编译区块链时,它将调用自定义构建脚本(build.rs在运行时箱中)首先构建 wasm 二进制文件,将其保存在构建目录中,然后构建嵌入wasm_binary.rs. 这回答了您关于“可用”的问题。

因此,以下代码意味着,如果处于std模式下,它将包含模式中内置的 wasm 文件no_std,嵌入到wasm_binary.rs文件中。

#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
Run Code Online (Sandbox Code Playgroud)

  • 据我所知,直接在 no_std 模式下构建运行时是极其罕见的。no_std 构建通常仅从 build.rs 启动。但是,如果您必须这样做,则运行时可能仍会在 wasm 目标中构建,但不会嵌入到外部构建中,因为它不是标准的。 (2认同)