Skip to content

Commit

Permalink
Add gemma.cpp bindings / llm-chain-gemma.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmuk committed Mar 8, 2024
1 parent 989b970 commit 54d2f5a
Show file tree
Hide file tree
Showing 17 changed files with 1,070 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "crates/llm-chain-llama/sys/llama.cpp"]
path = crates/llm-chain-llama-sys/llama.cpp
url = https://github.com/ggerganov/llama.cpp.git
[submodule "crates/llm-chain-gemma-sys/gemma.cpp"]
path = crates/llm-chain-gemma-sys/gemma.cpp
url = https://github.com/google/gemma.cpp.git
24 changes: 19 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions crates/llm-chain-gemma-sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "llm-chain-gemma-sys"
description = "A library with bindings for gemma.cpp"
version = "0.1.0"
edition = "2021"
license = "MIT"
keywords = ["llm", "langchain", "gemma", "chain"]
categories = ["science"]
authors = [
"Jun Mukai <[email protected]>",
]
repository = "https://github.com/sobelio/llm-chain/"
readme = "README.md"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[build-dependencies]
cc = "1.0.87"
Binary file added crates/llm-chain-gemma-sys/a.out
Binary file not shown.
123 changes: 123 additions & 0 deletions crates/llm-chain-gemma-sys/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#![allow(clippy::uninlined_format_args)]

extern crate cc;

use std::env;

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=gemma");
println!("cargo:rustc-link-lib=static=hwy");
println!("cargo:rustc-link-lib=static=hwy_contrib");
println!("cargo:rustc-link-lib=static=sentencepiece");
println!("cargo:rustc-link-lib=static=bindings");
println!("cargo:rerun-if-changed=wrapper.h");

// stop if we're on docs.rs
if env::var("DOCS_RS").is_ok() {
return;
}

// Run cmake to generate build files.
env::set_current_dir("gemma.cpp").expect("Unable to change directory to gemma.cpp");
env::set_current_dir("build").expect("Unable to change directory to gemma.cpp build");

env::set_var("CXXFLAGS", "-fPIC");
env::set_var("CFLAGS", "-fPIC");

let mut code = std::process::Command::new("cmake");
let code = code
.arg("..")
.arg("-DCMAKE_BUILD_TYPE=Release")
.arg("-DBUILD_SHARED_LIBS=OFF")
.arg("-DWEIGHT_TYPE=hwy::bfloat16_t")
.arg("-DSPM_ENABLE_SHARED=OFF");
let code = code.status().expect("Failed to generate build script");
if code.code() != Some(0) {
panic!("Failed to generate build script");
}

// Build binary.
#[allow(clippy::suspicious_command_arg_space)]
let code = std::process::Command::new("cmake")
.arg("--build")
.arg(".")
.arg("--config Release")
.arg("--")
.arg("libgemma")
.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")]
{
// I haven't tested windows, so it's not supported yet.
}

#[cfg(not(target_os = "windows"))]
{
std::fs::copy(
"libgemma.a",
format!("{}/libgemma.a", env::var("OUT_DIR").unwrap()),
)
.expect("Failed to copy lib");

std::fs::copy(
"_deps/highway-build/libhwy.a",
format!("{}/libhwy.a", env::var("OUT_DIR").unwrap()),
)
.expect("Failed to copy libwhy.a");

std::fs::copy(
"_deps/highway-build/libhwy_contrib.a",
format!("{}/libhwy_contrib.a", env::var("OUT_DIR").unwrap()),
)
.expect("Failed to copy libwhy_contrib.a");

std::fs::copy(
"_deps/sentencepiece-build/src/libsentencepiece.a",
format!("{}/libsentencepiece.a", env::var("OUT_DIR").unwrap()),
)
.expect("Failed to copy libsentencepiece.a");
}

// Finally, build bindings.cc to allow access for gemma.cpp.
// So far, bindgen does not correctly generate buildable rust file,
// so I manually wrote bindings.rs for hand-written src/bindings.cc file.
env::set_current_dir("..").expect("Unlable to change directory back to gemma.cpp");
env::set_current_dir("..").expect("Unlable to change directory back to crate top");

cc::Build::new()
.cpp(true)
.file("src/bindings.cc")
.include("./gemma.cpp")
.include("./gemma.cpp/build/_deps/highway-src")
.include("./gemma.cpp/build/_deps/sentencepiece-src")
.compile("bindings");
}

// 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++")
}
}
1 change: 1 addition & 0 deletions crates/llm-chain-gemma-sys/gemma.cpp
Submodule gemma.cpp added at 0508e2
Loading

0 comments on commit 54d2f5a

Please sign in to comment.