From 48e2225083d7c74b9ece7cad504699a4cecab070 Mon Sep 17 00:00:00 2001 From: Jorge Prendes Date: Mon, 31 Jul 2023 11:37:17 +0100 Subject: [PATCH] add options to allow generating statically linked binaries Signed-off-by: Jorge Prendes --- crates/wasmedge-sys/build.rs | 74 ++++++++++++++++++++----- crates/wasmedge-sys/build_paths.rs | 12 ++-- crates/wasmedge-sys/build_standalone.rs | 2 +- 3 files changed, 67 insertions(+), 21 deletions(-) diff --git a/crates/wasmedge-sys/build.rs b/crates/wasmedge-sys/build.rs index 2f8e34779..069c60860 100644 --- a/crates/wasmedge-sys/build.rs +++ b/crates/wasmedge-sys/build.rs @@ -7,6 +7,8 @@ use build_paths::{Env, LibWasmEdgePaths}; mod build_standalone; use build_standalone::*; +use crate::build_paths::AsPath; + const WASMEDGE_RELEASE_VERSION: &str = "0.13.3"; const REMOTE_ARCHIVES: phf::Map<&'static str, (&'static str, &'static str)> = phf_map! { "macos/aarch64" => ("db03037e2678e197f9cd5f01392ee088df07e7726849626190f2d4ec1dc693c9", "darwin_arm64"), @@ -87,11 +89,9 @@ fn main() { // Tell cargo to tell rustc to link our `wasmedge` library. Cargo will // automatically know it must look for a `libwasmedge.a` file. println!("cargo:rustc-link-lib=static=wasmedge"); - println!("cargo:rustc-link-lib=rt"); - println!("cargo:rustc-link-lib=dl"); - println!("cargo:rustc-link-lib=pthread"); - println!("cargo:rustc-link-lib=m"); - println!("cargo:rustc-link-lib=stdc++"); + for dep in ["rt", "dl", "pthread", "m", "stdc++"] { + link_lib(dep); + } } else { println!("cargo:rustc-env=LD_LIBRARY_PATH={lib_dir}"); println!("cargo:rustc-link-search={lib_dir}"); @@ -107,16 +107,55 @@ fn main() { let out_file = OUT_DIR.join("wasmedge.rs"); debug!("generating bindgen header {out_file:?}"); - bindgen::builder() - .header(header) - .clang_arg(format!("-I{inc_dir}")) - .prepend_enum_name(false) // The API already prepends the name. - .dynamic_link_require_all(true) - .parse_callbacks(Box::new(bindgen::CargoCallbacks)) - .generate() - .expect("failed to generate bindings") - .write_to_file(out_file) - .expect("failed to write bindings"); + if let Some(bindgen_path) = Env("WASMEDGE_RUST_BINDGEN_PATH").as_path() { + let success = std::process::Command::new(bindgen_path) + .arg("--no-prepend-enum-name") // The API already prepends the name. + .arg("--dynamic-link-require-all") + .arg("--formatter=none") + .arg("-o") + .arg(out_file) + .arg(header) + .arg("--") + .arg(format!("-I{inc_dir}")) + .status() + .expect("failed to run rust bindgen") + .success(); + assert!(success, "failed to run rust bindgen"); + } else { + bindgen::builder() + .header(header) + .clang_arg(format!("-I{inc_dir}")) + .prepend_enum_name(false) // The API already prepends the name. + .dynamic_link_require_all(true) + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + .generate() + .expect("failed to generate bindings") + .write_to_file(out_file) + .expect("failed to write bindings"); + } +} + +fn link_lib(dep: &str) { + // Sanitize dependency name for evn-vars, particularly `stdc++`. + let dep_slug: String = dep.replace('+', "x").to_uppercase(); + + let generic_link_type_var = Env!("WASMEDGE_DEPS_LINK_TYPE"); + let generic_lib_path_var = Env!("WASMEDGE_DEPS_LIB_PATH"); + let named_link_type_var = Env!("WASMEDGE_DEP_{dep_slug}_LINK_TYPE"); + let named_lib_path_var = Env!("WASMEDGE_DEP_{dep_slug}_LIB_PATH"); + + let link_type = named_link_type_var + .lossy() + .or_else(|| generic_link_type_var.lossy()) + .unwrap_or("dylib".to_string()); + + for path_var in [named_lib_path_var, generic_lib_path_var] { + if let Some(path) = path_var.lossy() { + println!("cargo:rustc-link-search={path}"); + } + } + + println!("cargo:rustc-link-lib={link_type}={dep}"); } #[macro_export] @@ -125,3 +164,8 @@ macro_rules! debug { println!("cargo:warning=[wasmedge-sys] {}", format!($($args),+)) }; } + +#[macro_export] +macro_rules! Env { + ($($args:expr),+) => { Env(format!($($args),+)) }; +} diff --git a/crates/wasmedge-sys/build_paths.rs b/crates/wasmedge-sys/build_paths.rs index 16f1b37a9..ccd89374b 100644 --- a/crates/wasmedge-sys/build_paths.rs +++ b/crates/wasmedge-sys/build_paths.rs @@ -1,10 +1,13 @@ use crate::debug; -pub struct Env<'a>(pub &'a str); +pub struct Env>(pub S); -impl Env<'_> { +impl> Env { pub fn read>(&self) -> Option { - std::env::var_os(self.0).map(T::from) + if self.0.as_ref() != "OUT_DIR" && !self.0.as_ref().starts_with("CARGO_") { + println!("cargo:rerun-if-env-changed={}", self.0.as_ref()); + } + std::env::var_os(self.0.as_ref()).map(T::from) } pub fn expect>(&self, msg: &str) -> T @@ -31,9 +34,8 @@ pub trait AsPath { fn as_path(&self) -> Option; } -impl AsPath for Env<'_> { +impl> AsPath for Env { fn as_path(&self) -> Option { - println!("cargo:rerun-if-env-changed={}", self.0); self.read() } } diff --git a/crates/wasmedge-sys/build_standalone.rs b/crates/wasmedge-sys/build_standalone.rs index e7de7b574..c5a28760a 100644 --- a/crates/wasmedge-sys/build_standalone.rs +++ b/crates/wasmedge-sys/build_standalone.rs @@ -108,7 +108,7 @@ fn get_remote_archive() -> Archive { fn do_http_request(url: &str) -> impl std::io::Read { let builder = reqwest::blocking::Client::builder(); - let builder = match Env("STANDALONE_PROXY").lossy() { + let builder = match Env("WASMEDGE_STANDALONE_PROXY").lossy() { Some(proxy) => { debug!("using proxy to download archive: {proxy}"); let proxy = reqwest::Proxy::all(proxy).expect("failed to parse proxy");