axbuild 0.4.19

An OS build lib toolkit used by arceos
Documentation
use anyhow::anyhow;

use super::metadata::platform_feature_names;

pub(super) fn normalize_axvisor_feature_surface(
    features: &mut Vec<String>,
    target: &str,
    metadata: &cargo_metadata::Metadata,
) -> anyhow::Result<()> {
    let _ = target;
    let known_platforms = platform_feature_names(metadata);
    retain_non_platform_features(features, &known_platforms);
    Ok(())
}

fn retain_non_platform_features(features: &mut Vec<String>, known_platforms: &[String]) {
    features.retain(|feature| {
        nested_platform_feature_name(feature, known_platforms).is_none()
            && ax_hal_platform_feature_name(feature, known_platforms).is_none()
            && !known_platforms.iter().any(|platform| platform == feature)
    });
}

pub(super) fn reject_unsupported_nested_platform_features(
    features: &[String],
    known_platforms: &[String],
) -> anyhow::Result<()> {
    if let Some(feature) = features
        .iter()
        .find(|feature| is_removed_dynamic_platform_feature(feature))
    {
        return Err(anyhow!(
            "Axvisor depends on an ax-std surface with dynamic platform support enabled; remove \
             dynamic platform features from `features`; found `{feature}`"
        ));
    }

    if let Some(feature) = features.iter().find(|feature| {
        nested_platform_feature_name(feature, known_platforms).is_some()
            || known_platforms.iter().any(|platform| platform == *feature)
    }) {
        return Err(anyhow!(
            "Axvisor build configs must use ax-hal platform features directly; found `{feature}`"
        ));
    }
    Ok(())
}

pub(super) fn remove_dynamic_platform_features(features: &mut Vec<String>) {
    features.retain(|feature| !is_removed_dynamic_platform_feature(feature));
}

pub(super) fn is_removed_dynamic_platform_feature(feature: &str) -> bool {
    matches!(
        feature,
        "dyn-plat"
            | "plat-dyn"
            | "axplat-dyn"
            | "ax-hal/plat-dyn"
            | "ax-std/plat-dyn"
            | "axvm/plat-dyn"
            | "ax-driver/plat-dyn"
    ) || feature.starts_with("axplat-dyn/")
}

fn nested_platform_feature_name<'a>(
    feature: &'a str,
    known_platforms: &[String],
) -> Option<&'a str> {
    feature
        .strip_prefix("ax-std/")
        .filter(|name| is_platform_control_feature(name, known_platforms))
}

fn ax_hal_platform_feature_name<'a>(
    feature: &'a str,
    known_platforms: &[String],
) -> Option<&'a str> {
    feature
        .strip_prefix("ax-hal/")
        .filter(|name| known_platforms.iter().any(|platform| platform == name))
}

fn is_platform_control_feature(name: &str, known_platforms: &[String]) -> bool {
    name == "plat-dyn" || known_platforms.iter().any(|platform| platform == name)
}