条件付きコンパイル』を使えば、no_std 環境に対応しつつ、かつ std 環境ではより便利になるクレートを作成できる。ここではサンプルを通してその作成手順を紹介する。

cargo.toml ファイル

以下は関係する項目。

package.categories

crates.io などでクレートの検索に使われるカテゴリを指定する。
no_std 環境用の値には no-stdno-std::no-alloc がある。

package.metadata.docs.rs

Docs.rs における rustdoc コマンドの引数を指定する。
詳しくは『rustdoc でのフィーチャーの表示』を参照。

features

条件付きコンパイルのためのフィーチャーを定義する。よく見かける設定は、標準環境用のフィーチャー std をデフォルトとして作り、その配下をヒープメモリのためのフィーチャ alloc などで細分化していくパターンである。



[package]
name = "my_crate"
version = "0.1.0"
categories = ["no-std"]

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["std"]
std = ["alloc"]
alloc = []

lib.rs ファイル

以下が必要になる場合が多い。



#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]

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

// ... //

条件付きコンパイル

条件付きコンパイルを利用した各アイテムを記載する。

アイテム単位

以下では、関数 print_box はフィーチャー alloc の有効時にのみ使用できる。


pub fn print_val<T: std::fmt::Display>(arg: T) {
    println!("{arg}")
}

#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn print_box<T: std::fmt::Display>(arg: Box<T>) {
    println!("`{0}` at '{0:p}'", arg);
}

ファイル単位

以下でも、関数 print_box はフィーチャー alloc の有効時にのみ使用できる。
なお、ここでの path 属性はファイル階層を少し分かりやすくする狙いがある。

some/mod.rs

mod print_basic;
pub use print_basic::*;

#[doc(hidden)]
#[cfg(feature = "alloc")]
#[path = ""]
mod with_alloc {
    mod print_etc;
    pub use print_etc::*;
}

#[cfg(feature = "alloc")]
pub use with_alloc::*;
some/print_basic.rs

pub fn print_val<T: std::fmt::Display>(arg: T) {
    println!("{arg}")
}
some/print_etc.rs

#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn print_box<T: std::fmt::Display>(arg: Box<T>) {
    println!("`{0}` at '{0:p}'", arg);
}