Skip to content

Commit 4f7c45b

Browse files
committed
feat(cargo): add feature flags for optional heavy dependencies
- Make wasmtime, ssh2, and image optional dependencies behind feature flags (wasm-extensions, remote-ssh, image-processing) - All features enabled by default for backward compatibility - Replace tokio 'full' with explicit feature list - Add #[cfg] gates throughout codebase with stub fallbacks - Add dev profile settings for faster debug builds
1 parent 4cd813e commit 4f7c45b

File tree

14 files changed

+414
-84
lines changed

14 files changed

+414
-84
lines changed

src-tauri/Cargo.toml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ serde_json = "1"
3232
rmp-serde = "1"
3333

3434
# Async runtime
35-
tokio = { version = "1", features = ["full"] }
35+
tokio = { version = "1", features = ["rt-multi-thread", "sync", "time", "io-util", "net", "fs", "process", "macros"] }
3636
async-channel = "2"
3737
futures = "0.3"
3838

@@ -46,7 +46,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
4646

4747
# Utilities
4848
open = "5"
49-
ssh2 = "0.9"
49+
ssh2 = { version = "0.9", optional = true }
5050
uuid = { version = "1", features = ["v4"] }
5151
once_cell = "1"
5252
dirs = "5"
@@ -87,7 +87,7 @@ git2 = "0.19"
8787
zip = "0.6"
8888

8989
# WASM extension runtime
90-
wasmtime = { version = "29", features = ["cranelift"] }
90+
wasmtime = { version = "29", features = ["cranelift"], optional = true }
9191

9292
# File encoding
9393
encoding_rs = "0.8"
@@ -101,7 +101,7 @@ libc = "0.2"
101101
# MCP support
102102
interprocess = { version = "2.2", features = ["tokio"] }
103103
enigo = "0.3"
104-
image = "0.24"
104+
image = { version = "0.24", optional = true }
105105

106106
# Note: plist and wry are provided by tauri and don't need direct dependencies
107107

@@ -141,8 +141,15 @@ tauri-plugin-deep-link = "2.4"
141141
tempfile = "3"
142142

143143
[features]
144-
default = ["custom-protocol"]
144+
default = ["custom-protocol", "wasm-extensions", "remote-ssh", "image-processing"]
145145
custom-protocol = ["tauri/custom-protocol"]
146+
wasm-extensions = ["dep:wasmtime"]
147+
remote-ssh = ["dep:ssh2"]
148+
image-processing = ["dep:image"]
149+
150+
[profile.dev]
151+
opt-level = 0
152+
debug = 2
146153

147154
[profile.dev.package."*"]
148155
opt-level = 2

