summaryrefslogtreecommitdiffstats
path: root/third_party/rust/lucet-wasi-wasmsbx/build.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/lucet-wasi-wasmsbx/build.rs')
-rw-r--r--third_party/rust/lucet-wasi-wasmsbx/build.rs114
1 files changed, 114 insertions, 0 deletions
diff --git a/third_party/rust/lucet-wasi-wasmsbx/build.rs b/third_party/rust/lucet-wasi-wasmsbx/build.rs
new file mode 100644
index 0000000000..068e214fae
--- /dev/null
+++ b/third_party/rust/lucet-wasi-wasmsbx/build.rs
@@ -0,0 +1,114 @@
+#![allow(unused)]
+
+use std::env;
+use std::fs::File;
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+
+fn wasi_sdk() -> PathBuf {
+ Path::new(&env::var("WASI_SDK").unwrap_or("/opt/wasi-sdk".to_owned())).to_path_buf()
+}
+
+fn wasi_sysroot() -> PathBuf {
+ match env::var("WASI_SYSROOT") {
+ Ok(wasi_sysroot) => Path::new(&wasi_sysroot).to_path_buf(),
+ Err(_) => {
+ let mut path = wasi_sdk();
+ path.push("share");
+ path.push("wasi-sysroot");
+ path
+ }
+ }
+}
+
+fn wasm_clang_root() -> PathBuf {
+ match env::var("CLANG_ROOT") {
+ Ok(clang) => Path::new(&clang).to_path_buf(),
+ Err(_) => {
+ let mut path = wasi_sdk();
+ path.push("lib");
+ path.push("clang");
+ path.push("8.0.1");
+ path
+ }
+ }
+}
+
+// `src/wasi_host.rs` is automatically generated using clang and
+// wasi-libc headers. This requires these to be present, and installed
+// at specific paths, which is not something we can rely on outside
+// of our environment.
+// So, we follow what most other tools using `bindgen` do, and provide
+// a pre-generated version of the file, along with a way to update it.
+// This is what the `update-bindings` feature do. It requires the WASI SDK
+// to be either installed in `/opt/wasi-sdk`, or at a location defined by
+// a `WASI_SDK` environment variable, as well as `clang` headers either
+// being part of `WASI_SDK`, or found in a path defined by a
+// `CLANG_ROOT` environment variable.
+#[cfg(not(feature = "update-bindings"))]
+fn main() {}
+
+#[cfg(feature = "update-bindings")]
+fn main() {
+ let wasi_sysroot = wasi_sysroot();
+ let wasm_clang_root = wasm_clang_root();
+ assert!(
+ wasi_sysroot.exists(),
+ "wasi-sysroot not present at {:?}",
+ wasi_sysroot
+ );
+ assert!(
+ wasm_clang_root.exists(),
+ "clang-root not present at {:?}",
+ wasm_clang_root
+ );
+
+ let wasi_sysroot_core_h = wasi_sysroot.join("include/wasi/core.h");
+
+ assert!(
+ wasi_sysroot_core_h.exists(),
+ "wasi-sysroot core.h not present at {:?}",
+ wasi_sysroot_core_h
+ );
+
+ println!("cargo:rerun-if-changed={}", wasi_sysroot_core_h.display());
+
+ let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
+
+ let core_h_path = out_path.join("core.h");
+ let core_h = File::create(&core_h_path).unwrap();
+
+ // `bindgen` doesn't understand typed constant macros like `UINT8_C(123)`, so this fun regex
+ // strips them off to yield a copy of `wasi/core.h` with bare constants.
+ let sed_result = Command::new("sed")
+ .arg("-E")
+ .arg(r#"s/U?INT[0-9]+_C\(((0x)?[0-9]+)\)/\1/g"#)
+ .arg(wasi_sysroot_core_h)
+ .stdout(Stdio::from(core_h))
+ .status()
+ .expect("can execute sed");
+
+ if !sed_result.success() {
+ // something failed, but how?
+ match sed_result.code() {
+ Some(code) => panic!("sed failed with code {}", code),
+ None => panic!("sed exited abnormally"),
+ }
+ }
+
+ let host_builder = bindgen::Builder::default()
+ .clang_arg("-nostdinc")
+ .clang_arg("-D__wasi__")
+ .clang_arg(format!("-isystem={}/include/", wasi_sysroot.display()))
+ .clang_arg(format!("-I{}/include/", wasm_clang_root.display()))
+ .header(core_h_path.to_str().unwrap())
+ .whitelist_type("__wasi_.*")
+ .whitelist_var("__WASI_.*");
+
+ let src_path = Path::new("src");
+ host_builder
+ .generate()
+ .expect("can generate host bindings")
+ .write_to_file(src_path.join("wasi_host.rs"))
+ .expect("can write host bindings");
+}