extern crate autotools;
extern crate bindgen;
use std::{
env, fs,
path::{Path, PathBuf},
process::Command,
};
fn check_installed(name: &str) -> anyhow::Result<()> {
let check = Command::new(name).arg("--version").output();
match check {
Ok(output) => {
if !output.status.success() {
return Err(anyhow::anyhow!(
"{} is required, but it's not installed or not in PATH.",
name
));
}
}
Err(_) => {
return Err(anyhow::anyhow!(
"{} is required, but it's not installed or not in PATH.",
name
));
}
}
Ok(())
}
fn main() -> anyhow::Result<()> {
check_installed("autoconf")?;
check_installed("automake")?;
let out_dir = env::var("OUT_DIR").map(PathBuf::from)?;
let src_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("jq");
let build_dir = out_dir.join("jq_build");
if build_dir.exists() {
fs::remove_dir_all(&build_dir)?;
}
fs::create_dir(&build_dir)?;
for entry in walkdir::WalkDir::new(&src_dir) {
let entry = entry?;
let target_path = build_dir.join(entry.path().strip_prefix(&src_dir)?);
if entry.file_type().is_dir() {
fs::create_dir_all(target_path)?;
} else {
fs::copy(entry.path(), target_path)?;
}
}
let lexer_src = src_dir.join("src/lexer.c");
let lexer_target = build_dir.join("src/lexer.c");
fs::copy(lexer_src, lexer_target)?;
let parser_src = src_dir.join("src/parser.c");
let parser_target = build_dir.join("src/parser.c");
fs::copy(parser_src, parser_target)?;
autotools::Config::new(&build_dir)
.reconf("-i")
.out_dir(&out_dir)
.with("oniguruma", Some("builtin"))
.make_args(vec![
"CPPFLAGS=-D_REENTRANT".into(),
])
.build();
let lib_dir = out_dir.join("lib");
println!("cargo:rustc-link-search=native={}", lib_dir.display());
for lib in &["onig", "jq"] {
println!("cargo:rustc-link-lib=static={}", lib);
}
let bindings = bindgen::Builder::default()
.header("jq/src/jq.h")
.generate()?;
bindings.write_to_file(out_dir.join("bindings.rs"))?;
Ok(())
}