mod config;
mod features;
mod load;
mod metadata;
#[cfg(test)]
mod tests;
pub type AxvisorBuildInfo = config::AxvisorBuildInfo;
use std::path::{Path, PathBuf};
use anyhow::{Context, anyhow};
pub(crate) use config::AxvisorBoardFile;
pub use config::{AXVISOR_PACKAGE, AxvisorBoardConfig};
pub(crate) use load::{
default_build_info_path, load_board_file, load_target_from_build_config,
resolve_build_info_path,
};
use ostool::build::config::Cargo;
use self::{
config::LoadedAxvisorBuildConfig, features::reject_unsupported_nested_platform_features,
load::load_build_config, metadata::platform_feature_names,
};
pub use crate::build::LogLevel;
use crate::context::ResolvedAxvisorRequest;
pub(crate) fn workspace_root_from_axvisor_dir(axvisor_dir: &Path) -> PathBuf {
load::workspace_root_from_axvisor_dir(axvisor_dir)
}
pub(crate) fn load_cargo_config(request: &ResolvedAxvisorRequest) -> anyhow::Result<Cargo> {
let metadata =
crate::build::cached_workspace_metadata().context("failed to load workspace metadata")?;
to_cargo_config(load_build_config(request)?, request, metadata)
}
fn to_cargo_config(
mut config: LoadedAxvisorBuildConfig,
request: &ResolvedAxvisorRequest,
metadata: &cargo_metadata::Metadata,
) -> anyhow::Result<Cargo> {
config.target = request.target.clone();
let makefile_features = crate::build::makefile_features_from_env();
crate::build::apply_makefile_features(&mut config.build_info, &makefile_features)?;
let known_platforms = platform_feature_names(metadata);
reject_unsupported_nested_platform_features(&config.build_info.features, &known_platforms)?;
let mut cargo = config
.build_info
.into_prepared_std_cargo_config_with_metadata(&request.package, &config.target, metadata)?;
patch_axvisor_cargo_config(&mut cargo, request, &config.vm_configs)?;
Ok(cargo)
}
fn patch_axvisor_cargo_config(
cargo: &mut Cargo,
request: &ResolvedAxvisorRequest,
config_vmconfigs: &[PathBuf],
) -> anyhow::Result<()> {
cargo.package = request.package.clone();
ensure_axvisor_bin_arg(&mut cargo.args);
cargo
.env
.insert("AX_ARCH".to_string(), request.arch.clone());
cargo
.env
.insert("AX_TARGET".to_string(), request.target.clone());
let vmconfigs = if request.vmconfigs.is_empty() {
config_vmconfigs
.iter()
.map(|path| resolve_build_config_vmconfig_path(request, path))
.collect::<Vec<_>>()
} else {
request.vmconfigs.clone()
};
if !vmconfigs.is_empty() {
let joined = std::env::join_paths(&vmconfigs)
.map_err(|e| anyhow!("failed to join vmconfig paths: {e}"))?;
cargo.env.insert(
"AXVISOR_VM_CONFIGS".to_string(),
joined.to_string_lossy().into_owned(),
);
}
cargo.features.sort();
cargo.features.dedup();
Ok(())
}
fn resolve_build_config_vmconfig_path(request: &ResolvedAxvisorRequest, path: &Path) -> PathBuf {
if path.is_absolute() {
return path.to_path_buf();
}
let workspace_root = request
.axvisor_dir
.parent()
.and_then(Path::parent)
.unwrap_or(&request.axvisor_dir);
workspace_root.join(path)
}
fn ensure_axvisor_bin_arg(args: &mut Vec<String>) {
if args.iter().any(|arg| arg == "--bin") {
return;
}
args.push("--bin".to_string());
args.push(AXVISOR_PACKAGE.to_string());
}