ipasir-sys 0.1.1

A Rust crate that contains FFI bindings for IPASIR-compatible SAT solvers.
use bindgen::Builder;
use copy_dir::copy_dir;

use std::env;
use std::fs::{copy, remove_dir_all};
use std::path::Path;
use std::process::Command;

fn main() {
    let build = Build::new();

    build.generate_bindings();

    if let Ok(ipasir) = env::var("IPASIR") {
        build.copy_existing_library(ipasir);
    }

    if !build.static_library_exists() {
        build.remove_cadical_dir();
        build.copy_cadical_dir();

        build.configure_cadical();
        build.make_cadical();

        build.copy_cadical_library();
        build.remove_cadical_dir();
    }

    println!("cargo:rustc-link-search={}", build.out_dir);
    println!("cargo:rustc-link-lib=static=ipasir");

    println!("cargo:rustc-link-search=/usr/local/lib");
    println!("cargo:rustc-link-lib=static=stdc++");
}

struct Build {
    pub out_dir: String,
}

impl Build {
    fn new() -> Self {
        Self { out_dir: env::var("OUT_DIR").unwrap() }
    }

    fn generate_bindings(&self) {
        Builder::default()
            .header("vendor/ipasir/ipasir.h").generate().unwrap()
            .write_to_file(format!("{}/bindings.rs", self.out_dir)).unwrap();
    }

    fn static_library_exists(&self) -> bool {
        Path::new(&format!("{}/libipasir.a", self.out_dir)).exists()
    }

    fn remove_cadical_dir(&self) {
        let _ = remove_dir_all(format!("{}/cadical", self.out_dir));
    }

    fn copy_cadical_dir(&self) {
        copy_dir("vendor/cadical", format!("{}/cadical", self.out_dir)).unwrap();
    }

    fn configure_cadical(&self) {
        Command::new("./configure")
            .arg("-fPIC")
            .env("CXX", "/usr/local/bin/g++")
            .current_dir(format!("{}/cadical", self.out_dir))
            .spawn().unwrap().wait().unwrap();
    }

    fn make_cadical(&self) {
        Command::new("make")
            .current_dir(format!("{}/cadical/build", self.out_dir))
            .spawn().unwrap().wait().unwrap();
    }

    fn copy_cadical_library(&self) {
        copy(
            format!("{}/cadical/build/libcadical.a", self.out_dir),
            format!("{}/libipasir.a", self.out_dir)
        ).unwrap();
    }

    fn copy_existing_library(&self, ipasir: String) {
        copy(ipasir, format!("{}/libipasir.a", self.out_dir)).unwrap();
    }
}