Merge branch 'main' into philsippl/init_path

This commit is contained in:
Remco Bloemen 2022-04-04 12:12:34 -07:00
commit 77050626e2
5 changed files with 119 additions and 108 deletions

View File

@ -65,6 +65,10 @@ tempfile = "3.0"
tiny-keccak = "2.0.2"
tracing-test = "0.2"
[build-dependencies]
color-eyre = "0.5"
enumset = "1.0.8"
wasmer = { version = "2.0", features = [ "dylib" ] }
wasmer-engine-dylib = "2.2.1"
wasmer-compiler-cranelift = "2.2.1"

106
build.rs Normal file
View File

@ -0,0 +1,106 @@
use color_eyre::eyre::{eyre, Result};
use std::{
path::{Component, Path, PathBuf},
process::Command,
str::FromStr, env,
};
use wasmer::{Module, Store, Target, Triple};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_dylib::Dylib;
use enumset::enum_set;
const ZKEY_FILE: &str = "./semaphore/build/snark/semaphore_final.zkey";
const WASM_FILE: &str = "./semaphore/build/snark/semaphore.wasm";
// See <https://internals.rust-lang.org/t/path-to-lexical-absolute/14940>
fn absolute(path: &str) -> Result<PathBuf> {
let path = Path::new(path);
let mut absolute = if path.is_absolute() {
PathBuf::new()
} else {
std::env::current_dir()?
};
for component in path.components() {
match component {
Component::CurDir => {}
Component::ParentDir => {
absolute.pop();
}
component @ _ => absolute.push(component.as_os_str()),
}
}
Ok(absolute)
}
fn build_circuit() -> Result<()> {
println!("cargo:rerun-if-changed=./semaphore");
let run = |cmd: &[&str]| -> Result<()> {
// TODO: Use ExitCode::exit_ok() when stable.
Command::new(cmd[0])
.args(cmd[1..].iter())
.current_dir("./semaphore")
.status()?
.success()
.then(|| ())
.ok_or(eyre!("procees returned failure"))?;
Ok(())
};
// Compute absolute paths
let zkey_file = absolute(ZKEY_FILE)?;
let wasm_file = absolute(WASM_FILE)?;
// Build circuits if not exists
// TODO: This does not rebuild if the semaphore submodule is changed.
// NOTE: This requires npm / nodejs to be installed.
if !(zkey_file.exists() && wasm_file.exists()) {
run(&["npm", "install"])?;
run(&["npm", "exec", "ts-node", "./scripts/compile-circuits.ts"])?;
}
assert!(zkey_file.exists());
assert!(wasm_file.exists());
// Export generated paths
println!("cargo:rustc-env=BUILD_RS_ZKEY_FILE={}", zkey_file.display());
println!("cargo:rustc-env=BUILD_RS_WASM_FILE={}", wasm_file.display());
Ok(())
}
fn build_dylib() -> Result<()> {
let wasm_file = absolute(WASM_FILE)?;
assert!(wasm_file.exists());
let out_dir = env::var("OUT_DIR")?;
let out_dir = Path::new(&out_dir).to_path_buf();
let dylib_file = out_dir.join("semaphore.dylib");
println!("cargo:rustc-env=BUILD_DYLIB_FILE={}", dylib_file.display());
if dylib_file.exists() {
return Ok(());
}
// Create a WASM engine for the target that can compile
let triple = Triple::from_str(&env::var("TARGET")?).map_err(|e| eyre!(e))?;
let cpu_features = enum_set!();
let target = Target::new(triple, cpu_features);
let compiler_config = Cranelift::default();
let engine = Dylib::new(compiler_config)
.target(target)
.engine();
// Compile the WASM module
let store = Store::new(&engine);
let module = Module::from_file(&store, &wasm_file)?;
module.serialize_to_file(&dylib_file)?;
assert!(dylib_file.exists());
println!("cargo:warning=Circuit dylib is in {}", dylib_file.display());
Ok(())
}
fn main() -> Result<()> {
build_circuit()?;
build_dylib()?;
Ok(())
}

View File

@ -1,40 +0,0 @@
use wasmer::{Module, Store};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_dylib::Dylib;
const PATH: &str = "../semaphore/build/snark/semaphore.wasm";
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Define a compiler configuration.
//
// In this situation, the compiler is
// `wasmer_compiler_cranelift`. The compiler is responsible to
// compile the Wasm module into executable code.
let compiler_config = Cranelift::default();
println!("Creating Dylib engine...");
// Define the engine that will drive everything.
//
// In this case, the engine is `wasmer_engine_dylib` which means
// that a shared object is going to be generated.
let engine = Dylib::new(compiler_config).engine();
// Create a store, that holds the engine.
let store = Store::new(&engine);
println!("Compiling module...");
// Here we go.
//
// Let's compile the Wasm module. It is at this step that the Wasm
// text is transformed into Wasm bytes (if necessary), and then
// compiled to executable code by the compiler, which is then
// stored into a shared object by the engine.
let module = Module::from_file(&store, "../semaphore/build/snark/semaphore.wasm")?;
println!("Storing as \"{}\"", PATH);
module.serialize_to_file(PATH)?;
println!("Done! you can now compile with CIRCUIT_WASM_DYLIB=\"{}\"", PATH);
Ok(())
}

