const CPP_VERSION_FLAG: &str = "-std=c++17";
fn main() {
if std::env::var("DOCS_RS").is_ok() {
return;
}
env_logger::init();
let use_conda = std::env::var("CARGO_FEATURE_DYNAMIC_LINKING_FROM_CONDA").is_ok();
let mut lib_paths = vec![];
let mut include_paths = vec![];
match (std::env::consts::OS, std::env::consts::ARCH, use_conda) {
(_, _, true) => {
match std::env::var("CONDA_PREFIX") {
Ok(prefix) => {
include_paths.push(format!("{prefix}/include"));
include_paths.push(format!("{prefix}/include/rdkit"));
lib_paths.push(format!("{prefix}/lib"));
}
Err(_) => {
let conda = which::which("conda")
.map(|p| p.to_str().unwrap().to_string())
.unwrap_or_else(|_| panic!("conda not found"));
let mut conda = std::process::Command::new(conda);
conda.args(["info", "--base"]);
let output = conda.output().unwrap();
let stdout = String::from_utf8(output.stdout).unwrap();
let conda_root = stdout.trim().to_string();
lib_paths.push(format!("{}/lib", conda_root));
include_paths.push(format!("{}/include", conda_root));
include_paths.push(format!("{}/include/rdkit", conda_root));
}
}
}
("macos", "x86_64", _) => {
include_paths.push("/usr/local/include".to_string());
include_paths.push("/usr/local/include/rdkit".to_string());
}
("macos", "aarch64", _) => {
include_paths.push("/opt/homebrew/include".to_string());
include_paths.push("/opt/homebrew/include/rdkit".to_string());
lib_paths.push("/opt/homebrew/lib".to_string())
}
("linux", _, _) => {
include_paths.push("/usr/local/include".to_string());
include_paths.push("/usr/local/include/rdkit".to_string());
include_paths.push("/usr/include".to_string());
include_paths.push("/usr/include/rdkit".to_string());
}
(unsupported_os, unsupported_arch, use_conda) => panic!(
"sorry, rdkit-sys doesn't support {}/{}/use_conda={} at this time",
unsupported_os, unsupported_arch, use_conda
),
};
let dir = std::fs::read_dir("src/bridge").unwrap();
let rust_files = dir
.into_iter()
.filter_map(|p| match p {
Ok(p) => {
if p.metadata().unwrap().is_file() {
Some(p.path())
} else {
None
}
}
Err(_) => None,
})
.filter(|p| !p.ends_with("mod.rs"))
.collect::<Vec<_>>();
let mut wrapper_cc_paths = vec![];
let wrapper_root = std::path::PathBuf::from("wrapper");
for file in &rust_files {
let file_name = file.file_name().unwrap();
let file_name = file_name.to_str().unwrap();
let base_name = &file_name[0..file_name.len() - 3];
let cc_path = wrapper_root.join("src").join(format!("{}.cc", base_name));
let meta = std::fs::metadata(&cc_path).unwrap();
if !meta.is_file() {
panic!("{} must exist", cc_path.display())
}
println!("cargo:rerun-if-changed={}", cc_path.to_str().unwrap());
wrapper_cc_paths.push(cc_path);
let h_path = wrapper_root
.join("include")
.join(format!("{}.h", base_name));
let meta = std::fs::metadata(&h_path)
.unwrap_or_else(|_| panic!("could not get metadata for {h_path:?}"));
if !meta.is_file() {
panic!("{} must exist", h_path.display())
}
println!("cargo:rerun-if-changed={}", h_path.to_str().unwrap());
}
cxx_build::bridges(rust_files)
.files(wrapper_cc_paths)
.includes(include_paths)
.include(std::env::var("CARGO_MANIFEST_DIR").unwrap())
.flag(CPP_VERSION_FLAG)
.warnings(false)
.compile("rdkit");
for path in lib_paths {
println!("cargo:rustc-link-search=native={}", path);
}
for lib in &[
"DataStructs",
"Descriptors",
"FileParsers",
"Fingerprints",
"GraphMol",
"MolStandardize",
"RDGeneral",
"ScaffoldNetwork",
"SmilesParse",
"SubstructMatch",
] {
println!("cargo:rustc-link-lib=dylib=RDKit{}", lib);
}
println!("cargo:rustc-link-lib=dylib=boost_serialization");
}