use super::types::LinkerFamily;
pub(super) fn cross_platform_file_name(tool: &str) -> &str {
tool.rsplit(['/', '\\']).next().unwrap_or(tool)
}
pub(super) fn file_stem(filename: &str) -> &str {
match filename.rfind('.') {
Some(pos) if pos > 0 => &filename[..pos],
_ => filename,
}
}
pub(super) fn detect_family(tool: &str) -> Option<LinkerFamily> {
let full_name = cross_platform_file_name(tool);
let stem = file_stem(full_name);
if stem.eq_ignore_ascii_case("link") {
return Some(LinkerFamily::MsvcLink);
}
if full_name == "ld.lld"
|| full_name.starts_with("ld.lld-")
|| stem == "lld"
|| stem.starts_with("lld-")
|| stem == "wasm-ld"
{
return Some(LinkerFamily::Lld);
}
if full_name == "ld.bfd" || full_name == "ld.gold" || stem == "ld" || stem.ends_with("-ld") {
return Some(LinkerFamily::Ld);
}
None
}
pub(super) fn is_compiler_driver(tool: &str) -> bool {
let stem = file_stem(cross_platform_file_name(tool));
matches!(stem, "cc" | "c++" | "emcc" | "em++")
|| stem == "gcc"
|| stem == "g++"
|| stem.ends_with("-gcc")
|| stem.ends_with("-g++")
|| stem.contains("clang")
}
#[must_use]
pub fn is_linker(tool: &str) -> bool {
detect_family(tool).is_some()
}
#[must_use]
pub fn is_link_invocation(tool: &str, args: &[String]) -> bool {
if detect_family(tool).is_some() {
return true;
}
if !is_compiler_driver(tool) {
return false;
}
let expanded;
let effective_args = if args.iter().any(|a| a.starts_with('@') && a.len() > 1) {
expanded = super::super::response_file::expand_response_files(args).unwrap_or_default();
if expanded.is_empty() {
args
} else {
&expanded
}
} else {
args
};
if effective_args
.iter()
.any(|a| a == "-c" || a == "-E" || a == "-S" || a == "--precompile")
{
return false;
}
for pair in effective_args.windows(2) {
if pair[0] == "-x" {
if let Some(mode) = super::super::parse::source_mode_from_language(&pair[1]) {
if mode.implies_compilation() {
return false;
}
}
}
}
true
}