use std::path::PathBuf;
use serde_derive::Deserialize;
use crate::utils::exec::command;
use crate::{t, Build, Crate};
#[derive(Debug, Deserialize)]
struct Output {
packages: Vec<Package>,
}
#[derive(Debug, Deserialize)]
struct Package {
name: String,
source: Option<String>,
manifest_path: String,
dependencies: Vec<Dependency>,
targets: Vec<Target>,
}
#[derive(Debug, Deserialize)]
struct Dependency {
name: String,
source: Option<String>,
}
#[derive(Debug, Deserialize)]
struct Target {
kind: Vec<String>,
}
pub fn build(build: &mut Build) {
for package in workspace_members(build) {
if package.source.is_none() {
let name = package.name;
let mut path = PathBuf::from(package.manifest_path);
path.pop();
let deps = package
.dependencies
.into_iter()
.filter(|dep| dep.source.is_none())
.map(|dep| dep.name)
.collect();
let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib"));
let krate = Crate { name: name.clone(), deps, path, has_lib };
let relative_path = krate.local_path(build);
build.crates.insert(name.clone(), krate);
let existing_path = build.crate_paths.insert(relative_path, name);
assert!(
existing_path.is_none(),
"multiple crates with the same path: {}",
existing_path.unwrap()
);
}
}
}
fn workspace_members(build: &Build) -> Vec<Package> {
let collect_metadata = |manifest_path| {
let mut cargo = command(&build.initial_cargo);
cargo
.env("RUSTC_BOOTSTRAP", "1")
.arg("metadata")
.arg("--format-version")
.arg("1")
.arg("--no-deps")
.arg("--manifest-path")
.arg(build.src.join(manifest_path));
let metadata_output = cargo.run_always().run_capture_stdout(build).stdout();
let Output { packages, .. } = t!(serde_json::from_str(&metadata_output));
packages
};
let mut packages = vec![];
packages.extend(collect_metadata("Cargo.toml"));
packages.extend(collect_metadata("library/Cargo.toml"));
packages
}