use std::env;
use std::path::PathBuf;
use std::process::Command;
fn python_link() {
let windows = env::var("CARGO_CFG_WINDOWS").is_ok();
if env::var("CARGO_CFG_UNIX").is_err() && !windows {
return;
}
let default_python = if windows { "python" } else { "python3" };
let python = env::var("LIBYTDLP_PYTHON").unwrap_or_else(|_| default_python.to_owned());
if windows {
let output = Command::new(&python)
.args([
"-c",
"import os, sys; print(os.path.join(sys.base_prefix, 'libs')); print('python%d%d.lib' % sys.version_info[:2])",
])
.output();
let output = match output {
Ok(output) if output.status.success() => output,
_ => return,
};
let text = String::from_utf8_lossy(&output.stdout);
let mut lines = text.lines();
if let (Some(libdir), Some(file)) = (lines.next(), lines.next()) {
let stem = file.strip_suffix(".lib").unwrap_or(file);
println!("cargo:rustc-link-search=native={libdir}");
println!("cargo:rustc-link-lib={stem}");
}
return;
}
let output = Command::new(&python)
.args([
"-c",
"import sysconfig; print(sysconfig.get_config_var('LIBDIR')); print('python' + sysconfig.get_config_var('LDVERSION'))",
])
.output();
let output = match output {
Ok(output) if output.status.success() => output,
_ => return,
};
let text = String::from_utf8_lossy(&output.stdout);
let mut lines = text.lines();
if let (Some(libdir), Some(lib)) = (lines.next(), lines.next()) {
println!("cargo:rustc-link-search=native={libdir}");
println!("cargo:rustc-link-lib={lib}");
println!("cargo:rustc-link-arg=-Wl,-rpath,{libdir}");
}
}
fn system_lib_dir() -> Option<PathBuf> {
if env::var("CARGO_CFG_WINDOWS").is_ok() {
let path = env::var_os("PATH")?;
for dir in env::split_paths(&path) {
for name in ["ytdlp.lib", "ytdlp_static.lib"] {
if dir.join(name).exists() {
return Some(dir);
}
}
}
return None;
}
if env::var("CARGO_CFG_UNIX").is_err() {
return None;
}
for dir in [
"/usr/lib",
"/usr/lib64",
"/usr/local/lib",
"/usr/local/lib64",
] {
for name in ["libytdlp.so", "libytdlp.dylib", "libytdlp.a"] {
if PathBuf::from(dir).join(name).exists() {
return Some(PathBuf::from(dir));
}
}
}
None
}
fn main() {
println!("cargo:rerun-if-env-changed=LIBYTDLP_LIB_DIR");
println!("cargo:rerun-if-env-changed=LIBYTDLP_LINK");
println!("cargo:rerun-if-env-changed=LIBYTDLP_PYTHON");
let windows = env::var("CARGO_CFG_WINDOWS").is_ok();
let static_name = if windows {
"ytdlp_static.lib"
} else {
"libytdlp.a"
};
let link_name = "ytdlp";
let static_link_name = if windows { "ytdlp_static" } else { "ytdlp" };
let dir = env::var("LIBYTDLP_LIB_DIR")
.ok()
.map(PathBuf::from)
.or_else(system_lib_dir);
let Some(dir) = dir else {
panic!(
"libytdlp native library not found: install it system-wide \
or set LIBYTDLP_LIB_DIR to the directory holding libytdlp.so, libytdlp.a \
(ytdlp.lib or ytdlp_static.lib on Windows)"
);
};
let link = env::var("LIBYTDLP_LINK").unwrap_or_default();
let want_shared = link == "shared";
let have_static = dir.join(static_name).exists();
if link == "static" && !have_static {
panic!(
"LIBYTDLP_LINK=static but no {} in {}",
static_name,
dir.display()
);
}
println!("cargo:rustc-link-search=native={}", dir.display());
if env::var("CARGO_CFG_UNIX").is_ok() {
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", dir.display());
}
if have_static && !want_shared {
println!("cargo:rerun-if-changed={}/{}", dir.display(), static_name);
println!("cargo:rustc-link-lib=static={static_link_name}");
if env::var("CARGO_CFG_UNIX").is_ok() {
let runtime = match env::var("CARGO_CFG_TARGET_OS").as_deref() {
Ok("macos") => "c++",
_ => "stdc++",
};
println!("cargo:rustc-link-lib={runtime}");
}
python_link();
} else {
println!("cargo:rustc-link-lib={link_name}");
}
}