首页 > 解决方案 > 将 `#![no_std]` 添加到库时,该库的用户是否有任何缺点或复杂性?

问题描述

我写了一个 Rust 库。我听说了这个no_std功能,并注意到我的库不使用andstd不提供的任何东西。所以理论上我可以添加属性并更改一些导入。corealloc#![no_std]

但我想知道这如何影响我图书馆的用户。当然,我希望通过使用#![no_std]no_std环境中的用户也可以使用我的 crate。这当然很好。但是:我的图书馆的用户对我的图书馆有什么不利no_std吗?例如,他们是否也被迫使用#![no_std]? 那会很糟糕。我想知道,因为大多数 crate 都隐藏no_std了 Cargo 功能背后的兼容性。我实际上在网上找不到关于这个问题的任何信息。

如果使用 没有缺点,那么每个可以不使用#![no_std]的箱子都应该添加该属性,对吗?std

标签: rust

解决方案


例如,他们是否也被迫使用#![no_std]?

一点也不。依赖的 crate(即,将使用您的 crate 的 crate/项目)将知道找到core您的依赖项所需的 crate,并且可以像no_std曾经参与过一样自由使用它。主要区别在于对这种依赖的期望以及有多少其他 crate 可以使用它。换句话说,与您的依赖项兼容的 crate 集应该始终是一个超集,如果该依赖项已准备好用于no_std.

KodrAus/rust-nostd的自述文件是在库中使用和测试的示例no_std,也建议no_std尽可能使用以实现最大兼容性:

Rust 标准库的当前设计分为几层,每一层都建立在下面一层的假定平台能力之上。有:

  • std:完整的标准库假定存在线程、文件系统和网络。[...]
  • alloc:集合层建立在核心之上,假设运行时支持动态内存分配。
  • core:核心层对 > 底层平台没有(嗯,不是很多)假设。核心支持几乎所有可以运行 Rust 代码的目标。

因此,当您设计您的库时,您可以通过尽可能针对标准库的最低层来使其具有最大的可移植性。

一些 crate 放置no_stdCargo 功能的原因是因为 crate 可能包含一些确实需要std或至少需要的可选功能alloc。通过调整 Cargo 特性,没有标准库的环境仍然可以使用 crate,而那些有stdalloc可以使用 crate 的扩展 API 的环境。显示此功能的“lib.rs”示例如下所示。

#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate core;

#[cfg(feature = "alloc")]
extern crate alloc;

pub fn foo_into_slice(slice: &mut [u8]) { unimplemented!() }

/// Vec requires alloc
#[cfg(feature = "alloc")]
use alloc::vec::Vec;

#[cfg(feature = "alloc")]
pub fn foo_into_vec(vec: &mut Vec<u8>) { unimplemented!() }

推荐阅读