Skip to content

Commit 242f1de

Browse files
cursoragentechobt
andcommitted
fix(plugins): make example plugins compile on edition 2024
Isolate the example crates with an empty [workspace] table so they build outside the CLI workspace. Use unsafe extern blocks and #[unsafe(no_mangle)] so hello-world and code-stats compile on Rust 1.98 / edition 2024 after dropping wee_alloc. Co-authored-by: Mathis <echobt@users.noreply.github.com>
1 parent c5c8839 commit 242f1de

7 files changed

Lines changed: 62 additions & 56 deletions

File tree

docs/customization/plugins/getting-started.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ Replace `src/lib.rs` with:
119119

120120
// Host function imports
121121
#[link(wasm_import_module = "cortex")]
122-
extern "C" {
122+
unsafe extern "C" {
123123
/// Log a message at the specified level
124124
/// level: 0=trace, 1=debug, 2=info, 3=warn, 4=error
125125
fn log(level: i32, msg_ptr: i32, msg_len: i32);
@@ -146,14 +146,14 @@ fn log_debug(msg: &str) {
146146
// ============================================================================
147147

148148
/// Called when the plugin is initialized
149-
#[no_mangle]
149+
#[unsafe(no_mangle)]
150150
pub extern "C" fn init() -> i32 {
151151
log_info("Hello Plugin initialized!");
152152
0 // Return 0 for success
153153
}
154154

155155
/// Called when the plugin is shutting down
156-
#[no_mangle]
156+
#[unsafe(no_mangle)]
157157
pub extern "C" fn shutdown() -> i32 {
158158
log_info("Hello Plugin shutting down");
159159
0
@@ -165,7 +165,7 @@ pub extern "C" fn shutdown() -> i32 {
165165

166166
/// Handler for the /hello command
167167
/// Function name format: cmd_<command_name_with_underscores>
168-
#[no_mangle]
168+
#[unsafe(no_mangle)]
169169
pub extern "C" fn cmd_hello() -> i32 {
170170
log_info("Hello, World!");
171171
0
@@ -284,7 +284,7 @@ fn log_debug(msg: &str) {
284284
}
285285
}
286286

287-
#[no_mangle]
287+
#[unsafe(no_mangle)]
288288
pub extern "C" fn cmd_hello() -> i32 {
289289
log_debug("cmd_hello called");
290290
// ... rest of function
@@ -393,9 +393,9 @@ timeout_ms = 30000 # Longer timeout for debugging
393393
- Rust: `fn cmd_my_command()`
394394
- Replace hyphens with underscores
395395

396-
2. Check `#[no_mangle]` attribute:
396+
2. Check `#[unsafe(no_mangle)]` attribute:
397397
```rust
398-
#[no_mangle]
398+
#[unsafe(no_mangle)]
399399
pub extern "C" fn cmd_hello() -> i32 {
400400
// ...
401401
}
@@ -467,7 +467,7 @@ timeout_ms = 30000 # Longer timeout for debugging
467467
**Solutions**:
468468
1. Log at the start and end of each exported function so a panic is easier to locate:
469469
```rust
470-
#[no_mangle]
470+
#[unsafe(no_mangle)]
471471
pub extern "C" fn cmd_hello() -> i32 {
472472
log_debug("Starting cmd_hello");
473473
// Your code here

examples/plugins/code-stats/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ license = "Apache-2.0"
1111
[lib]
1212
crate-type = ["cdylib"]
1313

14+
# Standalone package: not a workspace member of the Cortex CLI tree.
15+
[workspace]
16+
1417
[profile.release]
1518
opt-level = "s"
1619
lto = true

examples/plugins/code-stats/src/lib.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
1515
// ============================================================================
1616

1717
#[link(wasm_import_module = "cortex")]
18-
extern "C" {
18+
unsafe extern "C" {
1919
/// Log a message at the specified level.
2020
/// level: 0=trace, 1=debug, 2=info, 3=warn, 4=error
2121
fn log(level: i32, msg_ptr: i32, msg_len: i32);
@@ -273,7 +273,7 @@ fn record_file_deleted(lines: u64) {
273273
/// # Returns
274274
/// - `0` on success
275275
/// - Non-zero on failure
276-
#[no_mangle]
276+
#[unsafe(no_mangle)]
277277
pub extern "C" fn init() -> i32 {
278278
log_info("Code Stats plugin initializing...");
279279

@@ -303,7 +303,7 @@ pub extern "C" fn init() -> i32 {
303303
/// # Returns
304304
/// - `0` on success
305305
/// - Non-zero on failure
306-
#[no_mangle]
306+
#[unsafe(no_mangle)]
307307
pub extern "C" fn shutdown() -> i32 {
308308
log_info("Code Stats plugin shutting down");
309309

@@ -330,7 +330,7 @@ pub extern "C" fn shutdown() -> i32 {
330330
/// # Returns
331331
/// - `0` on success
332332
/// - Non-zero on failure
333-
#[no_mangle]
333+
#[unsafe(no_mangle)]
334334
pub extern "C" fn cmd_stats() -> i32 {
335335
log_debug("Stats command executed");
336336

@@ -354,7 +354,7 @@ pub extern "C" fn cmd_stats() -> i32 {
354354
/// # Returns
355355
/// - `0` on success
356356
/// - Non-zero on failure
357-
#[no_mangle]
357+
#[unsafe(no_mangle)]
358358
pub extern "C" fn cmd_stats_reset() -> i32 {
359359
log_debug("Stats reset command executed");
360360

@@ -378,7 +378,7 @@ pub extern "C" fn cmd_stats_reset() -> i32 {
378378
/// # Returns
379379
/// - `0` on success
380380
/// - Non-zero on failure
381-
#[no_mangle]
381+
#[unsafe(no_mangle)]
382382
pub extern "C" fn cmd_stats_export() -> i32 {
383383
log_debug("Stats export command executed");
384384

@@ -412,7 +412,7 @@ pub extern "C" fn cmd_stats_export() -> i32 {
412412
/// - `0` to continue normally
413413
/// - `1` to skip further processing
414414
/// - `2` to abort the operation chain
415-
#[no_mangle]
415+
#[unsafe(no_mangle)]
416416
pub extern "C" fn hook_file_operation_after() -> i32 {
417417
log_debug("File operation hook triggered");
418418

@@ -446,7 +446,7 @@ pub extern "C" fn hook_file_operation_after() -> i32 {
446446
/// - `0` to continue normally
447447
/// - `1` to skip further processing
448448
/// - `2` to abort
449-
#[no_mangle]
449+
#[unsafe(no_mangle)]
450450
pub extern "C" fn hook_session_end() -> i32 {
451451
log_info("Session end hook triggered - saving statistics");
452452

@@ -469,7 +469,7 @@ pub extern "C" fn hook_session_end() -> i32 {
469469
/// - `0` to continue normally
470470
/// - `1` to skip
471471
/// - `2` to abort
472-
#[no_mangle]
472+
#[unsafe(no_mangle)]
473473
pub extern "C" fn hook_widget_register() -> i32 {
474474
log_debug("Widget registration hook triggered");
475475

@@ -493,7 +493,7 @@ pub extern "C" fn hook_widget_register() -> i32 {
493493
/// # Returns
494494
/// - `0` on success
495495
/// - Non-zero on failure
496-
#[no_mangle]
496+
#[unsafe(no_mangle)]
497497
pub extern "C" fn widget_render_code_stats() -> i32 {
498498
// Get compact stats for status bar display
499499
let added = LINES_ADDED.load(Ordering::Relaxed);
@@ -519,7 +519,7 @@ pub extern "C" fn widget_render_code_stats() -> i32 {
519519
///
520520
/// # Returns
521521
/// - `0` on success
522-
#[no_mangle]
522+
#[unsafe(no_mangle)]
523523
pub extern "C" fn api_record_file_created() -> i32 {
524524
// In real implementation, read line count from shared buffer
525525
let lines: u64 = 0; // Placeholder - would be read from buffer
@@ -536,7 +536,7 @@ pub extern "C" fn api_record_file_created() -> i32 {
536536
///
537537
/// # Returns
538538
/// - `0` on success
539-
#[no_mangle]
539+
#[unsafe(no_mangle)]
540540
pub extern "C" fn api_record_file_deleted() -> i32 {
541541
// In real implementation, read line count from shared buffer
542542
let lines: u64 = 0; // Placeholder - would be read from buffer
@@ -551,7 +551,7 @@ pub extern "C" fn api_record_file_deleted() -> i32 {
551551
/// # Returns
552552
/// - Length of JSON string on success
553553
/// - Negative value on failure
554-
#[no_mangle]
554+
#[unsafe(no_mangle)]
555555
pub extern "C" fn api_get_stats_json() -> i64 {
556556
let json = get_stats_json();
557557
json.len() as i64

examples/plugins/hello-world/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ license = "Apache-2.0"
1111
[lib]
1212
crate-type = ["cdylib"]
1313

14+
# Standalone package: not a workspace member of the Cortex CLI tree.
15+
[workspace]
16+
1417
[profile.release]
1518
opt-level = "s"
1619
lto = true

examples/plugins/hello-world/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// ============================================================================
1313

1414
#[link(wasm_import_module = "cortex")]
15-
extern "C" {
15+
unsafe extern "C" {
1616
/// Log a message at the specified level.
1717
/// level: 0=trace, 1=debug, 2=info, 3=warn, 4=error
1818
fn log(level: i32, msg_ptr: i32, msg_len: i32);
@@ -119,7 +119,7 @@ fn show_notification(level: ToastLevel, message: &str, duration_ms: i32) {
119119
/// # Returns
120120
/// - `0` on success
121121
/// - Non-zero on failure (plugin will not be activated)
122-
#[no_mangle]
122+
#[unsafe(no_mangle)]
123123
pub extern "C" fn init() -> i32 {
124124
log_info("Hello World plugin initializing...");
125125

@@ -146,7 +146,7 @@ pub extern "C" fn init() -> i32 {
146146
/// # Returns
147147
/// - `0` on success
148148
/// - Non-zero on failure (logged but doesn't prevent unloading)
149-
#[no_mangle]
149+
#[unsafe(no_mangle)]
150150
pub extern "C" fn shutdown() -> i32 {
151151
log_info("Hello World plugin shutting down");
152152
0 // Success
@@ -166,7 +166,7 @@ pub extern "C" fn shutdown() -> i32 {
166166
/// # Returns
167167
/// - `0` on success
168168
/// - Non-zero on failure
169-
#[no_mangle]
169+
#[unsafe(no_mangle)]
170170
pub extern "C" fn cmd_hello() -> i32 {
171171
log_info("Hello command executed");
172172

@@ -201,7 +201,7 @@ pub extern "C" fn cmd_hello() -> i32 {
201201
/// - `0` to continue with tool execution
202202
/// - `1` to skip this tool execution
203203
/// - `2` to abort the entire operation
204-
#[no_mangle]
204+
#[unsafe(no_mangle)]
205205
pub extern "C" fn hook_tool_execute_before() -> i32 {
206206
log_debug("Tool execution intercepted by hello-world plugin");
207207

src/cortex-cli/src/plugin_cmd.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ const RUST_TEMPLATE: &str = r#"//! {{plugin_name}} - A Cortex plugin
8686
// ============================================================================
8787
8888
#[link(wasm_import_module = "cortex")]
89-
extern "C" {
89+
unsafe extern "C" {
9090
/// Log a message at the specified level.
9191
/// level: 0=trace, 1=debug, 2=info, 3=warn, 4=error
9292
fn log(level: i32, msg_ptr: i32, msg_len: i32);
@@ -120,14 +120,14 @@ fn log_info(msg: &str) { log_message(2, msg); }
120120
// ============================================================================
121121
122122
/// Called when the plugin is initialized.
123-
#[no_mangle]
123+
#[unsafe(no_mangle)]
124124
pub extern "C" fn init() -> i32 {
125125
log_info("{{plugin_name}} initialized");
126126
0 // Return 0 for success
127127
}
128128
129129
/// Called when the plugin is shutting down.
130-
#[no_mangle]
130+
#[unsafe(no_mangle)]
131131
pub extern "C" fn shutdown() -> i32 {
132132
log_info("{{plugin_name}} shutting down");
133133
0
@@ -138,7 +138,7 @@ pub extern "C" fn shutdown() -> i32 {
138138
// ============================================================================
139139
140140
/// Handler for the /{{command_name}} command.
141-
#[no_mangle]
141+
#[unsafe(no_mangle)]
142142
pub extern "C" fn cmd_{{command_name_snake}}() -> i32 {
143143
log_info("{{command_name}} command executed");
144144
0
@@ -164,7 +164,7 @@ const RUST_ADVANCED_TEMPLATE: &str = r#"//! {{plugin_name}} - Advanced Cortex Pl
164164
// ============================================================================
165165
166166
#[link(wasm_import_module = "cortex")]
167-
extern "C" {
167+
unsafe extern "C" {
168168
fn log(level: i32, msg_ptr: i32, msg_len: i32);
169169
fn get_context() -> i64;
170170
fn register_widget(region: i32, widget_type_ptr: i32, widget_type_len: i32) -> i32;
@@ -254,7 +254,7 @@ fn show_notification(level: ToastLevel, message: &str, duration_ms: i32) {
254254
// Plugin lifecycle
255255
// ============================================================================
256256
257-
#[no_mangle]
257+
#[unsafe(no_mangle)]
258258
pub extern "C" fn init() -> i32 {
259259
log_info("{{plugin_name}} initializing...");
260260
@@ -272,7 +272,7 @@ pub extern "C" fn init() -> i32 {
272272
0
273273
}
274274
275-
#[no_mangle]
275+
#[unsafe(no_mangle)]
276276
pub extern "C" fn shutdown() -> i32 {
277277
log_info("{{plugin_name}} shutting down");
278278
0
@@ -282,7 +282,7 @@ pub extern "C" fn shutdown() -> i32 {
282282
// Command handlers
283283
// ============================================================================
284284
285-
#[no_mangle]
285+
#[unsafe(no_mangle)]
286286
pub extern "C" fn cmd_{{command_name_snake}}() -> i32 {
287287
log_info("{{command_name}} command executed");
288288
show_notification(ToastLevel::Info, "Command executed!", 2000);
@@ -294,27 +294,27 @@ pub extern "C" fn cmd_{{command_name_snake}}() -> i32 {
294294
// ============================================================================
295295
296296
/// UI render hook - customize component rendering
297-
#[no_mangle]
297+
#[unsafe(no_mangle)]
298298
pub extern "C" fn hook_ui_render() -> i32 {
299299
// Return 0 to continue with normal rendering
300300
0
301301
}
302302
303303
/// Animation frame hook - called every frame for animations
304-
#[no_mangle]
304+
#[unsafe(no_mangle)]
305305
pub extern "C" fn hook_animation_frame(_frame: u64, _delta_us: u64) -> i32 {
306306
// Return 1 to request another frame, 0 to stop
307307
0
308308
}
309309
310310
/// Focus change hook
311-
#[no_mangle]
311+
#[unsafe(no_mangle)]
312312
pub extern "C" fn hook_focus_change(_focused: i32) -> i32 {
313313
0
314314
}
315315
316316
/// TUI event handler
317-
#[no_mangle]
317+
#[unsafe(no_mangle)]
318318
pub extern "C" fn hook_tui_event() -> i32 {
319319
0
320320
}
@@ -323,7 +323,7 @@ pub extern "C" fn hook_tui_event() -> i32 {
323323
// Custom action handlers
324324
// ============================================================================
325325
326-
#[no_mangle]
326+
#[unsafe(no_mangle)]
327327
pub extern "C" fn action_{{plugin_id_snake}}_action() -> i32 {
328328
log_info("Custom action triggered via keybinding");
329329
show_notification(ToastLevel::Success, "Action executed!", 1500);

0 commit comments

Comments
 (0)