1use std::{ffi::OsString, path::PathBuf, sync::Arc};
2
3use clap::{ColorChoice, Parser};
4use midenc_session::{
5 add_target_link_libraries,
6 diagnostics::{DefaultSourceManager, Emitter},
7 ColorChoice as MDColorChoice, InputFile, LinkLibrary, Options, ProjectType, Session, TargetEnv,
8};
9
10#[derive(Default, Debug, Parser)]
12#[command(name = "debug")]
13pub struct Debugger {
14 #[arg(long, value_name = "DIR", help_heading = "Output")]
18 pub working_dir: Option<PathBuf>,
19 #[arg(
23 long,
24 value_name = "DIR",
25 env = "MIDENC_SYSROOT",
26 help_heading = "Compiler"
27 )]
28 pub sysroot: Option<PathBuf>,
29 #[arg(
31 long,
32 value_enum,
33 default_value_t = ColorChoice::Auto,
34 default_missing_value = "auto",
35 num_args(0..=1),
36 help_heading = "Diagnostics"
37 )]
38 pub color: ColorChoice,
39 #[arg(
41 long,
42 value_name = "TARGET",
43 default_value_t = TargetEnv::Base,
44 help_heading = "Compiler"
45 )]
46 pub target: TargetEnv,
47 #[arg(long, help_heading = "Compiler", hide(true))]
50 pub entrypoint: Option<String>,
51 #[arg(
53 long = "search-path",
54 short = 'L',
55 value_name = "PATH",
56 help_heading = "Linker"
57 )]
58 pub search_path: Vec<PathBuf>,
59 #[arg(
70 long = "link-library",
71 short = 'l',
72 value_name = "[KIND=]NAME",
73 value_delimiter = ',',
74 next_line_help(true),
75 help_heading = "Linker"
76 )]
77 pub link_libraries: Vec<LinkLibrary>,
78}
79
80impl Debugger {
81 pub fn new_session<I, A, S>(inputs: I, emitter: Option<Arc<dyn Emitter>>, argv: A) -> Session
83 where
84 I: IntoIterator<Item = InputFile>,
85 A: IntoIterator<Item = S>,
86 S: Into<OsString> + Clone,
87 {
88 let argv = [OsString::from("run")]
89 .into_iter()
90 .chain(argv.into_iter().map(|arg| arg.into()));
91 let mut matches = <Self as clap::CommandFactory>::command()
92 .try_get_matches_from(argv)
93 .unwrap_or_else(|err| err.exit());
94
95 let opts = <Self as clap::FromArgMatches>::from_arg_matches_mut(&mut matches)
96 .map_err(format_error::<Self>)
97 .unwrap_or_else(|err| err.exit());
98
99 let inputs = inputs.into_iter().collect();
100 opts.into_session(inputs, emitter)
101 }
102
103 pub fn into_session(
105 self,
106 inputs: Vec<InputFile>,
107 emitter: Option<Arc<dyn Emitter>>,
108 ) -> Session {
109 let cwd = self
110 .working_dir
111 .unwrap_or_else(|| std::env::current_dir().expect("no working directory available"));
112
113 let color = match self.color {
115 ColorChoice::Auto => MDColorChoice::Auto,
116 ColorChoice::Always => MDColorChoice::Always,
117 ColorChoice::Never => MDColorChoice::Never,
118 };
119
120 let mut options = Options::new(None, self.target, ProjectType::Program, cwd, self.sysroot)
122 .with_color(color);
123 options.search_paths = self.search_path;
124
125 let link_libraries = add_target_link_libraries(self.link_libraries, &self.target);
126 options.link_libraries = link_libraries;
127
128 options.entrypoint = self.entrypoint;
129
130 let target_dir = std::env::temp_dir();
131 let source_manager = Arc::new(DefaultSourceManager::default());
132 Session::new(inputs, None, None, target_dir, options, emitter, source_manager)
133 }
134}
135
136fn format_error<I: clap::CommandFactory>(err: clap::Error) -> clap::Error {
137 let mut cmd = I::command();
138 err.format(&mut cmd)
139}