use std::env;
use std::fs;
use std::path::Path;
use std::process::Command;
fn build_gvproxy(source_dir: &Path, output_path: &Path) {
println!("cargo:warning=Building libgvproxy from Go sources...");
let download_status = Command::new("go")
.args(["mod", "download"])
.current_dir(source_dir)
.status()
.expect("Failed to run 'go mod download' - ensure Go is installed");
if !download_status.success() {
panic!("Failed to download Go module dependencies");
}
let mut build_cmd = Command::new("go");
build_cmd.args(["build", "-buildmode=c-archive"]);
if source_dir.join("vendor").exists() {
build_cmd.args(["-mod=vendor"]);
}
build_cmd.args([
"-o",
output_path.to_str().expect("Invalid output path"),
".",
]);
let build_status = build_cmd
.current_dir(source_dir)
.status()
.expect("Failed to run 'go build' - ensure Go is installed");
if !build_status.success() {
panic!("Failed to build libgvproxy");
}
println!("cargo:warning=Successfully built libgvproxy");
}
fn main() {
let bridge_dir = Path::new("gvproxy-bridge");
if bridge_dir.is_dir() {
for entry in fs::read_dir(bridge_dir).expect("Failed to read gvproxy-bridge directory") {
let entry = entry.expect("Failed to read directory entry");
let path = entry.path();
if path
.extension()
.is_some_and(|ext| ext == "go" || ext == "mod" || ext == "sum")
{
println!("cargo:rerun-if-changed={}", path.display());
}
}
}
println!("cargo:rerun-if-changed=gvproxy-bridge"); println!("cargo:rerun-if-env-changed=BOXLITE_DEPS_STUB");
if env::var("BOXLITE_DEPS_STUB").is_err() {
let manifest_dir = std::path::PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
if manifest_dir.join(".cargo_vcs_info.json").exists() {
unsafe { env::set_var("BOXLITE_DEPS_STUB", "1") };
}
}
if env::var("BOXLITE_DEPS_STUB").is_ok() {
println!("cargo:warning=BOXLITE_DEPS_STUB mode: skipping libgvproxy build");
println!("cargo:LIBGVPROXY_BOXLITE_DEP=/nonexistent");
return;
}
let out_dir = env::var("OUT_DIR").expect("OUT_DIR not set");
let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
let source_dir = Path::new(&manifest_dir).join("gvproxy-bridge");
let lib_output = Path::new(&out_dir).join("libgvproxy.a");
build_gvproxy(&source_dir, &lib_output);
let header_src = source_dir.join("libgvproxy.h");
if header_src.exists() {
let header_dst = Path::new(&out_dir).join("libgvproxy.h");
fs::copy(&header_src, &header_dst).expect("Failed to copy libgvproxy.h");
}
println!("cargo:rustc-link-search=native={}", out_dir);
println!("cargo:rustc-link-lib=static=gvproxy");
#[cfg(target_os = "macos")]
{
println!("cargo:rustc-link-lib=framework=CoreFoundation");
println!("cargo:rustc-link-lib=framework=Security");
}
#[cfg(target_os = "linux")]
{
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
let gnu_triple = match arch.as_str() {
"x86_64" => "x86_64-linux-gnu",
"aarch64" => "aarch64-linux-gnu",
_ => "x86_64-linux-gnu",
};
println!("cargo:rustc-link-search=native=/usr/lib/{}", gnu_triple);
println!("cargo:rustc-link-search=native=/usr/lib64");
println!("cargo:rustc-link-lib=static=resolv");
}
#[cfg(not(target_os = "linux"))]
println!("cargo:rustc-link-lib=resolv");
println!("cargo:LIBGVPROXY_BOXLITE_DEP={}", out_dir);
}