moore-circt-sys 0.14.0

Low-level language bindings to CIRCT.
// Copyright (c) 2016-2021 Fabian Schuiki

use std::env;
use std::path::PathBuf;

fn main() {
    static ENV_CIRCT_DIR: &str = "CIRCT_SYS_CIRCT_DIR";
    static ENV_CIRCT_BUILD_DIR: &str = "CIRCT_SYS_CIRCT_BUILD_DIR";
    static ENV_LLVM_DIR: &str = "CIRCT_SYS_LLVM_DIR";
    static ENV_LLVM_BUILD_DIR: &str = "CIRCT_SYS_LLVM_BUILD_DIR";

    println!("cargo:rerun-if-env-changed={}", &*ENV_CIRCT_DIR);
    println!("cargo:rerun-if-env-changed={}", &*ENV_CIRCT_BUILD_DIR);
    println!("cargo:rerun-if-env-changed={}", &*ENV_LLVM_DIR);
    println!("cargo:rerun-if-env-changed={}", &*ENV_LLVM_BUILD_DIR);

    let circt_dir = PathBuf::from(env::var(ENV_CIRCT_DIR).unwrap());
    let circt_build_dir = env::var(ENV_CIRCT_BUILD_DIR)
        .map(PathBuf::from)
        .unwrap_or_else(|_| circt_dir.join("build"));
    let llvm_dir = env::var(ENV_LLVM_DIR)
        .map(PathBuf::from)
        .unwrap_or_else(|_| circt_dir.join("llvm"));
    let llvm_build_dir = env::var(ENV_LLVM_BUILD_DIR)
        .map(PathBuf::from)
        .unwrap_or_else(|_| llvm_dir.join("build"));

    // CIRCT/LLVM/MLIR libraries
    let lib_dirs = [circt_build_dir.join("lib"), llvm_build_dir.join("lib")];
    let lib_names = [
        "CIRCTCAPIComb",
        "CIRCTCAPIHW",
        "CIRCTCAPILLHD",
        "CIRCTCAPISV",
        "CIRCTCAPISeq",
        "CIRCTComb",
        "CIRCTHW",
        "CIRCTLLHD",
        "CIRCTSV",
        "CIRCTSeq",
        "LLVMBinaryFormat",
        "LLVMBitstreamReader",
        "LLVMCore",
        "LLVMRemarks",
        "LLVMSupport",
        "MLIRAnalysis",
        "MLIRArithmetic",
        "MLIRCAPIIR",
        "MLIRCAPIStandard",
        "MLIRCallInterfaces",
        "MLIRControlFlowInterfaces",
        "MLIRIR",
        "MLIRInferTypeOpInterface",
        "MLIRPDL",
        "MLIRPDLInterp",
        "MLIRPDLToPDLInterp",
        "MLIRParser",
        "MLIRPass",
        "MLIRRewrite",
        "MLIRSideEffectInterfaces",
        "MLIRStandard",
        "MLIRSupport",
        "MLIRTransformUtils",
        "MLIRTransforms",
        "MLIRTranslation",
    ];
    for name in &lib_dirs {
        println!("cargo:rustc-link-search=native={}", name.display());
    }
    for name in &lib_names {
        println!("cargo:rustc-link-lib=static={}", name);
    }
    for lib_dir in &lib_dirs {
        for name in &lib_names {
            let path = lib_dir.join(format!("lib{}.a", name));
            if path.exists() {
                println!("cargo:rerun-if-changed={}", path.display());
            }
        }
    }

    // System libraries
    let system_libraries = [
        "stdc++", // llvm-config --system-libs --link-static
        "rt", "dl", "pthread", "m", "z", "tinfo",
    ];
    for name in &system_libraries {
        println!("cargo:rustc-link-lib=dylib={}", name);
    }

    // Make a list of include directories.
    let include_dirs = vec![
        circt_dir.join("include").display().to_string(),
        circt_build_dir.join("include").display().to_string(),
        llvm_dir.join("llvm/include").display().to_string(),
        llvm_dir.join("mlir/include").display().to_string(),
        llvm_build_dir.join("include").display().to_string(),
        llvm_build_dir
            .join("tools/mlir/include")
            .display()
            .to_string(),
    ];

    // Bindings
    println!("cargo:rerun-if-changed=wrapper.h");
    let mut bindings = bindgen::Builder::default().header("wrapper.h");
    for dir in &include_dirs {
        bindings = bindings.clang_arg("-I").clang_arg(dir);
    }
    let bindings = bindings
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        .generate()
        .expect("Unable to generate bindings");

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");

    // Additional wrapper code
    println!("cargo:rerun-if-changed=wrapper.cpp");
    cc::Build::new()
        .cpp(true)
        .file("wrapper.cpp")
        .includes(&include_dirs)
        .warnings(false)
        .extra_warnings(false)
        .compile("circt-sys-wrapper");
}