use crate::plat::dist::{PlatDist, plat_dist};
use crate::xpath::path::path_to_string;
use std::env;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
#[derive(Default, Debug, PartialEq, Eq, Clone)]
pub struct DevPath {
pub include: PathBuf,
pub lib: PathBuf,
}
impl DevPath {
pub fn get_shared(&self) -> Vec<PathBuf> {
let mut netca_libs = Vec::new();
if let Ok(paths) = std::fs::read_dir(&self.lib) {
for path in paths.flatten() {
let path = path.path();
if path.is_file() && path.extension() == Some(get_dist_lib_suffix().as_ref()) {
netca_libs.push(path);
}
}
}
netca_libs
}
pub fn include(&self) -> &PathBuf {
&self.include
}
pub fn lib(&self) -> &PathBuf {
&self.lib
}
}
pub fn watch<Paths>(path: Paths) -> PathBuf
where
Paths: AsRef<std::path::Path>,
{
if path.as_ref().exists() {
println!("cargo:rerun-if-changed={}", path.as_ref().join("*").display());
}
path.as_ref().to_path_buf()
}
pub fn watch_env<K>(k: K) -> anyhow::Result<String>
where
K: AsRef<OsStr>,
{
println!("cargo::rerun-if-env-changed={}", path_to_string(k.as_ref()));
let value = env::var(k)?;
Ok(value)
}
fn get_dist_lib_name() -> String {
match plat_dist() {
PlatDist::Rh => "lib64",
PlatDist::Debian => "lib",
PlatDist::Other => "lib",
}
.to_string()
}
fn get_dist_lib_suffix() -> String {
if cfg!(target_os = "linux") {
"so".to_string()
} else if cfg!(target_os = "windows") {
"dll".to_string()
} else {
panic!("unkown os")
}
}
pub fn lib_path_of_root<Paths>(lib_root: Paths) -> PathBuf
where
Paths: AsRef<std::path::Path>,
{
let p = Path::new(lib_root.as_ref());
let lib_must = p.join(get_dist_lib_name());
let lib_alt = if lib_must.ends_with("64") { "lib" } else { "lib64" };
let path = if lib_must.exists() { lib_must } else { p.join(lib_alt) };
watch(path)
}
pub fn include_path_of_root<Paths>(lib_root: Paths) -> PathBuf
where
Paths: AsRef<std::path::Path>,
{
let path = lib_root.as_ref().join("include");
watch(path)
}
pub fn dev_path_of_root<Paths>(lib_root: Paths) -> DevPath
where
Paths: AsRef<std::path::Path>,
{
DevPath {
include: include_path_of_root(&lib_root),
lib: lib_path_of_root(lib_root),
}
}
pub fn dev_path_of_root_env_or<K>(lib_root_key: K, default: DevPath) -> DevPath
where
K: AsRef<OsStr>,
{
match watch_env(lib_root_key) {
Err(_) => default,
Ok(lib_root) => dev_path_of_root(lib_root),
}
}
pub fn dev_path_of_root_env<K>(lib_root_key: K) -> DevPath
where
K: AsRef<OsStr>,
{
dev_path_of_root_env_or(lib_root_key, DevPath::default())
}
pub fn cargo_profile_dir() -> PathBuf {
PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
}
pub fn cargo_root_profile_dir() -> PathBuf {
cargo_target_dir().parent().unwrap().to_path_buf()
}
pub fn cargo_target_dir() -> PathBuf {
let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
let mut target_dir = None;
let mut sub_path = out_dir.as_path();
while let Some(parent) = sub_path.parent() {
if parent.ends_with("target") {
target_dir = Some(parent);
break;
}
sub_path = parent;
}
let target_dir = target_dir.unwrap();
target_dir.to_path_buf()
}
pub fn cargo_target_bin_dir() -> PathBuf {
let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
let profile = std::env::var("PROFILE").unwrap();
let mut target_dir = None;
let mut sub_path = out_dir.as_path();
while let Some(parent) = sub_path.parent() {
if parent.ends_with(&profile) {
target_dir = Some(parent);
break;
}
sub_path = parent;
}
let target_dir = target_dir.unwrap();
target_dir.to_path_buf()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_case_lib_path_of_root() {
match plat_dist() {
PlatDist::Rh => assert_eq!(
lib_path_of_root(PathBuf::from("/noexist")),
PathBuf::from("/noexist/lib")
),
PlatDist::Debian => assert_eq!(
lib_path_of_root(PathBuf::from("/noexist")),
PathBuf::from("/noexist/lib64")
),
PlatDist::Other => {},
};
if cfg!(target_os = "windows") {
assert_eq!(
lib_path_of_root(
r#"D:\code\thirdlib\EaxLibrary\EaxComponent\gb_media\build\gb-media\thirdlib\ffmpeg\"#
),
PathBuf::from(
r#"D:\code\thirdlib\EaxLibrary\EaxComponent\gb_media\build\gb-media\thirdlib\ffmpeg\lib"#
)
);
}
if cfg!(target_os = "linux") {
println!("fuck you ");
let catch_root = "/workspace/cyberex/thirdlib/ffmpeg";
let catch_lib = "/workspace/cyberex/thirdlib/ffmpeg/lib";
let catch_include = "/workspace/cyberex/thirdlib/ffmpeg/include";
assert_eq!(lib_path_of_root(catch_root), PathBuf::from(catch_lib));
assert_eq!(include_path_of_root(catch_root), PathBuf::from(catch_include));
let dev_path = dev_path_of_root(catch_root);
assert_eq!(dev_path.lib.display().to_string(), catch_lib);
assert_eq!(dev_path.include.display().to_string(), catch_include);
assert_eq!(
{
let mut v = dev_path.get_shared();
v.sort();
v
},
{
let mut v = Vec::from([
PathBuf::from("/workspace/cyberex/thirdlib/ffmpeg/lib/libavformat.so"),
PathBuf::from("/workspace/cyberex/thirdlib/ffmpeg/lib/libavutil.so"),
PathBuf::from("/workspace/cyberex/thirdlib/ffmpeg/lib/libavfilter.so"),
PathBuf::from("/workspace/cyberex/thirdlib/ffmpeg/lib/libavcodec.so"),
PathBuf::from("/workspace/cyberex/thirdlib/ffmpeg/lib/libswscale.so"),
PathBuf::from("/workspace/cyberex/thirdlib/ffmpeg/lib/libswresample.so"),
PathBuf::from("/workspace/cyberex/thirdlib/ffmpeg/lib/libavdevice.so"),
]);
v.sort();
v
}
);
let env_var = "FUCKYOU_ROOT";
unsafe { std::env::set_var(env_var, "/workspace/cyberex/thirdlib/catch2") };
let dev_path = dev_path_of_root_env(env_var);
assert_eq!(
dev_path.lib.display().to_string(),
"/workspace/cyberex/thirdlib/catch2/lib"
);
assert_eq!(
dev_path.include.display().to_string(),
"/workspace/cyberex/thirdlib/catch2/include"
);
let dev_path = dev_path_of_root_env("noexist");
assert_eq!(dev_path, DevPath::default());
}
}
#[test]
fn test_dev_path_of_root_env() {
let env_var = "NO_SET_ENV";
let default_value = DevPath {
include: "fuck".into(),
lib: "you".into(),
};
let dev_path = dev_path_of_root_env_or(env_var, default_value.clone());
assert!(dev_path == default_value);
}
#[test]
fn test_cargo_target_dir() {
let moc_out_dir = "/workspace/cyberex/target/debug/build/a_test_dir/out";
std::fs::create_dir_all(moc_out_dir).unwrap();
unsafe { std::env::set_var("OUT_DIR", moc_out_dir) };
unsafe { std::env::set_var("PROFILE", "debug") };
assert_eq!(cargo_target_bin_dir(), PathBuf::from("/workspace/cyberex/target/debug"));
assert_eq!(cargo_target_dir(), PathBuf::from("/workspace/cyberex/target"));
assert_eq!(cargo_profile_dir(), PathBuf::from("/workspace/cyberex/crates/cyberex"));
assert_eq!(cargo_root_profile_dir(), PathBuf::from("/workspace/cyberex"));
}
}