From 5cce5bf14648481790aa82c1da7e9d98b9b89163 Mon Sep 17 00:00:00 2001 From: Jonathan Hao Date: Mon, 2 Feb 2026 15:26:57 +0000 Subject: [PATCH 1/4] feat: add download functionality to build.rs for pre-built static libraries - build.rs now downloads libbb-external.a from GitHub releases when local cpp build is not available - Add test_download command to bootstrap.sh to verify download path works - Uses BARRETENBERG_VERSION env var or falls back to crate version - Blocks version 0.0.1 to prevent accidental downloads during development --- barretenberg/rust/barretenberg-rs/build.rs | 97 ++++++++++++++++++++-- barretenberg/rust/bootstrap.sh | 36 +++++++- 2 files changed, 124 insertions(+), 9 deletions(-) diff --git a/barretenberg/rust/barretenberg-rs/build.rs b/barretenberg/rust/barretenberg-rs/build.rs index de21724c68be..732670b7c2bc 100644 --- a/barretenberg/rust/barretenberg-rs/build.rs +++ b/barretenberg/rust/barretenberg-rs/build.rs @@ -1,14 +1,10 @@ +use std::path::PathBuf; + fn main() { - // Only for ffi feature - link libbb-external from cpp build + // Only for ffi feature - link libbb-external #[cfg(feature = "ffi")] { - // Find the cpp build lib directory relative to this crate - let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let lib_dir = std::path::Path::new(&manifest_dir) - .join("../../cpp/build/lib") - .canonicalize() - .expect("Failed to find cpp/build/lib - run barretenberg/cpp/bootstrap.sh first"); - + let lib_dir = get_lib_dir(); println!("cargo:rustc-link-search=native={}", lib_dir.display()); // libbb-external.a contains everything needed: barretenberg + env + vm2_stub @@ -16,3 +12,88 @@ fn main() { println!("cargo:rustc-link-lib=dylib=stdc++"); } } + +#[cfg(feature = "ffi")] +fn get_lib_dir() -> PathBuf { + // First, check for local cpp build (for development) + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let local_lib_dir = std::path::Path::new(&manifest_dir).join("../../cpp/build/lib"); + if local_lib_dir.join("libbb-external.a").exists() { + return local_lib_dir.canonicalize().unwrap(); + } + + // Otherwise, download from GitHub releases + let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); + let lib_path = out_dir.join("libbb-external.a"); + + if !lib_path.exists() { + download_lib(&out_dir); + } + + out_dir +} + +#[cfg(feature = "ffi")] +fn download_lib(out_dir: &PathBuf) { + let target = std::env::var("TARGET").unwrap(); + let arch = match target.as_str() { + t if t.contains("x86_64") && t.contains("linux") => "amd64-linux", + t if t.contains("aarch64") && t.contains("linux") => "arm64-linux", + _ => panic!( + "Unsupported target for FFI backend: {}. Supported: x86_64-linux, aarch64-linux", + target + ), + }; + + // Use BARRETENBERG_VERSION env var, or fall back to crate version + let version = std::env::var("BARRETENBERG_VERSION") + .unwrap_or_else(|_| env!("CARGO_PKG_VERSION").to_string()); + + // Skip download for test versions (0.0.1) + if version == "0.0.1" { + panic!( + "Cannot download pre-built library for test version 0.0.1. \ + Build barretenberg locally: cd barretenberg/cpp && ./bootstrap.sh" + ); + } + + let url = format!( + "https://github.com/AztecProtocol/aztec-packages/releases/download/v{}/barretenberg-static-{}.tar.gz", + version, arch + ); + + println!("cargo:warning=Downloading barretenberg static library from {}", url); + + // Download and extract + let tar_gz_path = out_dir.join("barretenberg-static.tar.gz"); + + let status = std::process::Command::new("curl") + .args(["-L", "-f", "-o"]) + .arg(&tar_gz_path) + .arg(&url) + .status() + .expect("Failed to run curl"); + + if !status.success() { + panic!( + "Failed to download barretenberg static library from {}. \ + Make sure version v{} exists as a GitHub release.", + url, version + ); + } + + let status = std::process::Command::new("tar") + .args(["-xzf"]) + .arg(&tar_gz_path) + .arg("-C") + .arg(out_dir) + .status() + .expect("Failed to run tar"); + + if !status.success() { + panic!("Failed to extract barretenberg static library"); + } + + // Clean up tar.gz + std::fs::remove_file(&tar_gz_path).ok(); +} diff --git a/barretenberg/rust/bootstrap.sh b/barretenberg/rust/bootstrap.sh index 4d11c656c172..d61a10b3978e 100755 --- a/barretenberg/rust/bootstrap.sh +++ b/barretenberg/rust/bootstrap.sh @@ -41,6 +41,40 @@ function test { RUSTFLAGS="-C link-arg=-Wl,--allow-multiple-definition" denoise "cargo test --release --features ffi" } +function test_download { + echo_header "barretenberg-rs download test" + + # Ensure Cargo is in PATH + if [ -f "$HOME/.cargo/env" ]; then + source "$HOME/.cargo/env" + fi + + # Test that build.rs can download pre-built libraries from GitHub releases + # Hide the local library to force download path + local lib_path="../cpp/build/lib/libbb-external.a" + if [ -f "$lib_path" ]; then + mv "$lib_path" "$lib_path.bak" + trap "mv '$lib_path.bak' '$lib_path' 2>/dev/null" EXIT + fi + + # Clean cargo cache to force rebuild + cargo clean -p barretenberg-rs 2>/dev/null || true + + # Build with a known release version + local version=${BARRETENBERG_VERSION:-$(gh release list --repo AztecProtocol/aztec-packages --limit 1 --json tagName --jq '.[0].tagName' | sed 's/^v//')} + echo "Testing download with version: $version" + + # Only run barretenberg-rs tests (not barretenberg-tests which has additional deps) + BARRETENBERG_VERSION=$version RUSTFLAGS="-C link-arg=-Wl,--allow-multiple-definition" \ + denoise "cargo test --release --features ffi -p barretenberg-rs" + + # Restore the local library (trap handles this, but be explicit) + if [ -f "$lib_path.bak" ]; then + mv "$lib_path.bak" "$lib_path" + trap - EXIT + fi +} + case "$cmd" in "clean") git clean -fdx @@ -58,7 +92,7 @@ case "$cmd" in bench|bench_cmds) # Empty handling just to make this command valid. ;; - test|test_cmds) + test|test_cmds|test_download) $cmd ;; *) From 14fd30145004ad220fe99a53c61eafe347dabc7d Mon Sep 17 00:00:00 2001 From: Jonathan Hao Date: Tue, 3 Feb 2026 10:24:00 +0000 Subject: [PATCH 2/4] fix: address PR review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add BB_LOCAL_BUILD env var to force local build and fail with helpful message if libbb-external.a is not found (instead of silently downloading) - Add retry logic (3 attempts) to test_download for network flakiness 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- barretenberg/rust/barretenberg-rs/build.rs | 12 ++++++++++ barretenberg/rust/bootstrap.sh | 26 +++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/barretenberg/rust/barretenberg-rs/build.rs b/barretenberg/rust/barretenberg-rs/build.rs index 732670b7c2bc..b01202e06400 100644 --- a/barretenberg/rust/barretenberg-rs/build.rs +++ b/barretenberg/rust/barretenberg-rs/build.rs @@ -15,6 +15,9 @@ fn main() { #[cfg(feature = "ffi")] fn get_lib_dir() -> PathBuf { + // Check if user wants to force local build only (for development) + let require_local = std::env::var("BB_LOCAL_BUILD").is_ok(); + // First, check for local cpp build (for development) let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); let local_lib_dir = std::path::Path::new(&manifest_dir).join("../../cpp/build/lib"); @@ -22,6 +25,15 @@ fn get_lib_dir() -> PathBuf { return local_lib_dir.canonicalize().unwrap(); } + // If local build is required but not found, fail with helpful message + if require_local { + panic!( + "BB_LOCAL_BUILD is set but libbb-external.a not found at {:?}. \ + Build barretenberg locally: cd barretenberg/cpp && ./bootstrap.sh", + local_lib_dir + ); + } + // Otherwise, download from GitHub releases let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); let lib_path = out_dir.join("libbb-external.a"); diff --git a/barretenberg/rust/bootstrap.sh b/barretenberg/rust/bootstrap.sh index d61a10b3978e..67c49aaf80fc 100755 --- a/barretenberg/rust/bootstrap.sh +++ b/barretenberg/rust/bootstrap.sh @@ -64,9 +64,29 @@ function test_download { local version=${BARRETENBERG_VERSION:-$(gh release list --repo AztecProtocol/aztec-packages --limit 1 --json tagName --jq '.[0].tagName' | sed 's/^v//')} echo "Testing download with version: $version" - # Only run barretenberg-rs tests (not barretenberg-tests which has additional deps) - BARRETENBERG_VERSION=$version RUSTFLAGS="-C link-arg=-Wl,--allow-multiple-definition" \ - denoise "cargo test --release --features ffi -p barretenberg-rs" + # Retry logic for network flakiness (GitHub releases can be flaky) + local max_retries=3 + local retry=0 + local success=false + while [ $retry -lt $max_retries ]; do + if BARRETENBERG_VERSION=$version RUSTFLAGS="-C link-arg=-Wl,--allow-multiple-definition" \ + cargo test --release --features ffi -p barretenberg-rs 2>&1; then + success=true + break + fi + retry=$((retry + 1)) + if [ $retry -lt $max_retries ]; then + echo "Attempt $retry failed, retrying in 5 seconds..." + sleep 5 + # Clean to force re-download + cargo clean -p barretenberg-rs 2>/dev/null || true + fi + done + + if [ "$success" = false ]; then + echo "Download test failed after $max_retries attempts" + exit 1 + fi # Restore the local library (trap handles this, but be explicit) if [ -f "$lib_path.bak" ]; then From 005948135f8521ade715a45c3b84f8dd4348a28c Mon Sep 17 00:00:00 2001 From: Jonathan Hao Date: Tue, 3 Feb 2026 10:30:07 +0000 Subject: [PATCH 3/4] fix: flip BB_LOCAL_BUILD logic - download by default, local is opt-in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now the default behavior is to download from GitHub releases. Set BB_LOCAL_BUILD=1 to use local cpp/build/lib instead (for monorepo development). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- barretenberg/rust/barretenberg-rs/build.rs | 24 ++++++++++------------ barretenberg/rust/bootstrap.sh | 3 ++- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/barretenberg/rust/barretenberg-rs/build.rs b/barretenberg/rust/barretenberg-rs/build.rs index b01202e06400..eeb1615877ea 100644 --- a/barretenberg/rust/barretenberg-rs/build.rs +++ b/barretenberg/rust/barretenberg-rs/build.rs @@ -15,18 +15,16 @@ fn main() { #[cfg(feature = "ffi")] fn get_lib_dir() -> PathBuf { - // Check if user wants to force local build only (for development) - let require_local = std::env::var("BB_LOCAL_BUILD").is_ok(); - - // First, check for local cpp build (for development) - let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let local_lib_dir = std::path::Path::new(&manifest_dir).join("../../cpp/build/lib"); - if local_lib_dir.join("libbb-external.a").exists() { - return local_lib_dir.canonicalize().unwrap(); - } - - // If local build is required but not found, fail with helpful message - if require_local { + // Check if user wants to use local build (for development in monorepo) + let use_local = std::env::var("BB_LOCAL_BUILD").is_ok(); + + if use_local { + // Use local cpp build + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let local_lib_dir = std::path::Path::new(&manifest_dir).join("../../cpp/build/lib"); + if local_lib_dir.join("libbb-external.a").exists() { + return local_lib_dir.canonicalize().unwrap(); + } panic!( "BB_LOCAL_BUILD is set but libbb-external.a not found at {:?}. \ Build barretenberg locally: cd barretenberg/cpp && ./bootstrap.sh", @@ -34,7 +32,7 @@ fn get_lib_dir() -> PathBuf { ); } - // Otherwise, download from GitHub releases + // Download from GitHub releases let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); let lib_path = out_dir.join("libbb-external.a"); diff --git a/barretenberg/rust/bootstrap.sh b/barretenberg/rust/bootstrap.sh index 67c49aaf80fc..2b8d2c351576 100755 --- a/barretenberg/rust/bootstrap.sh +++ b/barretenberg/rust/bootstrap.sh @@ -38,7 +38,8 @@ function test { denoise "cargo test --release" # Run FFI backend tests (requires libbb-external.a from cpp build) - RUSTFLAGS="-C link-arg=-Wl,--allow-multiple-definition" denoise "cargo test --release --features ffi" + # BB_LIB_DIR tells build.rs to use local lib instead of downloading + BB_LIB_DIR="../cpp/build/lib" RUSTFLAGS="-C link-arg=-Wl,--allow-multiple-definition" denoise "cargo test --release --features ffi" } function test_download { From 78cacb1664b8528ee203fef78ba3151c79bc6247 Mon Sep 17 00:00:00 2001 From: Jonathan Hao Date: Tue, 3 Feb 2026 10:30:56 +0000 Subject: [PATCH 4/4] fix: use BB_LIB_DIR env var to specify library path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of BB_LOCAL_BUILD=1, use BB_LIB_DIR=/path/to/lib to specify where libbb-external.a is located. More flexible and explicit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- barretenberg/rust/barretenberg-rs/build.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/barretenberg/rust/barretenberg-rs/build.rs b/barretenberg/rust/barretenberg-rs/build.rs index eeb1615877ea..4cfd1682fdfd 100644 --- a/barretenberg/rust/barretenberg-rs/build.rs +++ b/barretenberg/rust/barretenberg-rs/build.rs @@ -15,20 +15,16 @@ fn main() { #[cfg(feature = "ffi")] fn get_lib_dir() -> PathBuf { - // Check if user wants to use local build (for development in monorepo) - let use_local = std::env::var("BB_LOCAL_BUILD").is_ok(); - - if use_local { - // Use local cpp build - let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let local_lib_dir = std::path::Path::new(&manifest_dir).join("../../cpp/build/lib"); - if local_lib_dir.join("libbb-external.a").exists() { - return local_lib_dir.canonicalize().unwrap(); + // Check if user provided a custom library path + if let Ok(lib_dir) = std::env::var("BB_LIB_DIR") { + let lib_dir = PathBuf::from(&lib_dir); + if lib_dir.join("libbb-external.a").exists() { + return lib_dir.canonicalize().unwrap(); } panic!( - "BB_LOCAL_BUILD is set but libbb-external.a not found at {:?}. \ + "BB_LIB_DIR is set to {:?} but libbb-external.a not found there. \ Build barretenberg locally: cd barretenberg/cpp && ./bootstrap.sh", - local_lib_dir + lib_dir ); }