use ::{BoxResult, PanicResult};
use ::{BuildMeta, CcFlag, CcFlags};
use ::std::path::Path;
use ::path_abs::{PathArc, PathDir, PathFile};
use ::walkdir::WalkDir;
const SUBMODULE_PATH: &'static str = "lammps";
pub(crate) fn build_from_source_and_link() -> PanicResult<BuildMeta> {
let lmp_dir = lammps_repo_dir_build_copy()?;
let mut cmake = ::cmake::Config::new(lammps_cmake_root()?);
let mut defines = CcFlags(vec![]);
let mut include_dirs = CcFlags(vec![]);
cmake.define("CMAKE_INSTALL_LIBDIR", "lib");
cmake.define("BUILD_LIB", "yes");
cmake.define("BUILD_SHARED_LIBS", "yes");
cmake.define("BUILD_EXE", "no");
for key in ::packages::cmake_flags_from_features() {
cmake.define(key, "yes");
}
cmake.define("CMAKE_RULE_MESSAGES:BOOL", "OFF");
cmake.define("CMAKE_VERBOSE_MAKEFILE:BOOL", "ON");
cmake.define("BUILD_MPI", match cfg!(feature = "mpi") {
true => "yes",
false => "no",
});
if cfg!(feature = "exceptions") {
cmake.define("LAMMPS_EXCEPTIONS", "yes");
defines.0.push(CcFlag::Define("LAMMPS_EXCEPTIONS".into()));
}
let lib_dir = PathDir::new(cmake.build())?;
println!("cargo:rustc-link-search=native={}/lib", lib_dir.display());
println!("cargo:rustc-link-lib=lammps");
include_dirs.0.push(CcFlag::IncludeDir(lmp_dir.into()));
Ok(BuildMeta {
header: "src/library.h",
include_dirs,
defines,
})
}
fn lammps_repo_dir_build_copy() -> BoxResult<PathDir> {
let src_dir = lammps_repo_dir();
let copy_path = ::env::out_dir().join("lammps");
if copy_path.exists() {
return Ok(PathDir::new(copy_path)?);
};
let copy = PathDir::create(::env::out_dir().join("lammps"))?;
let suffix = |entry: &walkdir::DirEntry| {
entry.path().strip_prefix(&src_dir).unwrap_or_else(|e| panic!("{}", e)).to_owned()
};
let walker = {
WalkDir::new(&src_dir)
.follow_links(true)
.into_iter()
.filter_entry(|entry| {
let blacklist = &[
Path::new("examples"),
Path::new("bench"),
Path::new("doc/src"),
Path::new("doc/util"),
Path::new("tools"),
Path::new("potentials"),
];
!blacklist.contains(&suffix(&entry).as_ref())
})
};
for entry in walker {
let entry = entry?;
let dest = copy.join(suffix(&entry));
let ty = entry.file_type();
if ty.is_file() {
PathFile::new(entry.path()).unwrap_or_else(|e| panic!("{}", e)).copy(dest)?;
} else if ty.is_dir() {
PathDir::create(dest)?;
}
}
PathDir::create(copy.join("potentials"))?;
Ok(copy)
}
pub(crate) fn lammps_repo_dir() -> PathDir {
let msg = "Could not find lammps submodule";
assert!(!PathArc::new(SUBMODULE_PATH).symlink_metadata().expect(msg).file_type().is_symlink());
PathDir::new(SUBMODULE_PATH).expect(msg)
}
pub(crate) fn lammps_dotgit_dir() -> BoxResult<Option<PathDir>> {
let path = lammps_repo_dir().join(".git");
if !path.exists() {
return Ok(None);
}
let mut path = path.canonicalize()?;
while path.is_file() {
let text = ::std::fs::read_to_string(&path)?;
let line = text.lines().next().expect("empty .git file!");
assert!(text.starts_with("gitdir:"));
let line = &line["gitdir:".len()..];
path = PathArc::new(path.parent().unwrap()).join(line.trim()).canonicalize()?;
}
Ok(Some(PathDir::new(path)?))
}
pub(crate) fn lammps_cmake_root() -> BoxResult<PathDir> {
let cmake_root = lammps_repo_dir_build_copy()?.join("cmake");
Ok(PathDir::new(cmake_root.canonicalize().map_err(|_| {
format!("could not resolve {:?}, you probably forgot to `git submodule update --init`", cmake_root)
})?)?)
}