axbuild 0.4.14

An OS build lib toolkit used by arceos
Documentation
use std::path::{Path, PathBuf};

use anyhow::Context;
use ax_config_gen::read_config_string;

use super::{AXSTD_STD_CLIPPY_FEATURES, AXSTD_STD_DEFAULT_FEATURE, AXSTD_STD_PACKAGE};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(super) enum ClippyCheckKind {
    Base,
    Feature(String),
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(super) enum ClippyDepsMode {
    NoDeps,
    WithDeps,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(super) struct ClippyCheck {
    pub(super) package: String,
    pub(super) kind: ClippyCheckKind,
    pub(super) deps_mode: ClippyDepsMode,
    pub(super) target: Option<String>,
    pub(super) env: Vec<(String, String)>,
    pub(super) axconfig_override: Option<ClippyAxconfigOverride>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(super) struct ClippyAxconfigOverride {
    pub(super) target: String,
    pub(super) platform_config: PathBuf,
    pub(super) out_config: PathBuf,
    pub(super) overrides: Vec<String>,
}

impl ClippyAxconfigOverride {
    pub(super) fn generate(&self, workspace_root: &Path) -> anyhow::Result<()> {
        let platform_name =
            read_config_string(std::slice::from_ref(&self.platform_config), "platform")
                .with_context(|| {
                    format!(
                        "failed to read platform name from {}",
                        self.platform_config.display()
                    )
                })?;

        crate::build::generate_axconfig(
            workspace_root,
            &self.target,
            &platform_name,
            &self.platform_config,
            &self.out_config,
            None,
            &self.overrides,
        )
        .with_context(|| {
            format!(
                "failed to generate clippy axconfig override at {}",
                self.out_config.display()
            )
        })
    }
}

impl ClippyCheck {
    pub(super) fn cargo_args(&self) -> Vec<String> {
        let mut args = match &self.kind {
            ClippyCheckKind::Base => vec!["clippy".into(), "-p".into(), self.package.clone()],
            ClippyCheckKind::Feature(feature) => vec![
                "clippy".into(),
                "-p".into(),
                self.package.clone(),
                "--no-default-features".into(),
                "--features".into(),
                feature.clone(),
            ],
        };
        if self.package == AXSTD_STD_PACKAGE
            && matches!(&self.kind, ClippyCheckKind::Feature(feature) if feature == AXSTD_STD_DEFAULT_FEATURE)
        {
            args = vec![
                "clippy".into(),
                "-p".into(),
                self.package.clone(),
                "--no-default-features".into(),
                "--features".into(),
                AXSTD_STD_CLIPPY_FEATURES.into(),
            ];
        }
        if matches!(self.deps_mode, ClippyDepsMode::NoDeps) {
            args.insert(1, "--no-deps".into());
        }
        if let Some(target) = &self.target {
            args.extend(["--target".into(), target.clone()]);
        }
        args.extend(["--".into(), "-D".into(), "warnings".into()]);
        args
    }

    pub(super) fn label(&self) -> String {
        let base = match &self.kind {
            ClippyCheckKind::Base => format!("{} (base", self.package),
            ClippyCheckKind::Feature(feature) => {
                format!("{} (feature: {}", self.package, feature)
            }
        };

        match &self.target {
            Some(target) => format!("{base}, target: {target})"),
            None => format!("{base})"),
        }
    }

    pub(super) fn env_prefix(&self) -> String {
        self.env
            .iter()
            .map(|(key, value)| format!("{key}={value}"))
            .collect::<Vec<_>>()
            .join(" ")
    }
}