-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.rs
More file actions
97 lines (82 loc) · 3.17 KB
/
Copy pathbuild.rs
File metadata and controls
97 lines (82 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
fn find_llvm_config() -> anyhow::Result<PathBuf> {
if let Ok(path) = env::var("LLVM_CONFIG_PATH") {
let candidate = PathBuf::from(path);
if candidate.is_file() {
return Ok(candidate);
}
}
let default = PathBuf::from("llvm-config");
if Command::new(&default).arg("--version").output().is_ok() {
return Ok(default);
}
if cfg!(target_os = "macos")
&& let Ok(output) = Command::new("brew").args(["--prefix", "llvm"]).output()
&& output.status.success()
{
let prefix = String::from_utf8(output.stdout)?.trim().to_string();
let candidate = Path::new(&prefix).join("bin").join("llvm-config");
if candidate.is_file() {
return Ok(candidate);
}
}
anyhow::bail!(
"could not find llvm-config. Set LLVM_CONFIG_PATH, add llvm-config to PATH, or (on macOS) install LLVM via Homebrew"
)
}
fn run_llvm_config(llvm_config: &Path, arg: &str) -> anyhow::Result<String> {
let output = Command::new(llvm_config).arg(arg).output()?;
if !output.status.success() {
anyhow::bail!(
"{} {} failed: {}",
llvm_config.display(),
arg,
String::from_utf8_lossy(&output.stderr)
);
}
Ok(String::from_utf8(output.stdout)?.trim().to_string())
}
static LLVM_WRAPPER: &str = "./llvm/wrapper.h";
static LLVM_INIT_SHIM: &str = "./llvm/llvm_init_shim.c";
fn main() -> anyhow::Result<()> {
println!("cargo:rerun-if-changed={}", LLVM_WRAPPER);
println!("cargo:rerun-if-changed={}", LLVM_INIT_SHIM);
let llvm_config = find_llvm_config()?;
println!("cargo:rerun-if-env-changed=LLVM_CONFIG_PATH");
let include_dir = run_llvm_config(&llvm_config, "--includedir")?;
let lib_dir = run_llvm_config(&llvm_config, "--libdir")?;
let libs_raw = run_llvm_config(&llvm_config, "--libs")?;
let system_libs_raw = run_llvm_config(&llvm_config, "--system-libs")?;
println!("cargo:rustc-link-search=native={lib_dir}");
for token in libs_raw
.split_whitespace()
.chain(system_libs_raw.split_whitespace())
{
if let Some(name) = token.strip_prefix("-l") {
println!("cargo:rustc-link-lib={name}");
} else if let Some(path) = token.strip_prefix("-L") {
println!("cargo:rustc-link-search=native={path}");
}
}
let out_path = PathBuf::from(env::var("OUT_DIR")?);
cc::Build::new()
.file(LLVM_INIT_SHIM)
.include(&include_dir)
.out_dir(&out_path)
.compile("llvm_init_shim");
println!("cargo:rustc-link-search=native={}", out_path.display());
println!("cargo:rustc-link-lib=static=llvm_init_shim");
let bindings = bindgen::Builder::default()
.header(LLVM_WRAPPER)
.clang_arg(format!("-I{include_dir}"))
.allowlist_function("LLVM.*")
.allowlist_type("LLVM.*")
.allowlist_var("LLVM.*")
.generate_comments(false)
.generate()
.map_err(|_| anyhow::anyhow!("failed to generate LLVM bindings"))?;
bindings.write_to_file(out_path.join("llvm_bindings.rs"))?;
Ok(())
}