Windows bindings for rust (#259)

This commit is contained in:
Divma 2023-04-05 13:33:37 -05:00 committed by GitHub
parent 47ddabde63
commit b30983fc9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 92 additions and 80 deletions

View File

@ -9,7 +9,13 @@ on:
jobs:
tests:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
- windows-latest
- macos-latest
steps:
- uses: actions/checkout@v3
with:

View File

@ -42,7 +42,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
"syn 2.0.8",
"syn 2.0.13",
"which",
]
@ -74,6 +74,7 @@ version = "0.1.0"
dependencies = [
"bindgen",
"blst",
"cc",
"criterion",
"glob",
"hex",
@ -139,9 +140,9 @@ dependencies = [
[[package]]
name = "clang-sys"
version = "1.6.0"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a"
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
dependencies = [
"glob",
"libc",
@ -309,9 +310,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "indexmap"
version = "1.9.2"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
@ -355,9 +356,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.140"
version = "0.2.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
[[package]]
name = "libloading"
@ -488,9 +489,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.53"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
@ -558,9 +559,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.7.2"
version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c"
checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
dependencies = [
"regex-syntax",
]
@ -600,29 +601,29 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.158"
version = "1.0.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.158"
version = "1.0.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.13",
]
[[package]]
name = "serde_json"
version = "1.0.94"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744"
dependencies = [
"itoa",
"ryu",
@ -661,9 +662,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.8"
version = "2.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
dependencies = [
"proc-macro2",
"quote",
@ -846,5 +847,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.13",
]

View File

@ -2,6 +2,7 @@
name = "c-kzg"
version = "0.1.0"
edition = "2021"
links = "ckzg"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -24,6 +25,7 @@ serde_yaml = "0.9.17"
[build-dependencies]
bindgen = { git = "https://github.com/rust-lang/rust-bindgen" , rev = "0de11f0a521611ac8738b7b01d19dddaf3899e66" }
cc = "1.0"
[[bench]]
name = "kzg_benches"

View File

@ -1,18 +1,9 @@
use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::path::PathBuf;
const MAINNET_FIELD_ELEMENTS_PER_BLOB: usize = 4096;
const MINIMAL_FIELD_ELEMENTS_PER_BLOB: usize = 4;
fn move_file(src: &Path, dst: &Path) -> Result<(), String> {
std::fs::copy(src, dst)
.map_err(|_| format!("Failed to copy {} to {}", src.display(), dst.display()))?;
std::fs::remove_file(src)
.map_err(|_| format!("Failed to remove file {} from source", src.display()))?;
Ok(())
}
fn main() {
let cargo_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let root_dir = cargo_dir
@ -20,7 +11,6 @@ fn main() {
.expect("rust dir is nested")
.parent()
.expect("bindings dir is nested");
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let field_elements_per_blob = if cfg!(feature = "minimal-spec") {
MINIMAL_FIELD_ELEMENTS_PER_BLOB
@ -30,38 +20,24 @@ fn main() {
eprintln!("Using FIELD_ELEMENTS_PER_BLOB={}", field_elements_per_blob);
// Deleting any existing assembly and object files to ensure that compiling with a different
// feature flag changes the final linked library file.
let obj_file = root_dir.join("src").join("c_kzg_4844.o");
if obj_file.exists() {
std::fs::remove_file(obj_file).unwrap();
}
// Obtain the header files exposed by blst-bindings' crate.
let blst_headers_dir =
std::env::var_os("DEP_BLST_BINDINGS").expect("BLST exposes header files for bindings");
// Ensure libckzg exists in `OUT_DIR`
Command::new("make")
.current_dir(root_dir.join("src"))
.arg("c_kzg_4844.o")
.arg(format!(
"FIELD_ELEMENTS_PER_BLOB={}",
field_elements_per_blob
))
.status()
.unwrap();
let c_src_dir = root_dir.join("src");
Command::new("ar")
.current_dir(&root_dir.join("src"))
.args(["crus", "libckzg.a", "c_kzg_4844.o"])
.status()
.unwrap();
move_file(
root_dir.join("src").join("libckzg.a").as_path(),
out_dir.join("libckzg.a").as_path(),
)
.unwrap();
let mut cc = cc::Build::new();
#[cfg(windows)]
cc.compiler("clang").flag("-D_CRT_SECURE_NO_WARNINGS");
cc.include(blst_headers_dir.clone());
cc.warnings(false);
cc.flag(format!("-DFIELD_ELEMENTS_PER_BLOB={}", field_elements_per_blob).as_str());
cc.file(c_src_dir.join("c_kzg_4844.c"));
cc.try_compile("ckzg").expect("Failed to compile ckzg");
println!("cargo:rustc-link-search={}", out_dir.display());
println!("cargo:rustc-link-search={}", out_dir.display());
println!("cargo:rustc-link-lib=static=ckzg");
// Tell cargo to search for the static blst exposed by the blst-bindings' crate.
println!("cargo:rustc-link-lib=static=blst");
@ -71,12 +47,9 @@ fn main() {
"bindings_{build_target}_{field_elements_per_blob}.rs"
));
let header_file_path = root_dir.join("src").join("c_kzg_4844.h");
let header_file_path = c_src_dir.join("c_kzg_4844.h");
let header_file = header_file_path.to_str().expect("valid header file");
// Obtain the header files exposed by blst-bindings' crate.
let blst_headers_dir =
std::env::var_os("DEP_BLST_BINDINGS").expect("BLST exposes header files for bindings");
make_bindings(
field_elements_per_blob,
header_file,
@ -85,11 +58,8 @@ fn main() {
snapshot_path,
);
// Cleanup
let obj_file = root_dir.join("src").join("c_kzg_4844.o");
if obj_file.exists() {
std::fs::remove_file(obj_file).unwrap();
}
// Finally, tell cargo this provides ckzg
println!("cargo:rustc-link-lib=ckzg");
}
fn make_bindings<P>(

View File

@ -6,10 +6,8 @@ mod test_formats;
include!("generated.rs");
use libc::fopen;
use std::ffi::CString;
use std::mem::MaybeUninit;
use std::os::unix::prelude::OsStrExt;
use std::path::PathBuf;
pub const BYTES_PER_G1_POINT: usize = 48;
@ -102,12 +100,41 @@ impl KZGSettings {
/// FIELD_ELEMENT_PER_BLOB g1 byte values
/// 65 g2 byte values
pub fn load_trusted_setup_file(file_path: PathBuf) -> Result<Self, Error> {
let file_path = CString::new(file_path.as_os_str().as_bytes()).map_err(|e| {
Error::InvalidTrustedSetup(format!("Invalid trusted setup file: {:?}", e))
})?;
// SAFETY: vec![b'r'] has no 0 bytes.
let mode = unsafe { CString::from_vec_unchecked(vec![b'r']) };
#[cfg(unix)]
let file_path_bytes = {
use std::os::unix::prelude::OsStrExt;
file_path.as_os_str().as_bytes()
};
#[cfg(windows)]
let file_path_bytes = {
file_path
.as_os_str()
.to_str()
.ok_or(Error::InvalidTrustedSetup(format!(
"Unsuported non unicode file path"
)))?
.as_bytes()
};
let file_path = CString::new(file_path_bytes)
.map_err(|e| Error::InvalidTrustedSetup(format!("Invalid trusted setup file: {e}")))?;
// SAFETY:
// - .as_ptr(): pointer is not dangling because file_path has not been dropped.
// Usage or ptr: File will not be written to it by the c code.
let file_ptr = unsafe { libc::fopen(file_path.as_ptr(), mode.as_ptr()) };
if file_ptr.is_null() {
let e = std::io::Error::last_os_error();
return Err(Error::InvalidTrustedSetup(format!(
"Failed to open trusted setup file {e}"
)));
}
let mut kzg_settings = MaybeUninit::<KZGSettings>::uninit();
unsafe {
let file_ptr = fopen(file_path.as_ptr(), &('r' as libc::c_char));
let result = unsafe {
let res = load_trusted_setup_file(kzg_settings.as_mut_ptr(), file_ptr);
if let C_KZG_RET::C_KZG_OK = res {
Ok(kzg_settings.assume_init())
@ -117,7 +144,13 @@ impl KZGSettings {
res
)))
}
}
};
// We don't really care if this succeeds.
let _uncheched_close_result = unsafe { libc::fclose(file_ptr) };
drop(file_path);
result
}
}

View File

@ -8,7 +8,7 @@ pub use bindings::{
// Expose the constants.
pub use bindings::{
BYTES_PER_BLOB, BYTES_PER_COMMITMENT, BYTES_PER_FIELD_ELEMENT, BYTES_PER_PROOF,
FIELD_ELEMENTS_PER_BLOB,
FIELD_ELEMENTS_PER_BLOB, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT
};
// Expose the remaining relevant types.
pub use bindings::{Blob, Bytes32, Bytes48, Error, FFTSettings};