logicng-open-wbo-sys 0.1.0-alpha.3

LogicNG Bindings for OpenWBO
Documentation
use std::path::{Path, PathBuf};
use std::{env, fs};

fn main() {
    println!("cargo:rerun-if-changed=src/lib.rs");
    println!("cargo:rerun-if-changed=open_wbo_wrapper/library.cpp");
    println!("cargo:rerun-if-changed=open_wbo_wrapper/include/library.h");

    let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
    let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
    let lib_name = format!("_{os}_{arch}_open_wbo");
    let lib_file_name = format!("lib{lib_name}.a");

    let open_wbo_path = std::path::Path::new("open_wbo/");
    let out_dir = env::var("OUT_DIR").expect("$OUT_DIR is not set");
    let operating_path = PathBuf::from(&out_dir);
    let lib_path = operating_path.join(lib_file_name);
    if !lib_path.exists() {
        build_open_wbo(open_wbo_path, &lib_path, &operating_path.join("logicng-open-wbo-src"), &os, &arch);
    }

    //Link OpenWBO Library
    println!("cargo:rustc-link-search={}", out_dir);
    println!("cargo:rustc-link-lib=static={lib_name}");

    //Link other stuff
    if os == "linux" {
        println!("cargo:rustc-link-lib=gmpxx");
        println!("cargo:rustc-link-lib=gmp");
    }

    //Build Bridge between OpenWBO Wrapper and LogicNG
    let mut build = cxx_build::bridge("src/lib.rs");
    build
        .include(open_wbo_path.join("include/"))
        .flag("-w") //Suppress warnings
        .file("open_wbo_wrapper/library.cpp");

    if os == "macos" && arch == "aarch64" {
        build.include("/opt/homebrew/include");
    }

    if build.get_compiler().is_like_clang() || build.get_compiler().is_like_gnu() {
        build.flag("-std=c++11");
    } else {
        build.flag("/std:c++14"); //MSVC doesn't support c++11, but c++14 should also work.
    };
    build.compile("open_wbo_wrapper");
}

fn build_open_wbo(open_wbo_path: &std::path::Path, lib_path: &std::path::Path, operating_path: &std::path::Path, os: &str, arch: &str) {
    let open_wbo_src_path = open_wbo_path.join("logicng-open-wbo");
    if !open_wbo_src_path.exists() {
        panic!("Cannot build OpenWBO, because the source code is missing.")
    }

    copy_src(&open_wbo_src_path, operating_path);

    //Building OpenWBO Library
    let mut make = std::process::Command::new("make");
    if os == "macos" && arch == "aarch64" {
        make.env("CPATH", "/opt/homebrew/include");
    }
    make.current_dir(operating_path).arg("libr");
    if let Err(e) = make.status() {
        panic!("Building OpenWBO failed with: {}", e);
    }
    let lib_src_path = operating_path.join("lib_release.a");
    if let Err(e) = std::fs::copy(lib_src_path, lib_path) {
        panic!("Building OpenWBO failed with: {}", e);
    }

    //Cleanup build files
    if let Err(e) = fs::remove_dir_all(operating_path) {
        panic!("Building OpenWBO failed with: {}", e)
    }
}

fn copy_src(src: &Path, dst: &Path) {
    fs::create_dir_all(dst).expect("Couldn't create root directory");
    for entry in fs::read_dir(src).expect("Couldn't read directory") {
        let entry = entry.expect("Couldn't read file");
        let ty = entry.file_type().expect("Couldn't access filetype");
        if ty.is_dir() {
            copy_src(&entry.path(), &dst.join(entry.file_name()));
        } else {
            fs::copy(entry.path(), dst.join(entry.file_name())).expect("Couldn't copy file");
        }
    }
}