use std::fs;
use std::path::PathBuf;
use std::{env, path::Path};
fn main() {
let out_dir_path = PathBuf::from(env::var("OUT_DIR").expect("Cannot find OUT_DIR"));
#[cfg(feature = "rebuild")]
let out_dir_path_rebuild = out_dir_path.clone();
let quest_library_path = build_with_cc(out_dir_path);
println!(
"cargo:rustc-link-search=native={}",
quest_library_path.display()
);
println!("cargo:rustc-link-lib=static=QuEST");
println!("cargo:rerun-if-changed=wrapper.h");
#[cfg(feature = "rebuild")]
let builder = bindgen::Builder::default()
.header("wrapper.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.allowlist_function("copyStateFromGPU")
.allowlist_function("copyStateToPU")
.allowlist_function("create.*")
.allowlist_function("cloneQureg")
.allowlist_function("destroy.*")
.allowlist_function("report.*")
.allowlist_function("get.*")
.allowlist_function("set.*")
.allowlist_function("setComplexMatrixN")
.allowlist_function("initStateFromAmps")
.allowlist_function("report.*")
.allowlist_function("rotate.*")
.allowlist_function("report.*")
.allowlist_function("controlled.*")
.allowlist_function("report.*")
.allowlist_function("multiControlled.*")
.allowlist_function("report.*")
.allowlist_function("pauli.*")
.allowlist_function("report.*")
.allowlist_function("init.*")
.allowlist_function("report.*")
.allowlist_function("mix.*")
.allowlist_function("sGate")
.allowlist_function("tGate")
.allowlist_function("phaseShift")
.allowlist_function("compactUnitary")
.allowlist_function("apply.*")
.allowlist_function("hadamard*")
.allowlist_function("swapGate")
.allowlist_function("unitary")
.allowlist_function("twoQubitUnitary")
.allowlist_function("multiQubitUnitary")
.allowlist_function("measure")
.allowlist_function("statevec_twoQubitUnitary")
.allowlist_function("calc.*")
.allowlist_function("seedQuEST");
#[cfg(feature = "rebuild")]
let bindings = builder.generate().expect("Unable to generate bindings");
#[cfg(feature = "rebuild")]
bindings
.write_to_file(out_dir_path_rebuild.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
fn build_with_cc(out_dir: PathBuf) -> PathBuf {
let base_path = Path::new("QuEST").join("QuEST");
let src_path = base_path.join("src");
let include_path = base_path.join("include");
let mut files = vec![
src_path.join("QuEST.c"),
src_path.join("QuEST_common.c"),
src_path.join("QuEST_qasm.c"),
src_path.join("QuEST_validation.c"),
src_path.join("mt19937ar.c"),
];
let out_path = out_dir.join("build");
fs::create_dir_all(out_path.clone()).expect("Cannot create directory for x86_64 library");
#[cfg(not(feature = "cuda"))]
#[cfg(not(feature = "cuquantum"))]
{
files.push(src_path.join("CPU").join("QuEST_cpu.c"));
files.push(src_path.join("CPU").join("QuEST_cpu_local.c"));
#[cfg(target_arch = "x86_64")]
cc::Build::new()
.include(src_path)
.include(include_path)
.files(files)
.define("MULTITHREADED", "0")
.opt_level(2)
.debug(false)
.warnings(false)
.static_flag(true)
.out_dir(out_path.clone())
.flag("-std=c99")
.flag("-mavx")
.compile("QuEST");
#[cfg(not(target_arch = "x86_64"))]
cc::Build::new()
.include(src_path)
.include(include_path)
.files(files)
.define("MULTITHREADED", "0")
.opt_level(2)
.debug(false)
.warnings(false)
.static_flag(true)
.out_dir(out_path.clone())
.flag("-std=c99")
.compile("QuEST");
}
#[cfg(feature = "cuda")]
{
if cfg!(feature = "cuquantum") {
panic!("cuQuantum feature is different from CUDA feature. Choose one.");
}
files.push(src_path.join("GPU").join("QuEST_gpu.cu"));
files.push(src_path.join("GPU").join("QuEST_gpu_common.cu"));
cc::Build::new()
.include(src_path.clone())
.include(include_path.clone())
.files(files.clone())
.define("MULTITHREADED", "0")
.define("USE_HID", "0")
.opt_level(2)
.debug(false)
.warnings(false)
.out_dir(out_path.clone())
.cuda(true)
.compile("QuEST");
}
#[cfg(feature = "cuquantum")]
{
if cfg!(feature = "cuda") {
panic!("cuQuantum feature is different from CUDA feature. Choose one.");
}
let custate_include_lib = PathBuf::from(
env::var("CUSTATE_INCLUDE_DIR")
.expect("Cannot find CUSTATE_INCLUDE_DIR. Needs to be given explicitely."),
);
println!("cargo:rustc-link-lib=custatevec");
files.push(src_path.join("GPU").join("QuEST_cuQuantum.cu"));
files.push(src_path.join("GPU").join("QuEST_gpu_common.cu"));
cc::Build::new()
.include(src_path)
.include(include_path)
.include(custate_include_lib)
.files(files)
.define("MULTITHREADED", "0")
.define("USE_CUQUANTUM", "1")
.define("USE_HID", "0")
.opt_level(2)
.debug(false)
.warnings(false)
.out_dir(out_path.clone())
.cuda(true)
.compile("QuEST");
}
out_path
}