Skip to main content

debugger/setup/adapters/
gdb.rs

1//! GDB native DAP adapter installer
2//!
3//! Installs GDB with native DAP support (GDB ≥14.1).
4
5use 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}