1use std::env;
2use std::path::PathBuf;
3use std::process::Command;
4
5use serde::Deserialize;
6
7#[derive(Deserialize)]
8struct MetaData {
9 target_directory: PathBuf,
10}
11
12fn add_profile_dir(mut target_dir: PathBuf) -> PathBuf {
13 if cfg!(debug_assertions) {
14 target_dir.push("debug");
15 } else {
16 target_dir.push("release");
17 }
18 target_dir
19}
20
21fn primary_target_dir() -> PathBuf {
22 if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") {
24 let target_dir = add_profile_dir(PathBuf::from(target_dir));
25 if target_dir.is_dir() {
26 return target_dir;
27 };
28 }
29
30 env::current_exe()
32 .ok()
33 .map(|mut path| {
34 path.pop();
35 if path.ends_with("deps") || path.ends_with("examples") {
36 path.pop();
37 }
38 path
39 })
40 .unwrap()
41}
42
43fn cargo_inferred_target_dir() -> PathBuf {
44 let metadata = Command::new(env::var("CARGO").ok().unwrap_or_else(|| "cargo".into()))
45 .arg("metadata")
46 .output()
47 .unwrap();
48 let meta: MetaData = serde_json::from_slice(&metadata.stdout).unwrap();
49 add_profile_dir(meta.target_directory)
50}
51
52fn find_exe(name: &str) -> PathBuf {
53 let mut first = primary_target_dir();
54 first.push(name);
55 if first.is_file() {
56 return first;
57 }
58
59 let mut alt = cargo_inferred_target_dir();
60 alt.push(name);
61 if alt.is_file() {
62 return alt;
63 }
64 panic!("Cannot determine path to executable '{}'", name);
65}
66
67pub fn get_cargo_bin(name: &str) -> PathBuf {
69 let env_var = format!("CARGO_BIN_EXE_{}", name);
70 env::var_os(env_var)
71 .map(|p| p.into())
72 .unwrap_or_else(|| find_exe(&format!("{}{}", name, env::consts::EXE_SUFFIX)))
73}
74
75pub fn get_cargo_example(name: &str) -> PathBuf {
77 find_exe(&format!("examples/{}{}", name, env::consts::EXE_SUFFIX))
78}