llm_devices/
target_dir.rs

1use std::path::{Path, PathBuf};
2
3/// Resolves the Cargo target directory path.
4///
5/// This function attempts to find the target directory through multiple methods:
6/// 1. Checks the `CARGO_TARGET_DIR` environment variable
7/// 2. Traverses up from the `OUT_DIR` to find a 'target' directory
8/// 3. Traverses up from `CARGO_MANIFEST_DIR` to find a 'target' directory
9/// 4. Falls back to using the compile-time `CARGO_MANIFEST_DIR`
10///
11/// This helps resolve issues with cargo workspace target directory resolution
12/// (see https://github.com/rust-lang/cargo/issues/9661).
13///
14/// # Returns
15///
16/// * `Result<PathBuf>` - Path to the cargo target directory if found
17///
18/// # Errors
19///
20/// Returns an error if unable to locate the target directory through any method.
21///
22pub fn get_target_directory() -> crate::Result<PathBuf> {
23    // First, check CARGO_TARGET_DIR environment variable
24    if let Ok(target_dir) = std::env::var("CARGO_TARGET_DIR") {
25        return Ok(PathBuf::from(target_dir));
26    }
27    // Next, check OUT_DIR and traverse up to find 'target'
28    if let Ok(out_dir) = std::env::var("OUT_DIR") {
29        if let Some(target_dir) = find_target_in_ancestors(&PathBuf::from(out_dir)) {
30            return Ok(target_dir);
31        }
32    }
33
34    // If that fails, check CARGO_MANIFEST_DIR and traverse up to find 'target'
35    if let Ok(manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") {
36        if let Some(target_dir) = find_target_in_ancestors(&PathBuf::from(manifest_dir)) {
37            return Ok(target_dir);
38        }
39    }
40
41    // As a last resort, use the compile-time CARGO_MANIFEST_DIR
42    let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
43    match find_target_in_ancestors(&manifest_dir) {
44        Some(target_dir) => Ok(target_dir),
45        None => crate::bail!(
46            "Could not find target directory in ancestors of {}",
47            manifest_dir.display()
48        ),
49    }
50}
51
52fn find_target_in_ancestors(start_dir: &Path) -> Option<PathBuf> {
53    start_dir
54        .ancestors()
55        .find(|path| path.join("target").is_dir())
56        .map(|path| path.join("target"))
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_target_directory() {
65        let result = get_target_directory();
66        assert!(result.is_ok());
67        assert!(result.unwrap().ends_with("target"));
68    }
69}