Path: blob/main/crates/fuzzing/wasm-spec-interpreter/build.rs
1691 views
/// Build the OCaml code and statically link it into the Rust library; see the1/// [ocaml-interop2/// example](https://github.com/tezedge/ocaml-interop/blob/master/testing/rust-caller/build.rs)3/// for more details. After playing with this a bit, I discovered that the best4/// approach to avoid missing symbols was to imitate `dune`: I observed `rm -rf5/// _build && dune build ./ocaml/interpret.exe.o --display=verbose` and used6/// that as a pattern, now encoded in `ocaml/Makefile` for easier debugging.7use std::{env, path::PathBuf, process::Command};89const LIB_NAME: &'static str = "interpret";10const OCAML_DIR: &'static str = "ocaml";11const SPEC_DIR: &'static str = "ocaml/spec";12const SPEC_REPOSITORY: &'static str = "https://github.com/conrad-watt/spec";13const SPEC_REPOSITORY_BRANCH: &'static str = "wasmtime_fuzzing";14const SPEC_REPOSITORY_REV: &'static str = "c6bab4461e10229e557aae2e1027cadfce0161ce";1516fn main() {17println!("cargo:rustc-check-cfg=cfg(feature, values(\"has-libinterpret\"))");18println!("cargo:rustc-check-cfg=cfg(fuzzing)");19if cfg!(feature = "build-libinterpret") {20build();21}22}2324fn build() {25let out_dir = &env::var("OUT_DIR").unwrap();2627// Re-run if changed.28println!("cargo:rerun-if-changed={OCAML_DIR}/{LIB_NAME}.ml");29println!("cargo:rerun-if-changed={OCAML_DIR}/Makefile");3031if let Some(other_dir) = env::var_os("FFI_LIB_DIR") {32// Link with a library provided in the `FFI_LIB_DIR`.33println!("cargo:rustc-link-search={}", other_dir.to_str().unwrap());34println!("cargo:rustc-link-lib=static={LIB_NAME}");35} else {36// Ensure the spec repository is present.37if is_spec_repository_empty(SPEC_DIR) {38retrieve_spec_repository(SPEC_DIR)39}4041// Build the library to link to.42build_lib(out_dir, OCAML_DIR);43println!("cargo:rustc-link-search={out_dir}");44println!("cargo:rustc-link-lib=static={LIB_NAME}");45}4647// Enabling this feature alerts the compiler to use the `with_library`48// module.49println!("cargo:rustc-cfg=feature=\"has-libinterpret\"");50}5152// Build the OCaml library into Cargo's `out` directory.53fn build_lib(out_dir: &str, ocaml_dir: &str) {54let status = Command::new("make")55.arg(format!("BUILD_DIR={out_dir}"))56.current_dir(ocaml_dir)57.status()58.expect("Failed to execute 'make' command to build OCaml library");5960assert!(61status.success(),62"Failed to build the OCaml library using 'make'."63)64}6566// Check if the spec repository directory contains any files.67fn is_spec_repository_empty(destination: &str) -> bool {68PathBuf::from(destination)69.read_dir()70.map(|mut i| i.next().is_none())71.unwrap_or(true)72}7374// Clone the spec repository into `destination`. This exists due to the large75// size of the dependencies (e.g. KaTeX) that are pulled if this were cloned76// recursively as a submodule.77fn retrieve_spec_repository(destination: &str) {78let status = Command::new("git")79.arg("clone")80.arg(SPEC_REPOSITORY)81.arg("-b")82.arg(SPEC_REPOSITORY_BRANCH)83.arg(destination)84.status()85.expect("Failed to execute 'git' command to clone spec repository.");86assert!(status.success(), "Failed to retrieve the spec repository.");8788let status = Command::new("git")89.arg("reset")90.arg("--hard")91.arg(SPEC_REPOSITORY_REV)92.current_dir(destination)93.status()94.expect("Failed to execute 'git' command to clone spec repository.");95assert!(status.success(), "Failed to reset to revision.");96}979899