cxx_build/target.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
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()
.is_some_and(|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;
}
}