trifid/nebula-ffi/build.rs

130 lines
3.7 KiB
Rust

use std::{env, process};
use std::path::PathBuf;
use bindgen::CargoCallbacks;
use std::path::Path;
fn main() {
// Find compiler:
// 1. GOC
// 2. /usr/local/go/bin/go
// 3. system "go"
let compiler = match env::var("GOC") {
Ok(c) => c,
Err(_) => {
if Path::new("/usr/local/go/bin/go").exists() {
"/usr/local/go/bin/go".to_string()
} else {
"go".to_string()
}
}
};
println!("using go compiler {}", compiler);
//gobuild::Build::new().compiler(compiler).buildmode(BuildMode::CArchive).file("main.go").compile("nebulaffi");
let c_compiler = cc::Build::new().try_get_compiler().unwrap();
let out_dir = env::var("OUT_DIR").unwrap();
let out_path = PathBuf::from(out_dir);
let out_file = LIBRARY_PREFIX.to_owned() + "nebula" + LIBRARY_EXTENSION;
let out = out_path.join(out_file);
let mut command = process::Command::new(compiler);
command.args(["build", "-buildmode", link_type().as_str(), "-o", out.display().to_string().as_str(), "main.go"]);
command.env("CGO_ENABLED", "1");
command.env("CC", c_compiler.path());
command.env("GOARCH", goarch());
command.env("GOOS", goos());
println!("running go compile command: {:?}", command);
let mut child = command.spawn().unwrap();
let status = child.wait().unwrap();
println!("{}", status);
if !status.success() {
panic!("`{:?}` exited with status code {}", command, status);
}
println!("Go compile success");
print_link();
println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
//let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
//println!("cargo:rustc-link-search={}", out_path.display());
println!("cargo:rerun-if-changed=go.mod");
println!("cargo:rerun-if-changed=go.sum");
println!("cargo:rerun-if-changed=main.go");
println!("Generating bindings");
let bindings = bindgen::Builder::default()
.header(out_path.join(LIBRARY_PREFIX.to_owned() + "nebula.h").display().to_string())
.parse_callbacks(Box::new(CargoCallbacks))
.generate()
.expect("Error generating CFFI bindings");
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
#[cfg(target_family = "unix")]
const LIBRARY_EXTENSION: & str = ".a";
#[cfg(target_family = "unix")]
const LIBRARY_PREFIX: & str = "lib";
#[cfg(target_family = "windows")]
const LIBRARY_EXTENSION: &str = ".dll";
#[cfg(target_family = "windows")]
const LIBRARY_PREFIX: &str = "";
fn goarch() -> String {
match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() {
"x86" => "386",
"x86_64" => "amd64",
"mips" => "mips",
"powerpc" => "ppc",
"powerpc64" => "ppc64",
"arm" => "arm",
"aarch64" => "arm64",
arch => panic!("unsupported architecture {arch}")
}.to_string()
}
fn goos() -> String {
match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() {
"windows" => "windows",
"macos" => "darwin",
"ios" => "darwin",
"linux" => "linux",
"android" => "android",
"freebsd" => "freebsd",
"dragonfly" => "dragonfly",
"openbsd" => "openbsd",
"netbsd" => "netbsd",
os => panic!("unsupported operating system {os}")
}.to_string()
}
#[cfg(target_family = "unix")]
fn print_link() {
println!("cargo:rustc-link-lib=static=nebula");
}
#[cfg(target_family = "unix")]
fn link_type() -> String {
"c-archive".to_string()
}
#[cfg(target_family = "windows")]
fn print_link() {
println!("cargo:rustc-link-lib=dylib=nebula");
}
#[cfg(target_family = "windows")]
fn link_type() -> String {
"c-shared".to_string()
}