Skip to content

Commit fd24cf8

Browse files
[Rust] Remove blst to avoid double link issues, expose blst features (#287)
1 parent 8f43b2e commit fd24cf8

File tree

3 files changed

+138
-45
lines changed

3 files changed

+138
-45
lines changed

bindings/rust/Cargo.lock

Lines changed: 0 additions & 40 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindings/rust/Cargo.toml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,30 @@ links = "ckzg"
77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[features]
10+
11+
# BLST Compilation:
12+
# By default, compile with ADX extension if the host supports it. Binary can be
13+
# executed on systems similar to the host.
1014
default = ["mainnet-spec"]
1115
mainnet-spec = []
1216
minimal-spec = []
17+
# BLST Compilation:
18+
# Compile in portable mode, without ISA extensions.
19+
# Binary can be executed on all systems.
20+
portable = []
21+
# BLST Compilation:
22+
# Enable ADX even if the host CPU doesn't support it.
23+
# Binary can be executed on Broadwell+ and Ryzen+ systems.
24+
force-adx = []
25+
# BLST Compilation:
26+
# Suppress multi-threading.
27+
# Engaged on wasm32 target architecture automatically.
28+
no-threads = []
1329

1430
[dependencies]
1531
hex = "0.4.2"
1632
libc = "0.2"
1733
serde = { version = "1.0", features = ["derive"] }
18-
blst = { path = "../../blst/bindings/rust" }
1934

2035
[dev-dependencies]
2136
criterion = "0.4"
@@ -27,6 +42,9 @@ serde_yaml = "0.9.17"
2742
bindgen = { git = "https://github.com/rust-lang/rust-bindgen" , rev = "0de11f0a521611ac8738b7b01d19dddaf3899e66" }
2843
cc = "1.0"
2944

45+
[target.'cfg(target_env = "msvc")'.build-dependencies]
46+
glob = "0.3"
47+
3048
[[bench]]
3149
name = "kzg_benches"
3250
harness = false

bindings/rust/build.rs

Lines changed: 119 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,122 @@
11
use std::env;
2-
use std::path::PathBuf;
2+
use std::path::{Path, PathBuf};
33

44
const MAINNET_FIELD_ELEMENTS_PER_BLOB: usize = 4096;
55
const MINIMAL_FIELD_ELEMENTS_PER_BLOB: usize = 4;
66

7+
/// Compiles blst.
8+
//
9+
// NOTE: This code is taken from https://github.com/supranational/blst `build.rs` `main`. The crate
10+
// is not used as a depedency to avoid double link issues on dependants.
11+
fn compile_blst(blst_base_dir: PathBuf) {
12+
// account for cross-compilation [by examining environment variables]
13+
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
14+
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
15+
16+
if target_os.ne("none") && !env::var("BLST_TEST_NO_STD").is_ok() {
17+
println!("cargo:rustc-cfg=feature=\"std\"");
18+
if target_arch.eq("wasm32") {
19+
println!("cargo:rustc-cfg=feature=\"no-threads\"");
20+
}
21+
}
22+
println!("cargo:rerun-if-env-changed=BLST_TEST_NO_STD");
23+
24+
println!("Using blst source directory {}", blst_base_dir.display());
25+
26+
// Set CC environment variable to choose alternative C compiler.
27+
// Optimization level depends on whether or not --release is passed
28+
// or implied.
29+
30+
#[cfg(target_env = "msvc")]
31+
if env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap().eq("32") && !env::var("CC").is_ok() {
32+
match std::process::Command::new("clang-cl")
33+
.arg("--version")
34+
.output()
35+
{
36+
Ok(out) => {
37+
if String::from_utf8(out.stdout)
38+
.unwrap_or("unintelligible".to_string())
39+
.contains("Target: i686-")
40+
{
41+
env::set_var("CC", "clang-cl");
42+
}
43+
}
44+
Err(_) => { /* no clang-cl in sight, just ignore the error */ }
45+
}
46+
}
47+
48+
let mut cc = cc::Build::new();
49+
50+
let c_src_dir = blst_base_dir.join("src");
51+
println!("cargo:rerun-if-changed={}", c_src_dir.display());
52+
let mut file_vec = vec![c_src_dir.join("server.c")];
53+
54+
if target_arch.eq("x86_64") || target_arch.eq("aarch64") {
55+
let asm_dir = blst_base_dir.join("build");
56+
println!("cargo:rerun-if-changed={}", asm_dir.display());
57+
blst_assembly(&mut file_vec, &asm_dir, &target_arch);
58+
} else {
59+
cc.define("__BLST_NO_ASM__", None);
60+
}
61+
match (cfg!(feature = "portable"), cfg!(feature = "force-adx")) {
62+
(true, false) => {
63+
println!("Compiling in portable mode without ISA extensions");
64+
cc.define("__BLST_PORTABLE__", None);
65+
}
66+
(false, true) => {
67+
if target_arch.eq("x86_64") {
68+
println!("Enabling ADX support via `force-adx` feature");
69+
cc.define("__ADX__", None);
70+
} else {
71+
println!("`force-adx` is ignored for non-x86_64 targets");
72+
}
73+
}
74+
(false, false) =>
75+
{
76+
#[cfg(target_arch = "x86_64")]
77+
if target_arch.eq("x86_64") && std::is_x86_feature_detected!("adx") {
78+
println!("Enabling ADX because it was detected on the host");
79+
cc.define("__ADX__", None);
80+
}
81+
}
82+
(true, true) => panic!("Cannot compile with both `portable` and `force-adx` features"),
83+
}
84+
if env::var("CARGO_CFG_TARGET_ENV").unwrap().eq("msvc") {
85+
cc.flag("-Zl");
86+
}
87+
cc.flag_if_supported("-mno-avx") // avoid costly transitions
88+
.flag_if_supported("-fno-builtin")
89+
.flag_if_supported("-Wno-unused-function")
90+
.flag_if_supported("-Wno-unused-command-line-argument");
91+
if target_arch.eq("wasm32") {
92+
cc.flag_if_supported("-ffreestanding");
93+
}
94+
if !cfg!(debug_assertions) {
95+
cc.opt_level(2);
96+
}
97+
cc.files(&file_vec).compile("blst");
98+
}
99+
100+
/// Adds assembly files for blst compilation.
101+
fn blst_assembly(file_vec: &mut Vec<PathBuf>, base_dir: &Path, _arch: &String) {
102+
#[cfg(target_env = "msvc")]
103+
if env::var("CARGO_CFG_TARGET_ENV").unwrap().eq("msvc") {
104+
let sfx = match _arch.as_str() {
105+
"x86_64" => "x86_64",
106+
"aarch64" => "armv8",
107+
_ => "unknown",
108+
};
109+
let files = glob::glob(&format!("{}/win64/*-{}.asm", base_dir.display(), sfx))
110+
.expect("unable to collect assembly files");
111+
for file in files {
112+
file_vec.push(file.unwrap());
113+
}
114+
return;
115+
}
116+
117+
file_vec.push(base_dir.join("assembly.S"));
118+
}
119+
7120
fn main() {
8121
let cargo_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
9122
let root_dir = cargo_dir
@@ -20,9 +133,11 @@ fn main() {
20133

21134
eprintln!("Using FIELD_ELEMENTS_PER_BLOB={}", field_elements_per_blob);
22135

23-
// Obtain the header files exposed by blst-bindings' crate.
24-
let blst_headers_dir =
25-
std::env::var_os("DEP_BLST_BINDINGS").expect("BLST exposes header files for bindings");
136+
let blst_base_dir = root_dir.join("blst");
137+
compile_blst(blst_base_dir.clone());
138+
139+
// Obtain the header files of blst
140+
let blst_headers_dir = blst_base_dir.join("bindings");
26141

27142
let c_src_dir = root_dir.join("src");
28143

0 commit comments

Comments
 (0)