• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::env;
2 use std::ffi::OsStr;
3 use std::path::{Path, PathBuf};
4 
5 pub(crate) enum TargetDir {
6     Path(PathBuf),
7     Unknown,
8 }
9 
find_target_dir(out_dir: &Path) -> TargetDir10 pub(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     // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
21     // handle in includes.
22     // https://github.com/rust-lang/rust/issues/42869
23     // https://github.com/alexcrichton/cc-rs/issues/169
24     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                     .map_or(false, |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 }
50