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))]
49 pub entrypoint: Option<String>,
50 #[arg(
52 long = "search-path",
53 short = 'L',
54 value_name = "PATH",
55 help_heading = "Linker"
56 )]
57 pub search_path: Vec<PathBuf>,
58 #[arg(
69 long = "link-library",
70 short = 'l',
71 value_name = "[KIND=]NAME",
72 value_delimiter = ',',
73 next_line_help(true),
74 help_heading = "Linker"
75 )]
76 pub link_libraries: Vec<LinkLibrary>,
77}
78
79impl Debugger {
80 pub fn new_session<I, A, S>(inputs: I, emitter: Option<Arc<dyn Emitter>>, argv: A) -> Session
82 where
83 I: IntoIterator<Item = InputFile>,
84 A: IntoIterator<Item = S>,
85 S: Into<OsString> + Clone,
86 {
87 let argv = [OsString::from("run")]
88 .into_iter()
89 .chain(argv.into_iter().map(|arg| arg.into()));
90 let mut matches = <Self as clap::CommandFactory>::command()
91 .try_get_matches_from(argv)
92 .unwrap_or_else(|err| err.exit());
93
94 let opts = <Self as clap::FromArgMatches>::from_arg_matches_mut(&mut matches)
95 .map_err(format_error::<Self>)
96 .unwrap_or_else(|err| err.exit());
97
98 let inputs = inputs.into_iter().collect();
99 opts.into_session(inputs, emitter)
100 }
101
102 pub fn into_session(
104 self,
105 inputs: Vec<InputFile>,
106 emitter: Option<Arc<dyn Emitter>>,
107 ) -> Session {
108 let cwd = self
109 .working_dir
110 .unwrap_or_else(|| std::env::current_dir().expect("no working directory available"));
111
112 let color = match self.color {
114 ColorChoice::Auto => MDColorChoice::Auto,
115 ColorChoice::Always => MDColorChoice::Always,
116 ColorChoice::Never => MDColorChoice::Never,
117 };
118
119 let mut options = Options::new(None, self.target, ProjectType::Program, cwd, self.sysroot)
121 .with_color(color);
122 options.search_paths = self.search_path;
123
124 let link_libraries = add_target_link_libraries(self.link_libraries, &self.target);
125 options.link_libraries = link_libraries;
126
127 options.entrypoint = self.entrypoint;
128
129 let target_dir = std::env::temp_dir();
130 let source_manager = Arc::new(DefaultSourceManager::default());
131 Session::new(inputs, None, None, target_dir, options, emitter, source_manager)
132 }
133}
134
135fn format_error<I: clap::CommandFactory>(err: clap::Error) -> clap::Error {
136 let mut cmd = I::command();
137 err.format(&mut cmd)
138}