blob: 4c9a9f3d5bb08a686cd7b05a1fa15e3bb67ae43f [file] [log] [blame]
use std::env;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
pub(crate) enum TargetDir {
Path(PathBuf),
Unknown,
}
pub(crate) fn find_target_dir(out_dir: &Path) -> TargetDir {
if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") {
let target_dir = PathBuf::from(target_dir);
if target_dir.is_absolute() {
return TargetDir::Path(target_dir);
} else {
return TargetDir::Unknown;
};
}
// fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
// handle in includes.
// https://github.com/rust-lang/rust/issues/42869
// https://github.com/alexcrichton/cc-rs/issues/169
let mut also_try_canonical = cfg!(not(windows));
let mut dir = out_dir.to_owned();
loop {
if dir.join(".rustc_info.json").exists()
|| dir.join("CACHEDIR.TAG").exists()
|| dir.file_name() == Some(OsStr::new("target"))
&& dir
.parent()
.map_or(false, |parent| parent.join("Cargo.toml").exists())
{
return TargetDir::Path(dir);
}
if dir.pop() {
continue;
}
if also_try_canonical {
if let Ok(canonical_dir) = out_dir.canonicalize() {
dir = canonical_dir;
also_try_canonical = false;
continue;
}
}
return TargetDir::Unknown;
}
}