lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

portable_qualification.rs (4163B)


      1 use std::{fs, path::Path, process::Command};
      2 
      3 use serde::Deserialize;
      4 
      5 #[derive(Debug, Deserialize)]
      6 struct PortableMatrix {
      7     schema_version: u32,
      8     no_std_target: String,
      9     no_std_cross_compiler: String,
     10     no_std_cross_cflags: String,
     11     wasm_target: String,
     12     package: Vec<PortablePackage>,
     13 }
     14 
     15 #[derive(Debug, Deserialize)]
     16 struct PortablePackage {
     17     name: String,
     18     wasm: bool,
     19 }
     20 
     21 pub fn run(workspace_root: &Path) -> Result<(), String> {
     22     let matrix = load(workspace_root)?;
     23     for package in matrix.package {
     24         check(
     25             workspace_root,
     26             &package.name,
     27             &matrix.no_std_target,
     28             Some(&matrix.no_std_cross_compiler),
     29             Some(&matrix.no_std_cross_cflags),
     30         )?;
     31         if package.wasm {
     32             check(
     33                 workspace_root,
     34                 &package.name,
     35                 &matrix.wasm_target,
     36                 None,
     37                 None,
     38             )?;
     39         }
     40     }
     41     Ok(())
     42 }
     43 
     44 fn load(workspace_root: &Path) -> Result<PortableMatrix, String> {
     45     let path = workspace_root.join("contracts/releases/portable_matrix.toml");
     46     let raw = fs::read_to_string(&path)
     47         .map_err(|error| format!("failed to read {}: {error}", path.display()))?;
     48     let mut matrix = toml::from_str::<PortableMatrix>(&raw)
     49         .map_err(|error| format!("failed to parse {}: {error}", path.display()))?;
     50     if matrix.schema_version != 1
     51         || matrix.no_std_target != "thumbv7em-none-eabihf"
     52         || matrix.no_std_cross_compiler != "zig cc"
     53         || matrix.no_std_cross_cflags != "-target thumb-freestanding-eabihf -mcpu=cortex_m4"
     54         || matrix.wasm_target != "wasm32-unknown-unknown"
     55     {
     56         return Err(
     57             "portable matrix must retain schema 1 and the governed no_std/WASM targets".to_owned(),
     58         );
     59     }
     60     matrix
     61         .package
     62         .sort_by(|left, right| left.name.cmp(&right.name));
     63     let names = matrix
     64         .package
     65         .iter()
     66         .map(|package| package.name.as_str())
     67         .collect::<Vec<_>>();
     68     let expected = [
     69         "radroots_blossom",
     70         "radroots_core",
     71         "radroots_event",
     72         "radroots_event_codec",
     73         "radroots_identity",
     74         "radroots_nostr",
     75         "radroots_protocol",
     76         "radroots_secrets",
     77         "radroots_signing",
     78         "radroots_trade",
     79         "radroots_transport",
     80     ];
     81     if names != expected || matrix.package.iter().any(|package| !package.wasm) {
     82         return Err(
     83             "portable matrix must contain exactly the 11 declared no_std and WASM packages"
     84                 .to_owned(),
     85         );
     86     }
     87     Ok(matrix)
     88 }
     89 
     90 fn check(
     91     workspace_root: &Path,
     92     package: &str,
     93     target: &str,
     94     cross_compiler: Option<&str>,
     95     cross_cflags: Option<&str>,
     96 ) -> Result<(), String> {
     97     let args = [
     98         "check",
     99         "-p",
    100         package,
    101         "--lib",
    102         "--no-default-features",
    103         "--target",
    104         target,
    105         "--locked",
    106     ];
    107     eprintln!("cargo {}", args.join(" "));
    108     let mut command = Command::new("cargo");
    109     command.args(args).current_dir(workspace_root);
    110     if let Some(cross_compiler) = cross_compiler {
    111         command.env(format!("CC_{}", target.replace('-', "_")), cross_compiler);
    112     }
    113     if let Some(cross_cflags) = cross_cflags {
    114         command.env(format!("CFLAGS_{}", target.replace('-', "_")), cross_cflags);
    115     }
    116     let status = command
    117         .status()
    118         .map_err(|error| format!("failed to start cargo: {error}"))?;
    119     if status.success() {
    120         Ok(())
    121     } else {
    122         Err(format!(
    123             "portable qualification failed for {package} on {target}"
    124         ))
    125     }
    126 }
    127 
    128 #[cfg(test)]
    129 mod tests {
    130     use super::load;
    131 
    132     #[test]
    133     fn current_contract_selects_exact_portable_public_packages() {
    134         let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
    135             .parent()
    136             .and_then(std::path::Path::parent)
    137             .expect("workspace root");
    138         let matrix = load(root).expect("portable matrix");
    139         assert_eq!(matrix.package.len(), 11);
    140         assert!(matrix.package.iter().all(|package| package.wasm));
    141     }
    142 }