133d722a9Sopenharmony_ciuse std::env;
233d722a9Sopenharmony_ciuse std::ffi::OsStr;
333d722a9Sopenharmony_ciuse std::path::{Path, PathBuf};
433d722a9Sopenharmony_ci
533d722a9Sopenharmony_cipub(crate) enum TargetDir {
633d722a9Sopenharmony_ci    Path(PathBuf),
733d722a9Sopenharmony_ci    Unknown,
833d722a9Sopenharmony_ci}
933d722a9Sopenharmony_ci
1033d722a9Sopenharmony_cipub(crate) fn find_target_dir(out_dir: &Path) -> TargetDir {
1133d722a9Sopenharmony_ci    if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") {
1233d722a9Sopenharmony_ci        let target_dir = PathBuf::from(target_dir);
1333d722a9Sopenharmony_ci        if target_dir.is_absolute() {
1433d722a9Sopenharmony_ci            return TargetDir::Path(target_dir);
1533d722a9Sopenharmony_ci        } else {
1633d722a9Sopenharmony_ci            return TargetDir::Unknown;
1733d722a9Sopenharmony_ci        };
1833d722a9Sopenharmony_ci    }
1933d722a9Sopenharmony_ci
2033d722a9Sopenharmony_ci    // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
2133d722a9Sopenharmony_ci    // handle in includes.
2233d722a9Sopenharmony_ci    // https://github.com/rust-lang/rust/issues/42869
2333d722a9Sopenharmony_ci    // https://github.com/alexcrichton/cc-rs/issues/169
2433d722a9Sopenharmony_ci    let mut also_try_canonical = cfg!(not(windows));
2533d722a9Sopenharmony_ci
2633d722a9Sopenharmony_ci    let mut dir = out_dir.to_owned();
2733d722a9Sopenharmony_ci    loop {
2833d722a9Sopenharmony_ci        if dir.join(".rustc_info.json").exists()
2933d722a9Sopenharmony_ci            || dir.join("CACHEDIR.TAG").exists()
3033d722a9Sopenharmony_ci            || dir.file_name() == Some(OsStr::new("target"))
3133d722a9Sopenharmony_ci                && dir
3233d722a9Sopenharmony_ci                    .parent()
3333d722a9Sopenharmony_ci                    .map_or(false, |parent| parent.join("Cargo.toml").exists())
3433d722a9Sopenharmony_ci        {
3533d722a9Sopenharmony_ci            return TargetDir::Path(dir);
3633d722a9Sopenharmony_ci        }
3733d722a9Sopenharmony_ci        if dir.pop() {
3833d722a9Sopenharmony_ci            continue;
3933d722a9Sopenharmony_ci        }
4033d722a9Sopenharmony_ci        if also_try_canonical {
4133d722a9Sopenharmony_ci            if let Ok(canonical_dir) = out_dir.canonicalize() {
4233d722a9Sopenharmony_ci                dir = canonical_dir;
4333d722a9Sopenharmony_ci                also_try_canonical = false;
4433d722a9Sopenharmony_ci                continue;
4533d722a9Sopenharmony_ci            }
4633d722a9Sopenharmony_ci        }
4733d722a9Sopenharmony_ci        return TargetDir::Unknown;
4833d722a9Sopenharmony_ci    }
4933d722a9Sopenharmony_ci}
50