From 7860353117221dc0268c658e1a690b17319f95a8 Mon Sep 17 00:00:00 2001 From: Anand Krishnamoorthi Date: Thu, 16 Apr 2026 17:16:28 -0500 Subject: [PATCH] feat(xtask): add missing flags for CI-friendly Python and FFI builds Pass --frozen through to maturin so that build-python works in network-isolated containers (e.g. OneBranch CFS). Previously the flag only reached the preliminary cargo build but not maturin itself, causing cargo metadata to fail when it tried to fetch the index. Also add --out and --strip to build-python so the pipeline can place wheels in a flat output directory and strip debug symbols without calling maturin directly. Add --frozen to test-python (propagated to maturin develop) and build-ffi (propagated to cargo build) for parity with test-ffi which already supported it. --- .github/workflows/test-python.yml | 2 +- xtask/src/tasks/bindings/all.rs | 5 +++- xtask/src/tasks/bindings/csharp.rs | 2 +- xtask/src/tasks/bindings/ffi.rs | 15 ++++++++--- xtask/src/tasks/bindings/python.rs | 43 ++++++++++++++++++++++++++---- 5 files changed, 55 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 1f01a4e0..834f90dc 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -37,7 +37,7 @@ jobs: run: cargo fetch --locked - name: Fetch Python crate dependencies - run: cargo fetch --locked --manifest-path bindings/python/Cargo.toml --target ${{ matrix.host.target }} + run: cargo fetch --locked --manifest-path bindings/python/Cargo.toml - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: diff --git a/xtask/src/tasks/bindings/all.rs b/xtask/src/tasks/bindings/all.rs index 3a1010dd..397c2a89 100644 --- a/xtask/src/tasks/bindings/all.rs +++ b/xtask/src/tasks/bindings/all.rs @@ -27,7 +27,7 @@ impl BuildAllBindingsCommand { let release = self.release; let targets = ffi::resolve_targets(Vec::new())?; - ffi::build_targets(&workspace, &targets, release)?; + ffi::build_targets(&workspace, &targets, release, false)?; let ffi_dir = workspace.join("bindings/ffi/target"); let nuget_result = build_nuget_package(&BuildNugetConfig { @@ -53,7 +53,9 @@ impl BuildAllBindingsCommand { release, target: None, target_dir: None, + out: None, frozen: false, + strip: false, } .run()?; BuildWasmCommand { @@ -114,6 +116,7 @@ impl TestAllBindingsCommand { release: self.release, target: None, python: self.python.clone(), + frozen: false, } .run()?; diff --git a/xtask/src/tasks/bindings/csharp.rs b/xtask/src/tasks/bindings/csharp.rs index a0d31ad0..c216b7f9 100644 --- a/xtask/src/tasks/bindings/csharp.rs +++ b/xtask/src/tasks/bindings/csharp.rs @@ -77,7 +77,7 @@ pub fn build_nuget_package(config: &BuildNugetConfig) -> Result) -> Result> { } /// Compiles the FFI crate for the supplied target triples. -pub fn build_targets(root: &Path, targets: &[String], release: bool) -> Result<()> { +pub fn build_targets(root: &Path, targets: &[String], release: bool, frozen: bool) -> Result<()> { for target in targets { - cargo_build(root, target, release)?; + cargo_build(root, target, release, frozen)?; } Ok(()) } @@ -101,7 +105,7 @@ pub fn detect_host_triple() -> Result { Err(anyhow!("failed to detect host target triple")) } -fn cargo_build(root: &Path, target: &str, release: bool) -> Result<()> { +fn cargo_build(root: &Path, target: &str, release: bool, frozen: bool) -> Result<()> { let dir = root.join("bindings/ffi"); let mut args = vec![ OsString::from("build"), @@ -112,6 +116,9 @@ fn cargo_build(root: &Path, target: &str, release: bool) -> Result<()> { if release { args.push(OsString::from("--release")); } + if frozen { + args.push(OsString::from("--frozen")); + } let title = format!("cargo build (ffi:{target})"); run_cargo_step(&dir, &title, args) diff --git a/xtask/src/tasks/bindings/python.rs b/xtask/src/tasks/bindings/python.rs index 59eb2431..b498ded0 100644 --- a/xtask/src/tasks/bindings/python.rs +++ b/xtask/src/tasks/bindings/python.rs @@ -24,12 +24,20 @@ pub struct BuildPythonCommand { pub target: Option, /// Override the directory that receives built wheel files. - #[arg(long, value_name = "PATH")] + #[arg(long, value_name = "PATH", conflicts_with = "out")] pub target_dir: Option, - /// Propagate --frozen to cargo invocations prior to packaging. + /// Place built wheel files directly into this directory. + #[arg(long, value_name = "PATH", conflicts_with = "target_dir")] + pub out: Option, + + /// Propagate --frozen to cargo and maturin invocations. #[arg(long)] pub frozen: bool, + + /// Strip debug symbols from the built wheel. + #[arg(long)] + pub strip: bool, } impl BuildPythonCommand { @@ -65,8 +73,19 @@ impl BuildPythonCommand { maturin.arg("--target"); maturin.arg(target); } - maturin.arg("--target-dir"); - maturin.arg(&wheel_dir); + if self.frozen { + maturin.arg("--frozen"); + } + if self.strip { + maturin.arg("--strip"); + } + if let Some(out) = &self.out { + maturin.arg("--out"); + maturin.arg(out); + } else { + maturin.arg("--target-dir"); + maturin.arg(&wheel_dir); + } run_command(maturin, "maturin build (bindings/python)") } } @@ -84,6 +103,10 @@ pub struct TestPythonCommand { /// Python interpreter used to run the sample and tests. #[arg(long, value_name = "EXE", default_value = "python3")] pub python: String, + + /// Pass --frozen to all cargo and maturin invocations. + #[arg(long)] + pub frozen: bool, } impl TestPythonCommand { @@ -95,7 +118,13 @@ impl TestPythonCommand { install_testing_dependencies(&venv_python)?; - install_local_package(&python_dir, self.release, self.target.as_deref(), &venv_dir)?; + install_local_package( + &python_dir, + self.release, + self.target.as_deref(), + self.frozen, + &venv_dir, + )?; let mut sample = Command::new(&venv_python); sample.current_dir(&python_dir); @@ -133,6 +162,7 @@ fn install_local_package( python_dir: &Path, release: bool, target: Option<&str>, + frozen: bool, venv_dir: &Path, ) -> Result<()> { let mut maturin = Command::new("maturin"); @@ -145,6 +175,9 @@ fn install_local_package( maturin.arg("--target"); maturin.arg(target); } + if frozen { + maturin.arg("--frozen"); + } maturin.env("VIRTUAL_ENV", venv_dir); let bin_dir = venv_bin_dir(venv_dir); let mut path_value = bin_dir.clone().into_os_string();