1 use std::env::consts::EXE_SUFFIX; 2 use std::path::PathBuf; 3 use std::process::Command; 4 use std::{env, process}; 5 6 use anyhow::Result; 7 8 use crate::rustc::rustlib; 9 10 #[derive(Clone, Copy, PartialEq)] 11 pub enum Tool { 12 Ar, 13 Cov, 14 Lld, 15 Nm, 16 Objcopy, 17 Objdump, 18 Profdata, 19 Readobj, 20 Size, 21 Strip, 22 } 23 24 impl Tool { name(self) -> &'static str25 pub fn name(self) -> &'static str { 26 match self { 27 Tool::Ar => "ar", 28 Tool::Cov => "cov", 29 Tool::Lld => "lld", 30 Tool::Nm => "nm", 31 Tool::Objcopy => "objcopy", 32 Tool::Objdump => "objdump", 33 Tool::Profdata => "profdata", 34 Tool::Readobj => "readobj", 35 Tool::Size => "size", 36 Tool::Strip => "strip", 37 } 38 } 39 exe(self) -> String40 pub fn exe(self) -> String { 41 match self { 42 Tool::Lld => format!("rust-lld{}", EXE_SUFFIX), 43 _ => format!("llvm-{}{}", self.name(), EXE_SUFFIX), 44 } 45 } 46 path(self) -> Result<PathBuf>47 pub fn path(self) -> Result<PathBuf> { 48 let mut path = rustlib()?; 49 path.push(self.exe()); 50 Ok(path) 51 } 52 53 /// Forwards execution to the specified tool. 54 /// If the tool fails to start or is not found this process exits with 55 /// status code 101 the same as if the process has a panic! rust_exec(self) -> !56 pub fn rust_exec(self) -> ! { 57 let path = match self.path() { 58 Err(e) => { 59 eprintln!("Failed to find tool: {}\n{}", self.name(), e); 60 process::exit(101) 61 } 62 Ok(p) => p, 63 }; 64 65 // Note: The first argument is the name of the binary (e.g. `rust-nm`) 66 let args = env::args().skip(1); 67 68 // Spawn the process and check if the process did spawn 69 let status = match Command::new(path).args(args).status() { 70 Err(e) => { 71 eprintln!("Failed to execute tool: {}\n{}", self.name(), e); 72 process::exit(101) 73 } 74 Ok(s) => s, 75 }; 76 77 // Forward the exit code from the tool 78 process::exit(status.code().unwrap_or(101)); 79 } 80 81 /// Parses arguments for `cargo $tool` and then if needed executes `cargo build` 82 /// before parsing the required arguments to `rust-$tool`. 83 /// If the tool fails to start or is not found this process exits with 84 /// status code 101 the same as if the process has a panic! cargo_exec(self, examples: Option<&str>) -> !85 pub fn cargo_exec(self, examples: Option<&str>) -> ! { 86 let matches = crate::args(self, examples); 87 88 match crate::run(self, matches) { 89 Err(e) => { 90 eprintln!("error: {}", e); 91 process::exit(101) 92 } 93 Ok(ec) => process::exit(ec), 94 } 95 } 96 97 // Whether this tool requires the project to be previously built needs_build(self) -> bool98 pub fn needs_build(self) -> bool { 99 match self { 100 Tool::Ar | Tool::Cov | Tool::Lld | Tool::Profdata => false, 101 Tool::Nm | Tool::Objcopy | Tool::Objdump | Tool::Readobj | Tool::Size | Tool::Strip => { 102 true 103 } 104 } 105 } 106 } 107