1use std::path::Path;
8
9pub fn target_cpu() -> Result<Option<String>, String> {
17 if let Ok(force_override_cpu) = std::env::var("_DYLAN_RUST_TARGET_CPU_FORCE_OVERRIDE").map(|s| s.trim().to_owned()) {
20 if !force_override_cpu.is_empty() {
21 eprintln!("warning: force overriding CPU detection in crate '{}' to CPU '{}'",
22 env!("CARGO_PKG_NAME"), force_override_cpu);
23
24 return Ok(Some(force_override_cpu));
25 }
26 }
27
28 let target = if let Ok(target) = std::env::var("TARGET") {
29 target
30 } else {
31 return Err("cannot retrieve CPU name, please, pass --target flag to Cargo, e. g. \"--target atmega88pa.json\"".to_owned());
32 };
33
34 let target_json_relative_path = Path::new(&format!("{}.json", target)).to_owned();
35
36 let cpu_name = match parse_target_cpu_from_target_json(&target_json_relative_path) {
37 Some(target_cpu) => target_cpu,
38 None => {
39 eprintln!("[warning]: assuming a target CPU name of '{}' from the file name of the target spec JSON file", target);
45
46 if let Some(cpu_name) = target.strip_prefix("avr-unknown-gnu-"){
48 cpu_name.to_owned()
49 } else {
50 target
51 }
52 },
53 };
54
55 Ok(Some(cpu_name))
56}
57
58
59fn parse_target_cpu_from_target_json(possible_json_path: &Path)
60 -> Option<String> {
61 let json_content = match std::fs::read(possible_json_path) {
62 Ok(content) => String::from_utf8(content).unwrap(),
63 Err(..) => {
64 eprintln!("[warning]: cannot find target JSON file '{}' - due to limitations it needs to be in the crate root - is it?", possible_json_path.display());
65 return None;
66 },
67 };
68
69 let parsed = json::parse(&json_content).expect(&format!("failed to parse target JSON at '{}'", possible_json_path.display()));
70
71 match parsed {
72 json::JsonValue::Object(dict) => {
73 match dict.get("cpu") {
74 Some(target_cpu) => Some(target_cpu.as_str().expect("target CPU in JSON is not a string").to_owned()),
75 None => panic!("target specification file '{}' does not define a target CPU", possible_json_path.display()),
76 }
77 },
78 _ => None,
79 }
80}