pdb_wrapper 0.2.2

Rust library to create fake PDBs. Very in-dev, API is likely to break a lot (not including the frequent LLVM API breakages...)
use cmake::Config;
use std::{env, path::PathBuf};
use std::process::Command;
    use which::which;

#[cfg(all(feature = "llvm_10", feature = "llvm_13"))]
compile_error!("You may only enable one LLVM version");

#[cfg(feature = "llvm_10")]
const LLVM_VERSION: u32 = 10;

#[cfg(feature = "llvm_13")]
const LLVM_VERSION: u32 = 13;

fn version_specific_init() {
    // TODO: Does this work as expected on Windows?
    let binary = which("llvm-config")
        .expect("llvm-config was not found, please make sure that it's contained in your PATH!");

    // Get required libraries from `llvm-config`
    let result = Command::new(binary)
        .arg("--libnames")
        .arg("DebugInfoPDB")
        .output()
        .expect("Failed to run `llvm-config`");

    let result = String::from_utf8(result.stdout).expect("Failed to parse `llvm-config` output!");
    if cfg!(unix) {
        result
            .trim()
            .replace(".a", "")
            .replace(".so", "")
            .split_whitespace()
            .map(|lib| lib.trim())
            .filter_map(|lib| lib.strip_prefix("lib"))
            .filter(|lib| !lib.is_empty())
            .for_each(|lib| {
                println!("cargo:rustc-link-lib={}", lib);
            });
    } else if cfg!(windows) {
        result
            .trim()
            .replace(".lib", "")
            .split_whitespace()
            .map(|lib| lib.trim())
            .filter(|lib| !lib.is_empty())
            .for_each(|lib| {
                println!("cargo:rustc-link-lib={}", lib);
            });
    }

}

fn main() {
    let dst = Config::new("libllvm-pdb-wrapper").build();
    println!("cargo:rustc-link-search=native={}", dst.display());
    println!("cargo:rerun-if-changed={}", dst.display());

    println!("cargo:rustc-link-lib=static=llvm-pdb-wrapper");
    println!("cargo:rustc-link-lib=llvm-pdb-wrapper");

    version_specific_init();

    if cfg!(unix) {
        println!("cargo:rustc-link-lib=ncurses");
        println!("cargo:rustc-link-lib=z");
        println!("cargo:rustc-link-lib=stdc++");
    } else if cfg!(windows) {
        println!("cargo:rustc-link-lib=zlib");
    }

    println!("cargo:rerun-if-changed=libllvm-pdb-wrapper/wrapper.hpp");
    println!("cargo:rerun-if-changed=libllvm-pdb-wrapper/wrapper.cpp");

    let bindings = bindgen::Builder::default()
        // The input header we would like to generate
        // bindings for.
        .header("libllvm-pdb-wrapper/wrapper.hpp")
        .clang_arg(format!("-DLLVM_VERSION_MAJOR={}", LLVM_VERSION))
        .whitelist_function("PDB_File_.*")
        // Tell cargo to invalidate the built crate whenever any of the
        // included header files changed.
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        // Finish the builder and generate the bindings.
        .generate()
        // Unwrap the Result and panic on failure.
        .expect("Unable to generate bindings");
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}