This repository has been archived by the owner on Apr 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.rs
151 lines (131 loc) · 5.04 KB
/
build.rs
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Mostly based on https://github.com/tazz4843/whisper-rs/blob/master/sys/build.rs
extern crate bindgen;
use std::{env, path::PathBuf};
const LIB_NAME: &str = "rs-llama-cpp-wrapper";
const FUNCTION_NAME_PATTERN: &str = "rs_llama_cpp_.*";
fn main() {
let target = env::var("TARGET").unwrap();
// Link C++ standard library
if let Some(cpp_stdlib) = get_cpp_link_stdlib(&target) {
println!("cargo:rustc-link-lib=dylib={}", cpp_stdlib);
println!("cargo:rustc-link-arg=-l{}", cpp_stdlib);
}
// Link macOS Accelerate framework for matrix calculations
if target.contains("apple") {
println!("cargo:rustc-link-lib=framework=Accelerate");
}
println!("cargo:rustc-link-search={}", env::var("OUT_DIR").unwrap());
println!("cargo:rustc-link-lib=static=llama");
println!("cargo:rustc-link-lib=static={}", LIB_NAME);
for file in &[
"llama.cpp",
"CMakeLists.txt",
"rs-llama-cpp-wrapper.h",
"rs-llama-cpp-wrapper.cpp",
"run-inference.h",
"run-inference.cpp",
] {
println!("cargo:rerun-if-changed={}/{}", LIB_NAME, file);
}
let original_dir = env::current_dir().unwrap();
// build lib
env::set_current_dir(LIB_NAME)
.unwrap_or_else(|_| panic!("Unable to change directory to {}", LIB_NAME));
_ = std::fs::remove_dir_all("build");
_ = std::fs::create_dir("build");
env::set_current_dir("build")
.unwrap_or_else(|_| panic!("Unable to change directory to {} build", LIB_NAME));
let build_dir = env::current_dir().unwrap();
env::set_var("CXXFLAGS", "-fPIC");
env::set_var("CFLAGS", "-fPIC");
let code = std::process::Command::new("cmake")
.arg("..")
.arg("-DCMAKE_BUILD_TYPE=Release")
.status()
.expect("Failed to generate build script");
if code.code() != Some(0) {
panic!("Failed to generate build script");
}
#[allow(clippy::suspicious_command_arg_space)]
let code = std::process::Command::new("cmake")
.arg("--build")
.arg(".")
.arg("--config Release")
.status()
.expect("Failed to build lib");
if code.code() != Some(0) {
panic!("Failed to build lib");
}
// move libllama.a to where Cargo expects it (OUT_DIR)
#[cfg(target_os = "windows")]
{
std::fs::copy(
"llama.cpp/Release/llama.lib",
format!("{}/llama.lib", env::var("OUT_DIR").unwrap()),
)
.expect("Failed to copy lib");
std::fs::copy(
// TODO: change name
format!("Release/{}.lib", LIB_NAME),
format!("{}/{}.lib", env::var("OUT_DIR").unwrap(), LIB_NAME),
)
.expect("Failed to copy lib");
}
#[cfg(not(target_os = "windows"))]
{
std::fs::copy(
"llama.cpp/libllama.a",
format!("{}/libllama.a", env::var("OUT_DIR").unwrap()),
)
.expect("Failed to copy lib");
std::fs::copy(
format!("lib{}.a", LIB_NAME),
format!("{}/lib{}.a", env::var("OUT_DIR").unwrap(), LIB_NAME),
)
.expect("Failed to copy lib");
}
env::set_current_dir(original_dir).expect("Unable to change directory to original dir");
let bindings = bindgen::Builder::default()
.header(format!("{}/{}.h", LIB_NAME, LIB_NAME).as_str())
.allowlist_function(FUNCTION_NAME_PATTERN)
.allowlist_recursively(true)
.clang_args(&["-x", "c++"])
.clang_arg(format!("-I./{}", LIB_NAME).as_str())
.clang_arg(format!("-I./{}/llama.cpp", LIB_NAME).as_str())
.clang_arg(format!("-I./{}/llama.cpp/examples", LIB_NAME).as_str())
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate();
match bindings {
Ok(b) => {
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
b.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
b.write_to_file("src/bindings.rs")
.expect("Couldn't write bindings!");
}
Err(e) => {
println!("cargo:warning=Unable to generate bindings: {}", e);
println!("cargo:warning=Using bundled bindings.rs, which may be out of date");
// copy src/bindings.rs to OUT_DIR
std::fs::copy(
"src/bindings.rs",
env::var("OUT_DIR").unwrap() + "/bindings.rs",
)
.expect("Unable to copy bindings.rs");
}
}
// clean the modified files to prevent Cargo from complaining during crate publish
_ = std::fs::remove_dir_all(build_dir);
}
// From https://github.com/alexcrichton/cc-rs/blob/fba7feded71ee4f63cfe885673ead6d7b4f2f454/src/lib.rs#L2462
fn get_cpp_link_stdlib(target: &str) -> Option<&'static str> {
if target.contains("msvc") {
None
} else if target.contains("apple") || target.contains("freebsd") || target.contains("openbsd") {
Some("c++")
} else if target.contains("android") {
Some("c++_shared")
} else {
Some("stdc++")
}
}