Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

89 lines
3.5 KiB
Rust

//! Build script: generate the third-party dependency/license manifest
//! that `mirage about` prints.
//!
//! At build time we ask cargo for the fully-resolved dependency graph
//! (`cargo metadata`) and distil it into a small, sorted text manifest
//! of every crate mirage links, with its version and SPDX license. The
//! manifest is written to `OUT_DIR/about.txt` and embedded into the
//! binary via `include_str!`, so `mirage about` needs no files at
//! runtime and the list can never drift from what was actually built.
//!
//! The generation is best-effort: if `cargo metadata` is unavailable
//! (e.g. a restricted offline build) we still emit a valid, if sparse,
//! manifest so the build never fails on account of `about`.
use std::path::PathBuf;
fn main() {
// Only regenerate when the resolved dependency set changes.
println!("cargo:rerun-if-changed=Cargo.lock");
println!("cargo:rerun-if-changed=build.rs");
let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR set by cargo"));
let manifest = generate_manifest().unwrap_or_else(|e| {
println!("cargo:warning=mirage about: could not build dependency manifest: {e}");
String::from("(third-party dependency manifest unavailable for this build)\n")
});
std::fs::write(out_dir.join("about.txt"), manifest).expect("write about.txt");
}
/// Run `cargo metadata` and render the dependency/license manifest.
fn generate_manifest() -> Result<String, String> {
let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
let output = std::process::Command::new(cargo)
.args(["metadata", "--format-version", "1", "--all-features"])
.output()
.map_err(|e| format!("spawn cargo metadata: {e}"))?;
if !output.status.success() {
return Err(format!("cargo metadata exited with {}", output.status));
}
let value: serde_json::Value =
serde_json::from_slice(&output.stdout).map_err(|e| format!("parse metadata json: {e}"))?;
let packages = value
.get("packages")
.and_then(|p| p.as_array())
.ok_or("metadata has no packages array")?;
// Collect (name, version, license) for every resolved crate, skipping
// the mirage workspace crates themselves (they're first-party).
let mut entries: Vec<(String, String, String)> = Vec::new();
for pkg in packages {
let name = pkg.get("name").and_then(|v| v.as_str()).unwrap_or("");
if name.is_empty()
|| name == "mirage"
|| name.starts_with("mirage_")
|| name == "rocjitsu_sys"
{
continue;
}
let version = pkg.get("version").and_then(|v| v.as_str()).unwrap_or("");
let license = pkg
.get("license")
.and_then(|v| v.as_str())
.filter(|s| !s.is_empty())
.map(str::to_string)
.or_else(|| {
pkg.get("license_file")
.and_then(|v| v.as_str())
.filter(|s| !s.is_empty())
.map(|f| format!("see {f}"))
})
.unwrap_or_else(|| "(unspecified)".to_string());
entries.push((name.to_string(), version.to_string(), license));
}
entries.sort();
entries.dedup();
let mut out = String::new();
out.push_str(&format!(
"mirage links {} third-party crate(s):\n\n",
entries.len()
));
for (name, version, license) in &entries {
out.push_str(&format!(" {name} {version} — {license}\n"));
}
Ok(out)
}