1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
use serde::Deserialize;
use std::process::Command;
// We don't use cargo-metadata because it has a very unstable API!
#[derive(Deserialize, Debug)]
struct Metadata {
workspace_members: Vec<PackageId>,
resolve: MResolve,
packages: Vec<MPackage>,
}
#[derive(Deserialize, Debug)]
struct MResolve {
nodes: Vec<MNode>,
}
#[derive(Deserialize, Debug)]
struct MNode {
id: PackageId,
dependencies: Vec<PackageId>,
}
#[derive(Deserialize, Debug)]
struct MPackage {
id: PackageId,
version: String,
name: String,
}
#[derive(Deserialize, Debug, Eq, PartialEq)]
#[serde(transparent)]
struct PackageId(String);
impl Metadata {
fn package(&self, id: &PackageId) -> &MPackage {
self.packages.iter()
.find(|p| &p.id == id).expect("missing")
}
}
struct Context<'c> {
hippo: &'c MNode,
metadata: &'c Metadata,
}
impl Context<'_> {
fn emit_for_package(&self, package: &str, versions: &[&str]) {
let pkg = self.hippo.dependencies.iter()
.map(|i| self.metadata.package(i))
.find(|i| i.name == package).expect("no nix in hippotat's deps");
let pkg = &pkg.version;
let pkg: semver::Version = pkg.parse().expect(pkg);
for test in versions {
let cfg = test.replace('.', "_").replace(">=", "ge_");
let test: semver::VersionReq = test.parse().unwrap();
let cfg = format!("{package}_{cfg}");
println!(r#"cargo:rustc-check-cfg=cfg({cfg})"#);
if test.matches(&pkg) {
println!("cargo:rustc-cfg={cfg}");
}
}
}
}
fn main(){
let x = Command::new("cargo")
.args(["metadata", "--format-version=1"])
.stderr(std::process::Stdio::inherit())
.output().unwrap();
if !x.status.success() { panic!() }
let output = std::str::from_utf8(&x.stdout).unwrap();
// eprintln!("{}", output);
let metadata: Metadata = serde_json::from_str(&output).unwrap();
let hippo = metadata.workspace_members.iter()
.map(|i| metadata.package(i))
.find(|p| p.name == "hippotat").expect("no hippotat in workspace?");
let hippo = metadata.resolve.nodes.iter()
.find(|n| n.id == hippo.id).expect("no hippotat in nodes!");
let ctx = Context { hippo, metadata: &metadata };
ctx.emit_for_package("nix", &[">=0.27", ">=0.28"]);
}
|