use std::env;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
if env::var("CARGO_FEATURE_LLAMACPP").is_err() {
return;
}
build_llamacpp();
}
#[cfg(feature = "llamacpp")]
fn build_llamacpp() {
use std::path::{Path, PathBuf};
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let workspace_root = manifest_dir
.parent()
.and_then(Path::parent)
.expect("workspace root resolvable");
let llama_src = workspace_root.join("vendor").join("llama.cpp");
let cpp_wrapper = manifest_dir.join("cpp");
if !llama_src.join("CMakeLists.txt").exists() {
panic!(
"vendor/llama.cpp not populated at {}. Run \
`git submodule update --init --recursive`.",
llama_src.display()
);
}
if !cpp_wrapper.join("CMakeLists.txt").exists() {
panic!(
"inferd-engine cpp wrapper not found at {}. The crate is \
out of tree?",
cpp_wrapper.display()
);
}
println!(
"cargo:rerun-if-changed={}",
cpp_wrapper.join("CMakeLists.txt").display()
);
println!(
"cargo:rerun-if-changed={}",
llama_src.join("CMakeLists.txt").display()
);
println!(
"cargo:rerun-if-changed={}",
llama_src.join("include/llama.h").display()
);
println!(
"cargo:rerun-if-changed={}",
llama_src.join("tools/mtmd/mtmd.h").display()
);
let dst = cmake::Config::new(&cpp_wrapper)
.define("LLAMA_BUILD_SERVER", "OFF")
.define("LLAMA_BUILD_EXAMPLES", "OFF")
.define("LLAMA_BUILD_TESTS", "OFF")
.define("LLAMA_BUILD_TOOLS", "OFF")
.define("LLAMA_CURL", "OFF")
.define("INFERD_BUILD_MTMD", "ON")
.define("BUILD_SHARED_LIBS", "OFF")
.profile("Release")
.define(
"GGML_CUDA",
if cfg!(feature = "cuda") { "ON" } else { "OFF" },
)
.define(
"GGML_METAL",
if cfg!(feature = "metal") { "ON" } else { "OFF" },
)
.define(
"GGML_VULKAN",
if cfg!(feature = "vulkan") {
"ON"
} else {
"OFF"
},
)
.define(
"GGML_HIP",
if cfg!(feature = "rocm") { "ON" } else { "OFF" },
)
.build();
println!(
"cargo:rustc-link-search=native={}",
dst.join("lib").display()
);
println!(
"cargo:rustc-link-search=native={}",
dst.join("build").display()
);
println!("cargo:rustc-link-lib=static=mtmd");
println!("cargo:rustc-link-lib=static=llama");
println!("cargo:rustc-link-lib=static=ggml");
println!("cargo:rustc-link-lib=static=ggml-base");
println!("cargo:rustc-link-lib=static=ggml-cpu");
if cfg!(target_os = "linux") {
println!("cargo:rustc-link-lib=stdc++");
println!("cargo:rustc-link-lib=gomp");
} else if cfg!(target_os = "macos") {
println!("cargo:rustc-link-lib=c++");
println!("cargo:rustc-link-lib=static=ggml-blas");
println!("cargo:rustc-link-lib=framework=Accelerate");
}
if cfg!(target_os = "windows") {
println!("cargo:rustc-link-lib=Advapi32");
}
let llama_header = llama_src.join("include").join("llama.h");
let llama_bindings = bindgen::Builder::default()
.header(llama_header.to_string_lossy())
.clang_arg(format!("-I{}", llama_src.join("include").display()))
.clang_arg(format!(
"-I{}",
llama_src.join("ggml").join("include").display()
))
.allowlist_function("llama_.*")
.allowlist_type("llama_.*")
.allowlist_var("LLAMA_.*")
.prepend_enum_name(false)
.derive_default(true)
.layout_tests(false)
.generate()
.expect("bindgen generate llama.h");
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
llama_bindings
.write_to_file(out_dir.join("llama_bindings.rs"))
.expect("write llama bindgen output");
println!("cargo:rerun-if-changed={}", llama_header.display());
let mtmd_header = llama_src.join("tools").join("mtmd").join("mtmd.h");
let mtmd_helper_header = llama_src.join("tools").join("mtmd").join("mtmd-helper.h");
let mtmd_bindings = bindgen::Builder::default()
.header(mtmd_header.to_string_lossy())
.header(mtmd_helper_header.to_string_lossy())
.clang_arg(format!(
"-I{}",
llama_src.join("tools").join("mtmd").display()
))
.clang_arg(format!("-I{}", llama_src.join("include").display()))
.clang_arg(format!(
"-I{}",
llama_src.join("ggml").join("include").display()
))
.allowlist_function("mtmd_.*")
.allowlist_type("mtmd_.*")
.allowlist_var("MTMD_.*")
.blocklist_type("llama_.*")
.blocklist_type("ggml_.*")
.blocklist_function("llama_.*")
.blocklist_function("ggml_.*")
.raw_line("use crate::ffi::{llama_context, llama_model, llama_pos, llama_seq_id, llama_token, llama_flash_attn_type, ggml_log_callback, ggml_backend_sched_eval_callback};")
.prepend_enum_name(false)
.derive_default(true)
.layout_tests(false)
.generate()
.expect("bindgen generate mtmd.h + mtmd-helper.h");
mtmd_bindings
.write_to_file(out_dir.join("mtmd_bindings.rs"))
.expect("write mtmd bindgen output");
println!("cargo:rerun-if-changed={}", mtmd_header.display());
println!("cargo:rerun-if-changed={}", mtmd_helper_header.display());
}
#[cfg(not(feature = "llamacpp"))]
fn build_llamacpp() {
panic!("CARGO_FEATURE_LLAMACPP set but cfg(feature=\"llamacpp\") is off");
}