use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let lib_name = "librclone";
let rclone_repo = format!("github.com/rclone/rclone/{}", lib_name);
let target_triple = env::var("TARGET")?;
let out_dir = env::var("CARGO_MANIFEST_DIR")?;
let out_path = PathBuf::from(&out_dir).join("src").join(lib_name);
if env::var("DOCS_RS").is_ok() {
return Ok(());
}
println!(
"cargo:rerun-if-changed={}",
out_path.join("go.mod").display()
);
println!(
"cargo:rerun-if-changed={}",
out_path.join("go.sum").display()
);
let mut gofile_buf = String::new();
gofile_buf.push_str("package main\n\n");
gofile_buf.push_str(&format!("import \"{}\"", rclone_repo));
std::fs::write(out_path.join(format!("{}.go", lib_name)), gofile_buf)?;
let status = Command::new("go")
.current_dir("src/librclone")
.args(["build", "--buildmode=c-archive", "-o"])
.arg(out_path.join(format!("{}.a", lib_name)))
.arg(rclone_repo)
.status()?;
if !status.success() {
return Err("`go build` failed. Ensure Go is installed and up-to-date.".into());
}
println!("cargo:rustc-link-search=native={}", out_path.display());
println!("cargo:rustc-link-lib=static=rclone");
if target_triple.ends_with("darwin") {
for framework in &["CoreFoundation", "IOKit", "Security"] {
println!("cargo:rustc-link-lib=framework={}", framework);
}
println!("cargo:rustc-link-lib=resolv");
}
let bindings = bindgen::Builder::default()
.header(out_path.join(format!("{}.h", lib_name)).to_string_lossy())
.allowlist_function("RcloneRPC")
.allowlist_function("RcloneInitialize")
.allowlist_function("RcloneFinalize")
.allowlist_function("RcloneFreeString")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate()?;
let mut out_file = File::create(out_path.join("bindings.rs"))?;
writeln!(out_file, "//! Bindings generated by build.rs")?;
writeln!(out_file, "#![allow(missing_docs)]")?;
writeln!(out_file, "#![allow(non_upper_case_globals)]")?;
writeln!(out_file, "#![allow(non_camel_case_types)]")?;
writeln!(out_file, "#![allow(non_snake_case)]")?;
writeln!(out_file, "#![allow(clippy::all)]")?;
writeln!(out_file)?;
bindings.write(Box::new(out_file))?;
let mut makefile_buf = String::new();
makefile_buf.push_str("update:\n");
makefile_buf.push_str("\trm -f go.mod go.sum\n");
makefile_buf.push_str("\tgo mod init github.com/Its-Just-Nans/galion\n");
makefile_buf.push_str("\tgo mod tidy -go=1.24.4\n");
std::fs::write(out_path.join("Makefile"), makefile_buf)?;
Ok(())
}