Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 98 additions & 8 deletions barretenberg/rust/barretenberg-rs/build.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,108 @@
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
println!("cargo:rustc-link-lib=static=bb-external");
println!("cargo:rustc-link-lib=dylib=stdc++");
}
}

#[cfg(feature = "ffi")]
fn get_lib_dir() -> PathBuf {
// 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_LIB_DIR is set to {:?} but libbb-external.a not found there. \
Build barretenberg locally: cd barretenberg/cpp && ./bootstrap.sh",
lib_dir
);
}

// 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 development versions (0.x.x without BARRETENBERG_VERSION override)
// Real releases use the aztec-packages version (e.g., 4.0.0) set via BARRETENBERG_VERSION
if version.starts_with("0.") && std::env::var("BARRETENBERG_VERSION").is_err() {
panic!(
"Cannot download pre-built library for development version {}. \
Either set BARRETENBERG_VERSION to a released version, or \
set BB_LIB_DIR to point to a local build: cd barretenberg/cpp && ./bootstrap.sh",
version
);
}

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();
}
64 changes: 61 additions & 3 deletions barretenberg/rust/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ function build {
(cd ../ts && yarn generate)

# Build all targets
denoise "cargo build --release"
# BB_LIB_DIR tells build.rs to use local lib instead of downloading (ffi feature is on by default)
# Must use absolute path since build.rs runs from a different directory
BB_LIB_DIR="$(cd ../cpp/build/lib && pwd)" denoise "cargo build --release"

# Upload build artifacts and generated source files to cache
cache_upload barretenberg-rs-$hash.tar.gz target/release barretenberg-rs/src/generated_types.rs barretenberg-rs/src/api.rs
Expand All @@ -38,7 +40,63 @@ 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
# Must use absolute path since build.rs runs from a different directory
BB_LIB_DIR="$(cd ../cpp/build/lib && pwd)" 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"

# 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
mv "$lib_path.bak" "$lib_path"
trap - EXIT
fi
}

case "$cmd" in
Expand All @@ -58,7 +116,7 @@ case "$cmd" in
bench|bench_cmds)
# Empty handling just to make this command valid.
;;
test|test_cmds)
test|test_cmds|test_download)
$cmd
;;
*)
Expand Down
Loading