1use std::env;
2use std::ffi::OsStr;
3use std::path::{Path, PathBuf};
4
5pub(crate) enum TargetDir {
6 Path(PathBuf),
7 Unknown,
8}
9
10pub(crate) fn find_target_dir(out_dir: &Path) -> TargetDir {
11 if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") {
12 let target_dir = PathBuf::from(target_dir);
13 if target_dir.is_absolute() {
14 return TargetDir::Path(target_dir);
15 } else {
16 return TargetDir::Unknown;
17 };
18 }
19
20 let mut also_try_canonical = cfg!(not(windows));
25
26 let mut dir = out_dir.to_owned();
27 loop {
28 if dir.join(".rustc_info.json").exists()
29 || dir.join("CACHEDIR.TAG").exists()
30 || dir.file_name() == Some(OsStr::new("target"))
31 && dir
32 .parent()
33 .is_some_and(|parent| parent.join("Cargo.toml").exists())
34 {
35 return TargetDir::Path(dir);
36 }
37 if dir.pop() {
38 continue;
39 }
40 if also_try_canonical {
41 if let Ok(canonical_dir) = out_dir.canonicalize() {
42 dir = canonical_dir;
43 also_try_canonical = false;
44 continue;
45 }
46 }
47 return TargetDir::Unknown;
48 }
49}