src-tauri/src/app/mod.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ pub fn register_state(
396396
builder: tauri::Builder<tauri::Wry>,
397397
remote_manager: Arc<RemoteManager>,
398398
) -> tauri::Builder<tauri::Wry> {
399-
builder
399+
let builder = builder
400400
.manage(ServerState(Arc::new(Mutex::new(None))))
401401
.manage(LogState(Arc::new(Mutex::new(VecDeque::new()))))
402402
.manage(PortState(Arc::new(Mutex::new(0))))
@@ -438,7 +438,6 @@ pub fn register_state(
438438
.manage(crate::themes::ThemeState::new())
439439
.manage(crate::keybindings::KeybindingsState::new())
440440
.manage(crate::wsl::WSLState::new())
441-
.manage(crate::ssh_terminal::SSHTerminalState::new())
442441
.manage(crate::rules_library::RulesWatcherState::new())
443442
.manage(LazyState::new(crate::testing::TestWatcherState::new))
444443
.manage(LazyState::new(crate::factory::FactoryState::new))
@@ -458,7 +457,12 @@ pub fn register_state(
458457
.manage(LazyState::new(SandboxState::new))
459458
.manage(crate::remote::tunnel::TunnelState::new())
460459
.manage(crate::git::forge::ForgeState::new())
461-
.manage(LazyState::new(CollabState::new))
460+
.manage(LazyState::new(CollabState::new));
461+
462+
#[cfg(feature = "remote-ssh")]
463+
let builder = builder.manage(crate::ssh_terminal::SSHTerminalState::new());
464+
465+
builder
462466
}
463467

464468
// ===== Setup =====
@@ -676,9 +680,12 @@ pub fn handle_run_event(app: &AppHandle, event: RunEvent) {
676680
let _ = terminal_state.close_all(app);
677681
info!("All terminals closed on app exit");
678682

679-
let ssh_state = app.state::<crate::ssh_terminal::SSHTerminalState>();
680-
let _ = ssh_state.close_all(app);
681-
info!("All SSH sessions closed on app exit");
683+
#[cfg(feature = "remote-ssh")]
684+
{
685+
let ssh_state = app.state::<crate::ssh_terminal::SSHTerminalState>();
686+
let _ = ssh_state.close_all(app);
687+
info!("All SSH sessions closed on app exit");
688+
}
682689

683690
let lsp_state = app.state::<LspState>();
684691
let _ = lsp_state.stop_all_servers();
@@ -731,8 +738,16 @@ pub fn handle_run_event(app: &AppHandle, event: RunEvent) {
731738
{
732739
let ext_state = app.state::<LazyState<ExtensionsState>>();
733740
let manager = ext_state.get().0.lock();
734-
manager.wasm_runtime.unload_all();
735-
info!("WASM extension runtime stopped on app exit");
741+
#[cfg(feature = "wasm-extensions")]
742+
{
743+
manager.wasm_runtime.unload_all();
744+
info!("WASM extension runtime stopped on app exit");
745+
}
746+
#[cfg(not(feature = "wasm-extensions"))]
747+
{
748+
drop(manager);
749+
info!("WASM extension runtime not enabled, skipping cleanup");
750+
}
736751
}
737752

738753
{

src-tauri/src/app/terminal_commands.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#[cfg(feature = "remote-ssh")]
12
#[macro_export]
23
macro_rules! terminal_commands {
34
(@commands $callback:ident [ $($acc:tt)* ]) => {
@@ -50,3 +51,42 @@ macro_rules! terminal_commands {
5051
])
5152
};
5253
}
54+
55+
#[cfg(not(feature = "remote-ssh"))]
56+
#[macro_export]
57+
macro_rules! terminal_commands {
58+
(@commands $callback:ident [ $($acc:tt)* ]) => {
59+
$callback!([ $($acc)*
60+
// Terminal PTY commands
61+
$crate::terminal::commands::terminal_create,
62+
$crate::terminal::commands::terminal_write,
63+
$crate::terminal::commands::terminal_update,
64+
$crate::terminal::commands::terminal_resize,
65+
$crate::terminal::commands::terminal_close,
66+
$crate::terminal::commands::terminal_list,
67+
$crate::terminal::commands::terminal_get,
68+
$crate::terminal::commands::terminal_send_interrupt,
69+
$crate::terminal::commands::terminal_send_eof,
70+
$crate::terminal::commands::terminal_ack,
71+
$crate::terminal::commands::terminal_close_all,
72+
$crate::terminal::commands::terminal_get_default_shell,
73+
// Port management commands
74+
$crate::terminal::commands::get_process_on_port,
75+
$crate::terminal::commands::kill_process_on_port,
76+
$crate::terminal::commands::list_listening_ports,
77+
// Shell detection commands
78+
$crate::terminal::commands::terminal_detect_shells,
79+
$crate::terminal::commands::path_exists,
80+
$crate::terminal::commands::terminal_detect_links,
81+
$crate::terminal::commands::terminal_search,
82+
$crate::terminal::commands::terminal_parse_shell_integration,
83+
$crate::terminal::commands::terminal_strip_sequences,
84+
// Terminal profiles commands
85+
$crate::terminal::profiles::terminal_profiles_list,
86+
$crate::terminal::profiles::terminal_profiles_save,
87+
$crate::terminal::profiles::terminal_profiles_delete,
88+
$crate::terminal::profiles::terminal_profiles_get,
89+
$crate::terminal::profiles::terminal_profiles_set_default,
90+
])
91+
};
92+
}

src-tauri/src/app/tests.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ fn state_types_are_send_sync() {
3434
assert_send_sync::<crate::LazyState<crate::sandbox::commands::SandboxState>>();
3535
assert_send_sync::<crate::testing::TestWatcherState>();
3636
assert_send_sync::<crate::LazyState<crate::testing::TestWatcherState>>();
37+
#[cfg(feature = "remote-ssh")]
3738
assert_send_sync::<crate::ssh_terminal::SSHTerminalState>();
3839
assert_send_sync::<crate::wsl::WSLState>();
3940
}
@@ -64,6 +65,7 @@ fn state_initialization_does_not_panic() {
6465
let _ = crate::extensions::activation::ActivationState::new();
6566
let _ = crate::extensions::registry::RegistryState::new();
6667
let _ = crate::testing::TestWatcherState::new();
68+
#[cfg(feature = "remote-ssh")]
6769
let _ = crate::ssh_terminal::SSHTerminalState::new();
6870
let _ = crate::wsl::WSLState::new();
6971
}

src-tauri/src/extensions/commands.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -146,22 +146,30 @@ pub async fn update_extension(app: AppHandle, name: String, version: String) ->
146146
/// Get activation time metrics for all loaded WASM extensions.
147147
#[tauri::command]
148148
pub async fn get_activation_time_metrics(app: AppHandle) -> Result<Vec<serde_json::Value>, String> {
149-
let state = app.state::<LazyState<ExtensionsState>>();
150-
let manager = state.get().0.lock();
151-
let states = manager.wasm_runtime.get_states();
152-
let metrics: Vec<serde_json::Value> = states
153-
.into_iter()
154-
.map(|s| {
155-
serde_json::json!({
156-
"id": s.id,
157-
"status": s.status,
158-
"activationTime": s.activation_time,
159-
"error": s.error,
160-
"lastActivity": s.last_activity,
149+
#[cfg(feature = "wasm-extensions")]
150+
{
151+
let state = app.state::<LazyState<ExtensionsState>>();
152+
let manager = state.get().0.lock();
153+
let states = manager.wasm_runtime.get_states();
154+
let metrics: Vec<serde_json::Value> = states
155+
.into_iter()
156+
.map(|s| {
157+
serde_json::json!({
158+
"id": s.id,
159+
"status": s.status,
160+
"activationTime": s.activation_time,
161+
"error": s.error,
162+
"lastActivity": s.last_activity,
163+
})
161164
})
162-
})
163-
.collect();
164-
Ok(metrics)
165+
.collect();
166+
Ok(metrics)
167+
}
168+
#[cfg(not(feature = "wasm-extensions"))]
169+
{
170+
let _ = app;
171+
Ok(Vec::new())
172+
}
165173
}
166174

167175
/// Update all installed extensions that have available updates.

src-tauri/src/extensions/contributions.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,17 +183,25 @@ pub async fn execute_extension_command(
183183
command: String,
184184
args: Option<Vec<serde_json::Value>>,
185185
) -> Result<serde_json::Value, String> {
186-
let state = app.state::<LazyState<ExtensionsState>>();
187-
let mut manager = state.get().0.lock();
186+
#[cfg(feature = "wasm-extensions")]
187+
{
188+
let state = app.state::<LazyState<ExtensionsState>>();
189+
let mut manager = state.get().0.lock();
188190

189-
let args_json = serde_json::to_string(&args.unwrap_or_default())
190-
.map_err(|e| format!("Failed to serialize args: {}", e))?;
191+
let args_json = serde_json::to_string(&args.unwrap_or_default())
192+
.map_err(|e| format!("Failed to serialize args: {}", e))?;
191193

192-
let result = manager
193-
.wasm_runtime
194-
.execute_command(&extension_id, &command, &args_json)?;
194+
let result = manager
195+
.wasm_runtime
196+
.execute_command(&extension_id, &command, &args_json)?;
195197

196-
serde_json::from_str(&result).unwrap_or(Ok(serde_json::Value::String(result)))
198+
serde_json::from_str(&result).unwrap_or(Ok(serde_json::Value::String(result)))
199+
}
200+
#[cfg(not(feature = "wasm-extensions"))]
201+
{
202+
let _ = (app, extension_id, command, args);
203+
Err("WASM extensions feature is not enabled".to_string())
204+
}
197205
}
198206

199207
// ============================================================================

src-tauri/src/extensions/state.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use tracing::{info, warn};
1212

1313
use super::types::{Extension, ExtensionManifest, ExtensionSource};
1414
use super::utils::{copy_dir_recursive, extensions_directory_path};
15+
#[cfg(feature = "wasm-extensions")]
1516
use super::wasm::WasmRuntime;
1617

1718
/// State for managing extensions
@@ -26,7 +27,7 @@ pub struct ExtensionsManager {
2627
pub extensions_dir: PathBuf,
2728
/// Enabled extensions (persisted)
2829
pub enabled_extensions: HashMap<String, bool>,
29-
/// WASM extension runtime
30+
#[cfg(feature = "wasm-extensions")]
3031
pub wasm_runtime: WasmRuntime,
3132
}
3233

@@ -44,6 +45,7 @@ impl ExtensionsManager {
4445
extensions: HashMap::new(),
4546
extensions_dir,
4647
enabled_extensions: HashMap::new(),
48+
#[cfg(feature = "wasm-extensions")]
4749
wasm_runtime: WasmRuntime::new(),
4850
}
4951
}
@@ -147,8 +149,10 @@ impl ExtensionsManager {
147149

148150
/// Uninstall an extension
149151
pub fn uninstall_extension(&mut self, name: &str) -> Result<(), String> {
150-
// Unload from WASM runtime if loaded
151-
let _ = self.wasm_runtime.unload_extension(name);
152+
#[cfg(feature = "wasm-extensions")]
153+
{
154+
let _ = self.wasm_runtime.unload_extension(name);
155+
}
152156

153157
if let Some(ext) = self.extensions.remove(name) {
154158
fs::remove_dir_all(&ext.path)

0 commit comments

Comments
 (0)