Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/fuzzing/wasm-spec-interpreter/build.rs
1691 views
1
/// Build the OCaml code and statically link it into the Rust library; see the
2
/// [ocaml-interop
3
/// example](https://github.com/tezedge/ocaml-interop/blob/master/testing/rust-caller/build.rs)
4
/// for more details. After playing with this a bit, I discovered that the best
5
/// approach to avoid missing symbols was to imitate `dune`: I observed `rm -rf
6
/// _build && dune build ./ocaml/interpret.exe.o --display=verbose` and used
7
/// that as a pattern, now encoded in `ocaml/Makefile` for easier debugging.
8
use std::{env, path::PathBuf, process::Command};
9
10
const LIB_NAME: &'static str = "interpret";
11
const OCAML_DIR: &'static str = "ocaml";
12
const SPEC_DIR: &'static str = "ocaml/spec";
13
const SPEC_REPOSITORY: &'static str = "https://github.com/conrad-watt/spec";
14
const SPEC_REPOSITORY_BRANCH: &'static str = "wasmtime_fuzzing";
15
const SPEC_REPOSITORY_REV: &'static str = "c6bab4461e10229e557aae2e1027cadfce0161ce";
16
17
fn main() {
18
println!("cargo:rustc-check-cfg=cfg(feature, values(\"has-libinterpret\"))");
19
println!("cargo:rustc-check-cfg=cfg(fuzzing)");
20
if cfg!(feature = "build-libinterpret") {
21
build();
22
}
23
}
24
25
fn build() {
26
let out_dir = &env::var("OUT_DIR").unwrap();
27
28
// Re-run if changed.
29
println!("cargo:rerun-if-changed={OCAML_DIR}/{LIB_NAME}.ml");
30
println!("cargo:rerun-if-changed={OCAML_DIR}/Makefile");
31
32
if let Some(other_dir) = env::var_os("FFI_LIB_DIR") {
33
// Link with a library provided in the `FFI_LIB_DIR`.
34
println!("cargo:rustc-link-search={}", other_dir.to_str().unwrap());
35
println!("cargo:rustc-link-lib=static={LIB_NAME}");
36
} else {
37
// Ensure the spec repository is present.
38
if is_spec_repository_empty(SPEC_DIR) {
39
retrieve_spec_repository(SPEC_DIR)
40
}
41
42
// Build the library to link to.
43
build_lib(out_dir, OCAML_DIR);
44
println!("cargo:rustc-link-search={out_dir}");
45
println!("cargo:rustc-link-lib=static={LIB_NAME}");
46
}
47
48
// Enabling this feature alerts the compiler to use the `with_library`
49
// module.
50
println!("cargo:rustc-cfg=feature=\"has-libinterpret\"");
51
}
52
53
// Build the OCaml library into Cargo's `out` directory.
54
fn build_lib(out_dir: &str, ocaml_dir: &str) {
55
let status = Command::new("make")
56
.arg(format!("BUILD_DIR={out_dir}"))
57
.current_dir(ocaml_dir)
58
.status()
59
.expect("Failed to execute 'make' command to build OCaml library");
60
61
assert!(
62
status.success(),
63
"Failed to build the OCaml library using 'make'."
64
)
65
}
66
67
// Check if the spec repository directory contains any files.
68
fn is_spec_repository_empty(destination: &str) -> bool {
69
PathBuf::from(destination)
70
.read_dir()
71
.map(|mut i| i.next().is_none())
72
.unwrap_or(true)
73
}
74
75
// Clone the spec repository into `destination`. This exists due to the large
76
// size of the dependencies (e.g. KaTeX) that are pulled if this were cloned
77
// recursively as a submodule.
78
fn retrieve_spec_repository(destination: &str) {
79
let status = Command::new("git")
80
.arg("clone")
81
.arg(SPEC_REPOSITORY)
82
.arg("-b")
83
.arg(SPEC_REPOSITORY_BRANCH)
84
.arg(destination)
85
.status()
86
.expect("Failed to execute 'git' command to clone spec repository.");
87
assert!(status.success(), "Failed to retrieve the spec repository.");
88
89
let status = Command::new("git")
90
.arg("reset")
91
.arg("--hard")
92
.arg(SPEC_REPOSITORY_REV)
93
.current_dir(destination)
94
.status()
95
.expect("Failed to execute 'git' command to clone spec repository.");
96
assert!(status.success(), "Failed to reset to revision.");
97
}
98
99