条件付きコンパイルについて。

分岐方法

専用の分岐方法がいくつかある。

cfg マクロ

条件によって truefalse の値になる。

以下では、OS ごとに通常の if 文で分岐している。


fn main() {
    println!("I am using '{}'.", os_name());
}

fn os_name() -> &'static str {
    if cfg!(target_os = "ios") {
        "iOS"
    } else if cfg!(target_os = "macos") {
        "macOS"
    } else {
        "non-Apple OS"
    }
}

cfg 属性

条件によって直後のコードブロックのコンパイル有無を変更する。

以下では、OS ごとに実装コードを分けている。


fn main() {
    println!("I am using '{}'.", os_name());
}

fn os_name() -> &'static str {
    #[cfg(target_os = "ios")]
    return "iOS";

    #[cfg(target_os = "macos")]
    return "macOS";

    #[cfg(not(any(target_os = "ios", target_os = "macos")))]
    return "non-Apple OS";
}

cfg_attr 属性

条件によって直後のコードブロックへの属性の適用有無を変更する。

以下では、OS ごとに実装ファイルを分けている。

main.rs

#[cfg_attr(target_os = "ios", path = "ios.rs")]
#[cfg_attr(target_os = "macos", path = "macos.rs")]
#[cfg_attr(not(any(target_os = "ios", target_os = "macos")), path = "os.rs")]
mod os;

fn main() {
    println!("I am using '{}'.", os::os_name());
}
ios.rs

pub fn os_name() -> &'static str {
    "iOS"
}
macos.rs

pub fn os_name() -> &'static str {
    "macOS"
}
os.rs

pub fn os_name() -> &'static str {
    "non-Apple OS"
}

分岐フラグ

専用の分岐フラグが多数用意されている。

構成オプション

構成オプションにはキーのみのものとキーと値からなるものがある。

以下はそれらの抜粋 (詳細は公式資料を参照)。

キーのみ
test
テスト時のみ有効
debug_assertions
デバッグモード時のみ有効
unix
target_family = "unix" と等価
windows
target_family = "windows" と等価
キーと値
feature = "value"
フィーチャーを指定
target_os = "value"
OS を指定
target_family = "value"
OS ファミリを指定
target_endian = "value"
エンディアンを指定
target_pointer_width = "value"
ポインタサイズを指定

フィーチャー

feature は条件として使える独自定義できる変数である。

自クレートでのフィーチャーの定義

クレートが対応する feature の値は cargo.toml ファイルで定義できる。

フィーチャーはネストでき、あるフィーチャを有効にするとその配下も有効になる。

デフォルトで有効にしたいフィーチャーは default フィーチャーの配下にする。


[package]
name = "my_crate"
version = "0.1.0"

[features]
default = ["feature1"]
feature1 = []
feature2 = ["feature2_1", "feature2_2"]
feature2_1 = []
feature2_2 = []
feature3 = ["feature3_1", "feature3_2"]
feature3_1 = []
feature3_2 = []

自クレートで定義されたフィーチャーの利用

cargo build に実行オプションを指定する。デフォルトのフィーチャーが不要なら --no-default-features を、全てのフィーチャーが必要なら --all-features を、個別指定するには --features "feature1 feature2" のようにする。

または、.cargo/config.toml ファイルの rustflags の項目を指定する。なお、rustflags の親項目は全体設定用の build の他に target 系があり、それらでは構成に応じたフィーチャの導入も可能 (詳しくは config.toml公式資料を参照)。


[build]
rustflags = ["--cfg", "feature2", "feature3"]

他クレートで定義されたフィーチャーの利用

config.toml ファイルで他クレートのフィーチャーを指定する。これには、他クレートへの依存と同時に記述する方法、そして自クレートのフィーチャーを他クレートのフィーチャと連携させる方法がある。


[package]
name = "my_app"
version = "0.1.0"

[dependencies]
extenal_crate1 = { version = "0.1.0", default-features=false }
extenal_crate2 = { version = "0.1.0", default-features=true }

[dev-dependencies]
extenal_crate3 = { version = "0.1.0", features=["deep_test"] }

[features]
default = ["my_feature"]
my_feature = ["extenal_crate2/additional_feature"]