mirror of
https://github.com/logos-blockchain/logos-blockchain-circuits.git
synced 2026-06-11 02:59:53 +00:00
feat: Unify env vars into single LBC_ROOT_DIR (#38)
This commit is contained in:
parent
8eab6dce28
commit
2939c83a67
@ -1,5 +1,9 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
// Canonical definition of the env var name. Also hardcoded as a literal in
|
||||
// `lbc-common`'s `circuit_artifacts!` macro (env!() requires a literal).
|
||||
const LBC_ROOT_DIR: &str = "LBC_ROOT_DIR";
|
||||
|
||||
#[cfg(feature = "prebuilt")]
|
||||
mod prebuilt {
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -19,7 +23,7 @@ mod prebuilt {
|
||||
format!("https://github.com/{REPO}/releases/download/v{version}/{artifact_tar_gz}")
|
||||
}
|
||||
|
||||
fn fetch_library(version: &str, os: &str, arch: &str, lib_var_name: &str) -> Response<Body> {
|
||||
fn fetch_artifact(version: &str, os: &str, arch: &str) -> Response<Body> {
|
||||
let url = build_artifact_url(version, os, arch);
|
||||
// We skip checksum verification intentionally.
|
||||
// Hardcoded hashes would protect against a silently replaced release asset but
|
||||
@ -27,15 +31,15 @@ mod prebuilt {
|
||||
// overkill for a first-party library.
|
||||
ureq::get(&url).call().unwrap_or_else(|error| {
|
||||
panic!(
|
||||
"Failed to download a prebuilt library for {os}-{arch} v{version}: {error}. \
|
||||
Set {lib_var_name} to point to a local build instead."
|
||||
"Failed to download a prebuilt artifact for {os}-{arch} v{version}: {error}. \
|
||||
Set {ENV_VAR} to point to a local build instead.",
|
||||
ENV_VAR = super::LBC_ROOT_DIR
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn unpack_library(
|
||||
fn unpack_artifact(
|
||||
response: Response<Body>,
|
||||
circuit_name: &str,
|
||||
version: &str,
|
||||
os: &str,
|
||||
arch: &str,
|
||||
@ -47,16 +51,15 @@ mod prebuilt {
|
||||
.unpack(output_dir)
|
||||
.expect("Failed to unpack the downloaded archive.");
|
||||
|
||||
let unpacked_artifact_path = output_dir.join(build_artifact_name(version, os, arch));
|
||||
let unpacked_library_directory = unpacked_artifact_path.join(circuit_name);
|
||||
let artifact_root = output_dir.join(build_artifact_name(version, os, arch));
|
||||
|
||||
assert!(
|
||||
unpacked_library_directory.is_dir(),
|
||||
"Failed to find the unpacked library at {}",
|
||||
unpacked_library_directory.display()
|
||||
artifact_root.is_dir(),
|
||||
"Failed to find the unpacked artifact directory at {}.",
|
||||
artifact_root.display()
|
||||
);
|
||||
|
||||
unpacked_library_directory
|
||||
artifact_root
|
||||
}
|
||||
|
||||
/// Produce a lockfile for the given directory
|
||||
@ -77,114 +80,95 @@ mod prebuilt {
|
||||
.join("blockchain")
|
||||
}
|
||||
|
||||
pub fn provision_library(circuit_name: &str, lib_var_name: &str) -> PathBuf {
|
||||
pub fn provision_artifact() -> PathBuf {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||
let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
|
||||
let cache = get_cache_dir();
|
||||
// The tarball unpacks to a top-level `{artifact_name}/` dir, so the circuit
|
||||
// lives at `cache/{artifact_name}/{circuit_name}/`.
|
||||
let circuit_dir = cache
|
||||
.join(build_artifact_name(version, &os, &arch))
|
||||
.join(circuit_name);
|
||||
let artifact_root = cache.join(build_artifact_name(version, &os, &arch));
|
||||
|
||||
std::fs::create_dir_all(&cache).expect("Failed to create the cache directory.");
|
||||
|
||||
// Since the circuits' libraries are all contained in the same single artifact,
|
||||
// each crate will try to download the same circuits.
|
||||
// each crate will try to download the same artifact.
|
||||
// To avoid redundant downloads, we use a lock to ensure that only one process
|
||||
// fetches the circuits while the others wait for it to complete and
|
||||
// fetches the artifact while the others wait for it to complete and
|
||||
// then re-check the cache.
|
||||
let mut lock = get_lockfile(&cache);
|
||||
let _guard = lock.write().expect("Failed to acquire cache lock.");
|
||||
|
||||
if circuit_dir.is_dir() {
|
||||
if artifact_root.is_dir() {
|
||||
println!(
|
||||
"Found a cached {circuit_name} library at {}, reusing.",
|
||||
circuit_dir.display()
|
||||
"Found a cached artifact at {}, reusing.",
|
||||
artifact_root.display()
|
||||
);
|
||||
return circuit_dir;
|
||||
return artifact_root;
|
||||
}
|
||||
|
||||
println!(
|
||||
"No cached download found, downloading {circuit_name} v{version} for {os}-{arch}..."
|
||||
);
|
||||
let response = fetch_library(version, &os, &arch, lib_var_name);
|
||||
println!("No cached download found, downloading v{version} for {os}-{arch}...");
|
||||
let response = fetch_artifact(version, &os, &arch);
|
||||
println!("Download complete, unpacking...");
|
||||
let lib_dir = unpack_library(response, circuit_name, version, &os, &arch, &cache);
|
||||
println!("Ready, {circuit_name} library at {}.", lib_dir.display());
|
||||
lib_dir
|
||||
let root = unpack_artifact(response, version, &os, &arch, &cache);
|
||||
println!("Ready, artifact at {}.", root.display());
|
||||
root
|
||||
}
|
||||
}
|
||||
|
||||
mod env_vars {
|
||||
pub const BUNDLE_LIB_DIR: &str = "LBC_LIB_DIR";
|
||||
}
|
||||
|
||||
pub fn build(circuit_name: &str, circuit_lib_dir_var: &str) {
|
||||
println!("cargo:rerun-if-env-changed={circuit_lib_dir_var}");
|
||||
println!("cargo:rerun-if-env-changed={}", env_vars::BUNDLE_LIB_DIR);
|
||||
pub fn build(circuit_name: &str) {
|
||||
println!("cargo:rerun-if-env-changed={LBC_ROOT_DIR}");
|
||||
println!("cargo:rerun-if-env-changed=CARGO_PKG_VERSION");
|
||||
println!("cargo:rerun-if-changed=Cargo.toml");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
let circuit_lib_dir = std::env::var(circuit_lib_dir_var).map_or_else(
|
||||
let lbc_root_dir = std::env::var(LBC_ROOT_DIR).map_or_else(
|
||||
|_| {
|
||||
#[cfg(not(feature = "prebuilt"))]
|
||||
panic!(
|
||||
"{circuit_lib_dir_var} is not set. Either:\n\
|
||||
- Set {circuit_lib_dir_var} to point at a local build, or\n\
|
||||
"{LBC_ROOT_DIR} is not set. Either:\n\
|
||||
- Set {LBC_ROOT_DIR} to point at a local build, or\n\
|
||||
- Enable the `prebuilt` feature to download from GitHub Releases."
|
||||
);
|
||||
|
||||
#[cfg(feature = "prebuilt")]
|
||||
{
|
||||
println!("Environment variable '{circuit_lib_dir_var}' is not set, falling back to prebuilt download");
|
||||
prebuilt::provision_library(circuit_name, circuit_lib_dir_var)
|
||||
println!(
|
||||
"Environment variable '{LBC_ROOT_DIR}' is not set, falling back to prebuilt download"
|
||||
);
|
||||
prebuilt::provision_artifact()
|
||||
}
|
||||
},
|
||||
|lib_dir| {
|
||||
println!("Environment variable '{circuit_lib_dir_var}' set, using local library at '{lib_dir}'");
|
||||
let lib_dir_path = PathBuf::from(lib_dir);
|
||||
|dir| {
|
||||
println!("Environment variable '{LBC_ROOT_DIR}' set, using local artifact at '{dir}'");
|
||||
let dir_path = PathBuf::from(dir);
|
||||
assert!(
|
||||
lib_dir_path.is_dir(),
|
||||
"The library directory specified in '{circuit_lib_dir_var}' at {} does not exist.",
|
||||
lib_dir_path.display()
|
||||
dir_path.is_dir(),
|
||||
"The root directory specified in '{LBC_ROOT_DIR}' at {} does not exist.",
|
||||
dir_path.display()
|
||||
);
|
||||
lib_dir_path
|
||||
dir_path
|
||||
},
|
||||
);
|
||||
|
||||
let circuit_lib_dir_str = circuit_lib_dir
|
||||
let lbc_root_dir_str = lbc_root_dir
|
||||
.to_str()
|
||||
.expect("Failed to convert the library directory path to a string");
|
||||
.expect("Failed to convert the root directory path to a string");
|
||||
|
||||
let bundle_lib_dir = std::env::var(env_vars::BUNDLE_LIB_DIR).map_or_else(
|
||||
|_| {
|
||||
let default = circuit_lib_dir
|
||||
.parent()
|
||||
.expect("Failed to determine the circuit library directory's parent.")
|
||||
.join("lib");
|
||||
println!(
|
||||
"Environment variable '{}' is not set, falling back to sibling 'lib/' at '{}'.",
|
||||
env_vars::BUNDLE_LIB_DIR,
|
||||
default.display()
|
||||
);
|
||||
default
|
||||
},
|
||||
PathBuf::from,
|
||||
);
|
||||
|
||||
let bundle_lib_dir_str = bundle_lib_dir
|
||||
let circuit_dir = lbc_root_dir.join(circuit_name);
|
||||
let circuit_dir_str = circuit_dir
|
||||
.to_str()
|
||||
.expect("Failed to convert the bundle library directory path to a string");
|
||||
.expect("Failed to convert the circuit directory path to a string");
|
||||
|
||||
println!("cargo:rerun-if-changed={circuit_lib_dir_str}");
|
||||
println!("cargo:rerun-if-changed={bundle_lib_dir_str}");
|
||||
println!("cargo:rustc-env={circuit_lib_dir_var}={circuit_lib_dir_str}"); // Ensure it's always defined for downstream crates.
|
||||
println!("cargo:rustc-link-search=native={circuit_lib_dir_str}");
|
||||
println!("cargo:rustc-link-search=native={bundle_lib_dir_str}");
|
||||
let lib_dir = lbc_root_dir.join("lib");
|
||||
let lib_dir_str = lib_dir
|
||||
.to_str()
|
||||
.expect("Failed to convert the lib directory path to a string");
|
||||
|
||||
println!("cargo:rerun-if-changed={circuit_dir_str}");
|
||||
println!("cargo:rerun-if-changed={lib_dir_str}");
|
||||
println!("cargo:rustc-env={LBC_ROOT_DIR}={lbc_root_dir_str}");
|
||||
println!("cargo:rustc-link-search=native={circuit_dir_str}");
|
||||
println!("cargo:rustc-link-search=native={lib_dir_str}");
|
||||
println!("cargo:rustc-link-lib=static={circuit_name}");
|
||||
let cpp_lib = std::env::var("CARGO_CFG_TARGET_OS").map_or_else(
|
||||
|_| "stdc++",
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
/// Generates a `pub mod artifacts` containing the circuit compilation
|
||||
/// artifacts.
|
||||
///
|
||||
/// The artifacts are loaded from the directory pointed to by
|
||||
/// `LBC_{CIRCUIT}_LIB_DIR`, set by the crate's build script.
|
||||
/// The artifacts are loaded from `LBC_ROOT_DIR/{circuit_dir}/`, set by the
|
||||
/// crate's build script.
|
||||
///
|
||||
/// # Generated items
|
||||
///
|
||||
@ -18,15 +18,17 @@
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// lbc_common::circuit_artifacts!("POQ"); // uses LBC_POQ_LIB_DIR
|
||||
/// lbc_common::circuit_artifacts!("poq"); // uses {LBC_ROOT_DIR}/poq/
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! circuit_artifacts {
|
||||
($circuit_stem:literal) => {
|
||||
($circuit_dir:literal) => {
|
||||
pub mod artifacts {
|
||||
macro_rules! __circuit_file {
|
||||
($file:literal) => {
|
||||
concat!(env!(concat!("LBC_", $circuit_stem, "_LIB_DIR")), "/", $file)
|
||||
// "LBC_ROOT_DIR" must stay in sync with the constant in `lbc-build`.
|
||||
// env!() requires a literal so the name cannot be shared.
|
||||
concat!(env!("LBC_ROOT_DIR"), "/", $circuit_dir, "/", $file)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
fn main() {
|
||||
lbc_build::build("poc", "LBC_POC_LIB_DIR");
|
||||
lbc_build::build("poc");
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ use lbc_types::{
|
||||
|
||||
use crate::ffi::{poc_generate_witness, poc_generate_witness_from_files};
|
||||
|
||||
lbc_common::circuit_artifacts!("POC");
|
||||
lbc_common::circuit_artifacts!("poc");
|
||||
|
||||
pub struct PocDat;
|
||||
impl<'dat> lbc_types::CircuitDat<'dat> for PocDat {
|
||||
@ -48,14 +48,8 @@ mod tests {
|
||||
|
||||
use super::{PocWitnessInput, generate_witness, generate_witness_from_files};
|
||||
|
||||
static LIB_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
|
||||
const ENV_VAR: &str = "LBC_POC_LIB_DIR";
|
||||
PathBuf::from(
|
||||
std::env::var(ENV_VAR).unwrap_or_else(
|
||||
|_| panic!("Environment variable '{ENV_VAR}' must be available, as provided by the build script."),
|
||||
)
|
||||
)
|
||||
});
|
||||
static LIB_DIR: LazyLock<PathBuf> =
|
||||
LazyLock::new(|| PathBuf::from(env!("LBC_ROOT_DIR")).join("poc"));
|
||||
static INPUTS: LazyLock<PathBuf> =
|
||||
LazyLock::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("sample.input.json"));
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
fn main() {
|
||||
lbc_build::build("pol", "LBC_POL_LIB_DIR");
|
||||
lbc_build::build("pol");
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ use lbc_types::{
|
||||
|
||||
use crate::ffi::{pol_generate_witness, pol_generate_witness_from_files};
|
||||
|
||||
lbc_common::circuit_artifacts!("POL");
|
||||
lbc_common::circuit_artifacts!("pol");
|
||||
|
||||
pub struct PolDat;
|
||||
impl<'dat> lbc_types::CircuitDat<'dat> for PolDat {
|
||||
@ -48,14 +48,8 @@ mod tests {
|
||||
|
||||
use super::{PolWitnessInput, generate_witness, generate_witness_from_files};
|
||||
|
||||
static LIB_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
|
||||
const ENV_VAR: &str = "LBC_POL_LIB_DIR";
|
||||
PathBuf::from(
|
||||
std::env::var(ENV_VAR).unwrap_or_else(
|
||||
|_| panic!("Environment variable '{ENV_VAR}' must be available, as provided by the build script."),
|
||||
)
|
||||
)
|
||||
});
|
||||
static LIB_DIR: LazyLock<PathBuf> =
|
||||
LazyLock::new(|| PathBuf::from(env!("LBC_ROOT_DIR")).join("pol"));
|
||||
static INPUTS: LazyLock<PathBuf> =
|
||||
LazyLock::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("sample.input.json"));
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
fn main() {
|
||||
lbc_build::build("poq", "LBC_POQ_LIB_DIR");
|
||||
lbc_build::build("poq");
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ use lbc_types::{
|
||||
|
||||
use crate::ffi::{poq_generate_witness, poq_generate_witness_from_files};
|
||||
|
||||
lbc_common::circuit_artifacts!("POQ");
|
||||
lbc_common::circuit_artifacts!("poq");
|
||||
|
||||
pub struct PoqDat;
|
||||
impl<'dat> lbc_types::CircuitDat<'dat> for PoqDat {
|
||||
@ -48,14 +48,8 @@ mod tests {
|
||||
|
||||
use super::{PoqWitnessInput, generate_witness, generate_witness_from_files};
|
||||
|
||||
static LIB_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
|
||||
const ENV_VAR: &str = "LBC_POQ_LIB_DIR";
|
||||
PathBuf::from(
|
||||
std::env::var(ENV_VAR).unwrap_or_else(
|
||||
|_| panic!("Environment variable '{ENV_VAR}' must be available, as provided by the build script."),
|
||||
)
|
||||
)
|
||||
});
|
||||
static LIB_DIR: LazyLock<PathBuf> =
|
||||
LazyLock::new(|| PathBuf::from(env!("LBC_ROOT_DIR")).join("poq"));
|
||||
static INPUTS: LazyLock<PathBuf> =
|
||||
LazyLock::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("sample.input.json"));
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
fn main() {
|
||||
lbc_build::build("signature", "LBC_SIGNATURE_LIB_DIR");
|
||||
lbc_build::build("signature");
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ use lbc_types::{
|
||||
|
||||
use crate::ffi::{signature_generate_witness, signature_generate_witness_from_files};
|
||||
|
||||
lbc_common::circuit_artifacts!("SIGNATURE");
|
||||
lbc_common::circuit_artifacts!("signature");
|
||||
|
||||
pub struct SignatureDat;
|
||||
impl<'dat> lbc_types::CircuitDat<'dat> for SignatureDat {
|
||||
@ -51,14 +51,8 @@ mod tests {
|
||||
|
||||
use super::{SignatureWitnessInput, generate_witness, generate_witness_from_files};
|
||||
|
||||
static LIB_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
|
||||
const ENV_VAR: &str = "LBC_SIGNATURE_LIB_DIR";
|
||||
PathBuf::from(
|
||||
std::env::var(ENV_VAR).unwrap_or_else(
|
||||
|_| panic!("Environment variable '{ENV_VAR}' must be available, as provided by the build script."),
|
||||
)
|
||||
)
|
||||
});
|
||||
static LIB_DIR: LazyLock<PathBuf> =
|
||||
LazyLock::new(|| PathBuf::from(env!("LBC_ROOT_DIR")).join("signature"));
|
||||
static INPUTS: LazyLock<PathBuf> =
|
||||
LazyLock::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("sample.input.json"));
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user