$npx -y skills add ZhangHanDong/makepad-skills --skill makepad-2.0-migrationCRITICAL: Use for migrating from Makepad 1.x to 2.0. Triggers on: makepad migration, live_design to script_mod, makepad upgrade, makepad 1.x, old syntax, new syntax, makepad breaking changes, makepad 迁移, 旧语法, LiveHook to ScriptHook, apply_over to script_apply_eval, Live to Script
| 1 | # Makepad 1.x to 2.0 Migration Skill |
| 2 | |
| 3 | > **Version:** makepad-widgets (dev branch) | **Last Updated:** 2026-03-03 |
| 4 | |
| 5 | ## Overview |
| 6 | |
| 7 | Makepad 2.0 is a **fundamental architecture shift** from compile-time static DSL to runtime scripting. Migration involves syntax changes, derive macro updates, lifecycle method renames, and new patterns for state management. |
| 8 | |
| 9 | ## Documentation |
| 10 | |
| 11 | Refer to the local files for detailed documentation: |
| 12 | - `./references/migration-guide.md` - Complete migration reference with examples |
| 13 | |
| 14 | --- |
| 15 | |
| 16 | ## Quick Syntax Mapping Table |
| 17 | |
| 18 | | Makepad 1.x | Makepad 2.0 | Notes | |
| 19 | |-------------|-------------|-------| |
| 20 | | `live_design! { ... }` | `script_mod! { ... }` | Core macro change | |
| 21 | | `<Widget> { ... }` | `Widget{ ... }` | No angle brackets | |
| 22 | | `Key = Value` | `Key: value` | Colon, not equals | |
| 23 | | `(THEME_COLOR)` | `theme.color_*` | Theme namespace | |
| 24 | | `live_body: { ... }` | `body +: { ... }` | Merge operator | |
| 25 | | `#[derive(Live)]` | `#[derive(Script)]` | Derive macro | |
| 26 | | `#[derive(LiveHook)]` | `#[derive(ScriptHook)]` | Lifecycle hooks | |
| 27 | | `#[derive(Widget)]` | `#[derive(Widget)]` | Unchanged | |
| 28 | | `before_apply()` | `on_before_apply()` | Method rename | |
| 29 | | `after_apply()` | `on_after_apply()` | Method rename | |
| 30 | | `apply_over!()` | `script_apply_eval!()` | Runtime updates | |
| 31 | | `DefaultNone` | `Default` | Enum default | |
| 32 | | `LiveRegister` | `WidgetRegister` | Widget registration | |
| 33 | | `live_register()` | `register_widget(vm)` | Registration method | |
| 34 | | `LiveId` | `LiveId` | Unchanged | |
| 35 | |
| 36 | --- |
| 37 | |
| 38 | ## Step-by-Step Migration |
| 39 | |
| 40 | ### Step 1: Replace Macro |
| 41 | |
| 42 | ```rust |
| 43 | // OLD |
| 44 | live_design! { |
| 45 | import makepad_widgets::base::*; |
| 46 | import makepad_widgets::theme_desktop_dark::*; |
| 47 | |
| 48 | App = {{App}} { |
| 49 | ui: <Root> { ... } |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | // NEW |
| 54 | script_mod! { |
| 55 | use mod.prelude.widgets.* |
| 56 | |
| 57 | startup() do #(App::script_component(vm)){ |
| 58 | ui: Root{ |
| 59 | // ... UI definition |
| 60 | } |
| 61 | } |
| 62 | } |
| 63 | ``` |
| 64 | |
| 65 | ### Step 2: Update Derives |
| 66 | |
| 67 | ```rust |
| 68 | // OLD |
| 69 | #[derive(Live, LiveHook, Widget)] |
| 70 | pub struct MyWidget { ... } |
| 71 | |
| 72 | // NEW |
| 73 | #[derive(Script, ScriptHook, Widget)] |
| 74 | pub struct MyWidget { ... } |
| 75 | ``` |
| 76 | |
| 77 | ### Step 3: Update App::run |
| 78 | |
| 79 | ```rust |
| 80 | // OLD |
| 81 | impl LiveRegister for App { |
| 82 | fn live_register(cx: &mut Cx) { |
| 83 | makepad_widgets::live_design(cx); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | // NEW |
| 88 | impl App { |
| 89 | fn run(vm: &mut ScriptVm) -> Self { |
| 90 | crate::makepad_widgets::script_mod(vm); |
| 91 | App::from_script_mod(vm, self::script_mod) |
| 92 | } |
| 93 | } |
| 94 | ``` |
| 95 | |
| 96 | ### Step 4: Rename Lifecycle Methods |
| 97 | |
| 98 | ```rust |
| 99 | // OLD |
| 100 | impl LiveHook for MyWidget { |
| 101 | fn before_apply(&mut self, cx: &mut Cx, ...) { ... } |
| 102 | fn after_apply(&mut self, cx: &mut Cx, ...) { ... } |
| 103 | } |
| 104 | |
| 105 | // NEW |
| 106 | impl ScriptHook for MyWidget { |
| 107 | fn on_before_apply(&mut self, cx: &mut Cx, ...) { ... } |
| 108 | fn on_after_apply(&mut self, cx: &mut Cx, ...) { ... } |
| 109 | } |
| 110 | ``` |
| 111 | |
| 112 | ### Step 5: Update DSL Syntax |
| 113 | |
| 114 | ``` |
| 115 | // OLD - angle brackets, equals signs |
| 116 | <View> { |
| 117 | width: Fill, height: Fill |
| 118 | show_bg: true |
| 119 | draw_bg: { color: (THEME_BG) } |
| 120 | |
| 121 | title = <Label> { |
| 122 | text: "Hello" |
| 123 | draw_text: { color: #fff } |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | // NEW - curly braces, colons, theme namespace |
| 128 | View{ |
| 129 | width: Fill height: Fill |
| 130 | show_bg: true |
| 131 | draw_bg.color: theme.color_bg_app |
| 132 | |
| 133 | title := Label{ |
| 134 | text: "Hello" |
| 135 | draw_text.color: #fff |
| 136 | } |
| 137 | } |
| 138 | ``` |
| 139 | |
| 140 | ### Step 6: Replace apply_over with script_eval |
| 141 | |
| 142 | ```rust |
| 143 | // OLD |
| 144 | self.label(id!(title)).apply_over(cx, live! { |
| 145 | text: "New text" |
| 146 | }); |
| 147 | |
| 148 | // NEW |
| 149 | script_eval!(cx, { |
| 150 | ui.title.set_text("New text") |
| 151 | }); |
| 152 | // OR |
| 153 | script_apply_eval!(cx, self.ui, { |
| 154 | title.text: "New text" |
| 155 | }); |
| 156 | ``` |
| 157 | |
| 158 | --- |
| 159 | |
| 160 | ## Key Breaking Changes |
| 161 | |
| 162 | 1. **No commas** between properties (whitespace-delimited) |
| 163 | 2. **No semicolons** anywhere in Splash |
| 164 | 3. **No angle brackets** for widget types |
| 165 | 4. **Theme constants** use `theme.*` prefix, not `(THEME_*)` syntax |
| 166 | 5. **Named children** use `:=` operator, not `=` |
| 167 | 6. **Merge operator** is `+:` not `:` for extending parent properties |
| 168 | 7. **`height: Fit`** is MANDATORY on containers (default is 0px, not auto) |
| 169 | 8. **Registration** happens in `App::run`, not `live_register` |
| 170 | 9. **Field attribute** `#[source]` links to script object (required on some widgets) |
| 171 | 10. **Old `old/` directory** contains archived 1.x code for reference |
| 172 | |
| 173 | --- |
| 174 | |
| 175 | ## Common Migration Mistakes |
| 176 | |
| 177 | | Mistake | Symptom | Fix | |
| 178 | |---------|---------|-----| |
| 179 | | Still using `live_design!` | Compile error | Replace with `script_mod!` | |
| 180 | | Using `<Widget>` syntax | Parse error | Use `Widget{}` | |
| 181 | | Using `Key = Value` | Property not applied | Use `Key: value` | |
| 182 | | Using `(THEME_COLOR)` | Unknown token | Use `theme.color_*` | |
| 183 | | Missing `height: Fit` | Container invisible (0px) | Add `height: Fit |