View File

@ -1,63 +0,0 @@
//! This builds the wasm file into a dylib for a given target platform.
//!
//! ```shell
//! cargo run --example dylib_ios aarch64-apple-ios semaphore/build/snark/semaphore.wasm semaphore/build/snark/semaphore.dylib
//! ```
//!
//! Ready?
use std::{str::FromStr};
use wasmer::{Module, Store, Triple, RuntimeError, CpuFeature, Target};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_dylib::Dylib;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// to build for ios: aarch64-apple-ios, aarch64-apple-ios-sim, x86_64-apple-ios
let target_os = std::env::args().nth(1).expect("no target given");
let wasm_path = std::env::args().nth(2).expect("no wasm path given");
let dylib_path = std::env::args().nth(3).expect("no dylib path given");
// Define a compiler configuration.
//
// In this situation, the compiler is
// `wasmer_compiler_cranelift`. The compiler is responsible to
// compile the Wasm module into executable code.
let compiler_config = Cranelift::default();
let triple = Triple::from_str(&target_os)
.map_err(|error| RuntimeError::new(error.to_string()))?;
// Let's build the target.
let mut cpu_feature = CpuFeature::set();
cpu_feature.insert(CpuFeature::from_str("sse2")?);
let target = Target::new(triple, cpu_feature);
println!("Chosen target: {:?}", target);
println!("Creating Dylib engine...");
// Define the engine that will drive everything.
//
// In this case, the engine is `wasmer_engine_dylib` which means
// that a shared object is going to be generated.
let engine = Dylib::new(compiler_config).target(target).engine();
// Create a store, that holds the engine.
let store = Store::new(&engine);
println!("Compiling module...");
// Here we go.
//
// Let's compile the Wasm module. It is at this step that the Wasm
// text is transformed into Wasm bytes (if necessary), and then
// compiled to executable code by the compiler, which is then
// stored into a shared object by the engine.
let module = Module::from_file(&store, &wasm_path)?;
module.serialize_to_file(&dylib_path)?;
println!("Done! you can now compile with CIRCUIT_WASM_DYLIB=\"{}\"", &dylib_path);
Ok(())
}

View File

@ -8,14 +8,14 @@ use std::{io::Cursor, sync::Mutex};
use wasmer::{Module, Store};
#[cfg(feature = "dylib")]
use std::{path::Path, env};
use std::{env, path::Path};
#[cfg(feature = "dylib")]
use wasmer::{Dylib};
use wasmer::Dylib;
const ZKEY_BYTES: &[u8] = include_bytes!("../semaphore/build/snark/semaphore_final.zkey");
const ZKEY_BYTES: &[u8] = include_bytes!(env!("BUILD_RS_ZKEY_FILE"));
#[cfg(not(feature = "dylib"))]
const WASM: &[u8] = include_bytes!("../semaphore/build/snark/semaphore.wasm");
const WASM: &[u8] = include_bytes!(env!("BUILD_RS_WASM_FILE"));
static ZKEY: Lazy<(ProvingKey<Bn254>, ConstraintMatrices<Fr>)> = Lazy::new(|| {
let mut reader = Cursor::new(ZKEY_BYTES);
@ -55,7 +55,11 @@ pub fn zkey() -> &'static (ProvingKey<Bn254>, ConstraintMatrices<Fr>) {
#[must_use]
pub fn witness_calculator() -> &'static Mutex<WitnessCalculator> {
WITNESS_CALCULATOR.get_or_init(|| {
let path = env::var("CIRCUIT_WASM_DYLIB").expect("Semaphore-rs is not initialized. The library needs to be initialized before use when build with the `cdylib` feature. You can initialize by calling `initialize` or seting the `CIRCUIT_WASM_DYLIB` environment variable.");
let path = env::var("CIRCUIT_WASM_DYLIB").expect(
"Semaphore-rs is not initialized. The library needs to be initialized before use when \
build with the `cdylib` feature. You can initialize by calling `initialize` or \
seting the `CIRCUIT_WASM_DYLIB` environment variable.",
);
from_dylib(&Path::new(&path))
})
}