commit a56654a61c257328ea4251b988cb922f593f3694
parent ddf11e6914d431f7896fedf22e4b70c7060ed185
Author: triesap <tyson@radroots.org>
Date: Mon, 3 Aug 2026 22:50:56 +0000
release: qualify front-door native targets
- mirror the governed toolchain and operating-system matrix
- check both front doors on MSRV and current stable
- cross-check Linux macOS and Windows library targets
- expose the locked qualification through the repository xtask
Diffstat:
2 files changed, 206 insertions(+), 1 deletion(-)
diff --git a/tools/sdk_xtask_import/src/main.rs b/tools/sdk_xtask_import/src/main.rs
@@ -15,6 +15,7 @@ mod package_matrix;
mod package_metadata;
mod release_qualification;
mod smoke;
+mod target_qualification;
mod ts;
mod wasm;
mod wasm_declarations;
@@ -31,6 +32,7 @@ enum CommandAction<'a> {
GeneratePackageMetadata,
Coverage(&'a [String]),
QualifyFeatures,
+ QualifyTargets,
Check,
Smoke(&'a [String]),
}
@@ -66,6 +68,7 @@ fn run(args: impl IntoIterator<Item = String>) -> Result<(), String> {
CommandAction::QualifyFeatures => {
release_qualification::run_feature_matrix(&fs::workspace_root()?)
}
+ CommandAction::QualifyTargets => target_qualification::run(&fs::workspace_root()?),
CommandAction::Check => check::check(),
CommandAction::Smoke(rest) => smoke::run(rest),
}
@@ -96,6 +99,9 @@ fn command_action(args: &[String]) -> Result<CommandAction<'_>, String> {
[command, target] if command == "release" && target == "qualify-features" => {
Ok(CommandAction::QualifyFeatures)
}
+ [command, target] if command == "release" && target == "qualify-targets" => {
+ Ok(CommandAction::QualifyTargets)
+ }
[command] if command == "check" => Ok(CommandAction::Check),
[command, rest @ ..] if command == "smoke" => Ok(CommandAction::Smoke(rest)),
[] => Err(usage()),
@@ -104,7 +110,7 @@ fn command_action(args: &[String]) -> Result<CommandAction<'_>, String> {
}
fn usage() -> String {
- "usage: cargo xtask architecture | cargo xtask architecture-ci | cargo xtask check-api-boundaries | cargo xtask check-dependency-boundaries | cargo xtask generate | cargo xtask generate ts | cargo xtask generate wasm [--package <key>] | cargo xtask generate bindings <swift|kotlin> | cargo xtask generate package-metadata | cargo xtask check | cargo xtask smoke facade-rust-local | sdk-rust-local | front-doors-rust-local | cargo xtask coverage run | cargo xtask release qualify-features"
+ "usage: cargo xtask architecture | cargo xtask architecture-ci | cargo xtask check-api-boundaries | cargo xtask check-dependency-boundaries | cargo xtask generate | cargo xtask generate ts | cargo xtask generate wasm [--package <key>] | cargo xtask generate bindings <swift|kotlin> | cargo xtask generate package-metadata | cargo xtask check | cargo xtask smoke facade-rust-local | sdk-rust-local | front-doors-rust-local | cargo xtask coverage run | cargo xtask release qualify-features | cargo xtask release qualify-targets"
.to_owned()
}
diff --git a/tools/sdk_xtask_import/src/target_qualification.rs b/tools/sdk_xtask_import/src/target_qualification.rs
@@ -0,0 +1,199 @@
+use std::{fs, path::Path, process::Command};
+
+use serde::Deserialize;
+
+#[derive(Debug, Deserialize)]
+struct TargetMatrix {
+ schema_version: u32,
+ msrv_toolchain: String,
+ current_toolchain: String,
+ operating_system: Vec<OperatingSystem>,
+}
+
+#[derive(Debug, Deserialize)]
+struct OperatingSystem {
+ name: String,
+ target: String,
+ cross_compiler: Option<String>,
+ cross_cflags: Option<String>,
+}
+
+#[derive(Debug, Deserialize)]
+struct Architecture {
+ repositories: Repositories,
+}
+
+#[derive(Debug, Deserialize)]
+struct Repositories {
+ sdk: Repository,
+}
+
+#[derive(Debug, Deserialize)]
+struct Repository {
+ packages: Vec<String>,
+}
+
+pub fn run(workspace_root: &Path) -> Result<(), String> {
+ let (matrix, packages) = load(workspace_root)?;
+ for toolchain in [&matrix.msrv_toolchain, &matrix.current_toolchain] {
+ run_command(
+ workspace_root,
+ "rustup",
+ &[
+ "run",
+ toolchain,
+ "cargo",
+ "check",
+ "--workspace",
+ "--all-targets",
+ "--locked",
+ ],
+ )?;
+ }
+ for operating_system in matrix.operating_system {
+ for package in &packages {
+ run_target_command(
+ workspace_root,
+ &operating_system,
+ &[
+ "check",
+ "-p",
+ package,
+ "--lib",
+ "--target",
+ &operating_system.target,
+ "--locked",
+ ],
+ )?;
+ }
+ }
+ Ok(())
+}
+
+fn load(workspace_root: &Path) -> Result<(TargetMatrix, Vec<String>), String> {
+ let matrix_path = workspace_root.join("contracts/releases/target_matrix.toml");
+ let matrix = toml::from_str::<TargetMatrix>(&read(&matrix_path)?)
+ .map_err(|error| format!("failed to parse {}: {error}", matrix_path.display()))?;
+ validate(&matrix)?;
+
+ let architecture_path = workspace_root.join("docs/specs/radroots_crates_release_v1.toml");
+ let architecture = toml::from_str::<Architecture>(&read(&architecture_path)?)
+ .map_err(|error| format!("failed to parse {}: {error}", architecture_path.display()))?;
+ let mut packages = architecture.repositories.sdk.packages;
+ packages.sort();
+ if packages != ["radroots", "radroots_sdk"] {
+ return Err(format!(
+ "target qualification requires exactly the two SDK front doors, found {packages:?}"
+ ));
+ }
+ Ok((matrix, packages))
+}
+
+fn read(path: &Path) -> Result<String, String> {
+ fs::read_to_string(path).map_err(|error| format!("failed to read {}: {error}", path.display()))
+}
+
+fn validate(matrix: &TargetMatrix) -> Result<(), String> {
+ if matrix.schema_version != 1 {
+ return Err(format!(
+ "target matrix schema_version must be 1, found {}",
+ matrix.schema_version
+ ));
+ }
+ if matrix.msrv_toolchain != "1.97.1" || matrix.current_toolchain != "stable" {
+ return Err("target matrix must retain MSRV 1.97.1 and current stable".to_owned());
+ }
+ let expected = [
+ (
+ "linux",
+ "x86_64-unknown-linux-gnu",
+ Some("zig cc"),
+ Some("-target x86_64-linux-gnu"),
+ ),
+ ("macos", "aarch64-apple-darwin", None, None),
+ (
+ "windows",
+ "x86_64-pc-windows-gnu",
+ Some("x86_64-w64-mingw32-gcc"),
+ None,
+ ),
+ ];
+ if matrix.operating_system.len() != expected.len()
+ || expected.iter().any(|(name, target, compiler, cflags)| {
+ !matrix.operating_system.iter().any(|entry| {
+ entry.name == *name
+ && entry.target == *target
+ && entry.cross_compiler.as_deref() == *compiler
+ && entry.cross_cflags.as_deref() == *cflags
+ })
+ })
+ {
+ return Err(
+ "target matrix must contain the exact Linux, macOS, and Windows triples".to_owned(),
+ );
+ }
+ Ok(())
+}
+
+fn run_target_command(
+ workspace_root: &Path,
+ operating_system: &OperatingSystem,
+ args: &[&str],
+) -> Result<(), String> {
+ eprintln!("cargo {}", args.join(" "));
+ let mut command = Command::new("cargo");
+ command.args(args).current_dir(workspace_root);
+ let target_key = operating_system.target.replace('-', "_");
+ if let Some(compiler) = operating_system.cross_compiler.as_deref() {
+ command.env(format!("CC_{target_key}"), compiler);
+ }
+ if let Some(cflags) = operating_system.cross_cflags.as_deref() {
+ command.env(format!("CFLAGS_{target_key}"), cflags);
+ }
+ let status = command
+ .status()
+ .map_err(|error| format!("failed to start cargo: {error}"))?;
+ if status.success() {
+ Ok(())
+ } else {
+ Err(format!(
+ "target qualification failed: cargo {}",
+ args.join(" ")
+ ))
+ }
+}
+
+fn run_command(workspace_root: &Path, program: &str, args: &[&str]) -> Result<(), String> {
+ eprintln!("{program} {}", args.join(" "));
+ let status = Command::new(program)
+ .args(args)
+ .current_dir(workspace_root)
+ .status()
+ .map_err(|error| format!("failed to start {program}: {error}"))?;
+ if status.success() {
+ Ok(())
+ } else {
+ Err(format!(
+ "target qualification failed: {program} {}",
+ args.join(" ")
+ ))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::load;
+
+ #[test]
+ fn current_contract_selects_exact_toolchains_targets_and_packages() {
+ let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
+ .parent()
+ .and_then(std::path::Path::parent)
+ .expect("workspace root");
+ let (matrix, packages) = load(root).expect("target matrix");
+ assert_eq!(matrix.msrv_toolchain, "1.97.1");
+ assert_eq!(matrix.current_toolchain, "stable");
+ assert_eq!(matrix.operating_system.len(), 3);
+ assert_eq!(packages, ["radroots", "radroots_sdk"]);
+ }
+}