debugger/setup/adapters/
gdb.rs1use crate::common::{Error, Result};
6use crate::setup::installer::{InstallMethod, InstallOptions, InstallResult, InstallStatus, Installer};
7use crate::setup::registry::{DebuggerInfo, Platform};
8use crate::setup::verifier::{verify_dap_adapter, VerifyResult};
9use async_trait::async_trait;
10
11use super::gdb_common::{get_gdb_version, is_gdb_version_sufficient};
12
13static INFO: DebuggerInfo = DebuggerInfo {
14 id: "gdb",
15 name: "GDB",
16 languages: &["c", "cpp"],
17 platforms: &[Platform::Linux, Platform::MacOS, Platform::Windows],
18 description: "GDB native DAP adapter",
19 primary: true,
20};
21
22pub struct GdbInstaller;
23
24#[async_trait]
25impl Installer for GdbInstaller {
26 fn info(&self) -> &DebuggerInfo {
27 &INFO
28 }
29
30 async fn status(&self) -> Result<InstallStatus> {
31 if let Ok(path) = which::which("gdb") {
32 match get_gdb_version(&path).await {
33 Some(version) if is_gdb_version_sufficient(&version) => {
34 return Ok(InstallStatus::Installed {
35 path,
36 version: Some(version),
37 });
38 }
39 Some(version) => {
40 return Ok(InstallStatus::Broken {
41 path,
42 reason: format!(
43 "GDB version {} found, but ≥14.1 required for native DAP support",
44 version
45 ),
46 });
47 }
48 None => {
49 return Ok(InstallStatus::Broken {
50 path,
51 reason: "Could not determine GDB version".to_string(),
52 });
53 }
54 }
55 }
56
57 Ok(InstallStatus::NotInstalled)
58 }
59
60 async fn best_method(&self) -> Result<InstallMethod> {
61 if let Ok(path) = which::which("gdb") {
62 if let Some(version) = get_gdb_version(&path).await {
63 if is_gdb_version_sufficient(&version) {
64 return Ok(InstallMethod::AlreadyInstalled { path });
65 }
66 }
67 }
68
69 Ok(InstallMethod::NotSupported {
70 reason: "GDB ≥14.1 not found. Install via your system package manager.".to_string(),
71 })
72 }
73
74 async fn install(&self, _opts: InstallOptions) -> Result<InstallResult> {
75 let method = self.best_method().await?;
76
77 match method {
78 InstallMethod::AlreadyInstalled { path } => {
79 let version = get_gdb_version(&path).await;
80 Ok(InstallResult {
81 path,
82 version,
83 args: vec!["-i=dap".to_string()],
84 })
85 }
86 InstallMethod::NotSupported { reason } => {
87 Err(Error::Internal(format!("Cannot install GDB: {}", reason)))
88 }
89 _ => Err(Error::Internal("Unexpected installation method".to_string())),
90 }
91 }
92
93 async fn uninstall(&self) -> Result<()> {
94 println!("GDB is a system package. Use your package manager to uninstall.");
95 Ok(())
96 }
97
98 async fn verify(&self) -> Result<VerifyResult> {
99 let status = self.status().await?;
100
101 match status {
102 InstallStatus::Installed { path, .. } => {
103 verify_dap_adapter(&path, &["-i=dap".to_string()]).await
104 }
105 InstallStatus::Broken { reason, .. } => Ok(VerifyResult {
106 success: false,
107 capabilities: None,
108 error: Some(reason),
109 }),
110 InstallStatus::NotInstalled => Ok(VerifyResult {
111 success: false,
112 capabilities: None,
113 error: Some("Not installed".to_string()),
114 }),
115 }
116 }
117}