Summary
Compiling a Perry app that imports embedNSView (or other perry/ui FFI helpers exported as extern fn) for --target harmonyos produces a libentry.so whose dynamic loader rejects the bundle at app launch:
Error relocating /data/storage/el1/bundle/libs/arm64/libentry.so: perry_ui_embed_nsview: symbol not found.
[ecmascript] export objects of native so is undefined, so name is @normalized:Y&&&libentry.so&
TypeError: Cannot read property run of undefined
Repro
Mango (~/projects/mango) at v1.1.29 imports @honeide/editor whose editor-component.ts calls embedNSView(hone_editor_nsview(handle)) to splice the editor's native view into the Perry widget tree. With Hone's new native/harmonyos/ no-op stub crate (PerryTS/hone#TBD, v0.2.1), the hone_editor_* symbols all resolve, but perry_ui_embed_nsview becomes the next undefined symbol and trips the loader.
cd ~/projects/mango
perry compile src/app.ts --target harmonyos -o /tmp/libentry.so
llvm-nm -D --undefined-only /tmp/libentry.so | grep "perry_ui_"
# → U perry_ui_embed_nsview
# (and likely others if the user calls more perry/ui FFI in non-harvested code paths)
The .so builds cleanly; the error only surfaces at app launch on the device.
Why it happens
HarmonyOS goes through the perry-codegen-arkts harvest model — App({body: VStack([...])}) is destructively rewritten into ArkUI source so LLVM never sees perry_ui_* calls for the harvested widget tree. There is no perry-ui-harmonyos crate by design.
But embedNSView (and the other perry/ui extern declarations in user-facing code paths that aren't part of an App({body: ...}) literal) survive into the lowered .so because they're called from inside library code (e.g. Hone's createEditorPerryWidget()), not from the harvest target. Codegen-arkts can't see them, codegen-llvm doesn't strip them, and there's nothing on the HarmonyOS link line that defines them.
Other platforms each export the symbol from their UI crate:
crates/perry-ui-macos/src/lib.rs — real impl (widgets::register_external_nsview)
crates/perry-ui-android/src/lib.rs:1682 — Android stub
crates/perry-ui-gtk4/src/lib.rs:166 — GTK4 stub with debug log
crates/perry-ui-windows/src/lib.rs:1390 — Windows stub
crates/perry-ui-harmonyos/ — doesn't exist
Suggested fix
Two options:
Option A (minimum viable): add a no-op perry_ui_embed_nsview (+ any sibling perry_ui_* FFI that might leak through library code) to crates/perry-runtime/src/ui_text_registry.rs (already gated #[cfg(not(feature = "ohos-napi"))] for the cross-platform stubs that route to a NULL handler when no UI lib is linked — same pattern as v0.5.419's showToast/setText cross-platform sweep). Returns 0; Hone's embedNSView(hone_editor_nsview(0)) becomes a no-op chain that link-resolves and runs without crashing. The editor renders blank but the app boots.
Option B (proper): create crates/perry-ui-harmonyos as a parallel to perry-ui-android etc, exporting every perry_ui_* FFI that user library code might reference. Codegen-arkts continues to handle the harvest path; this crate handles the residue. Bigger refactor, follows the existing per-platform UI crate convention. Probably the right long-term direction.
To find the full list of perry_ui_* symbols that can leak: build a Mango-shaped corpus (any Perry app pulling in a third-party widget library) for --target harmonyos and run llvm-nm -D --undefined-only over the resulting .so.
Affected versions
Found on Perry v0.5.471 (HarmonyOS bringup landed in v0.5.399 / v0.5.418-v0.5.447, sequence of Phase 2 v1-v13). All HarmonyOS releases are affected; this gap was masked until Hone's HarmonyOS no-op stub crate landed and pushed the next undefined symbol into view.
Blocking
This is the next blocker after PerryTS/hone#TBD ("Hone editor on HarmonyOS no-op stub") — once perry/ui exports are present on HarmonyOS, Mango (and any Perry app embedding a Perry-widget-using third-party library) should at minimum boot to the auto-generated ArkUI Index.ets page on the emulator.
Summary
Compiling a Perry app that imports
embedNSView(or otherperry/uiFFI helpers exported asextern fn) for--target harmonyosproduces alibentry.sowhose dynamic loader rejects the bundle at app launch:Repro
Mango (
~/projects/mango) at v1.1.29 imports@honeide/editorwhoseeditor-component.tscallsembedNSView(hone_editor_nsview(handle))to splice the editor's native view into the Perry widget tree. With Hone's newnative/harmonyos/no-op stub crate (PerryTS/hone#TBD, v0.2.1), thehone_editor_*symbols all resolve, butperry_ui_embed_nsviewbecomes the next undefined symbol and trips the loader.The
.sobuilds cleanly; the error only surfaces at app launch on the device.Why it happens
HarmonyOS goes through the
perry-codegen-arktsharvest model —App({body: VStack([...])})is destructively rewritten into ArkUI source so LLVM never seesperry_ui_*calls for the harvested widget tree. There is noperry-ui-harmonyoscrate by design.But
embedNSView(and the otherperry/uiextern declarations in user-facing code paths that aren't part of anApp({body: ...})literal) survive into the lowered.sobecause they're called from inside library code (e.g. Hone'screateEditorPerryWidget()), not from the harvest target. Codegen-arkts can't see them, codegen-llvm doesn't strip them, and there's nothing on the HarmonyOS link line that defines them.Other platforms each export the symbol from their UI crate:
crates/perry-ui-macos/src/lib.rs— real impl (widgets::register_external_nsview)crates/perry-ui-android/src/lib.rs:1682— Android stubcrates/perry-ui-gtk4/src/lib.rs:166— GTK4 stub with debug logcrates/perry-ui-windows/src/lib.rs:1390— Windows stubcrates/perry-ui-harmonyos/— doesn't existSuggested fix
Two options:
Option A (minimum viable): add a no-op
perry_ui_embed_nsview(+ any siblingperry_ui_*FFI that might leak through library code) tocrates/perry-runtime/src/ui_text_registry.rs(already gated#[cfg(not(feature = "ohos-napi"))]for the cross-platform stubs that route to a NULL handler when no UI lib is linked — same pattern as v0.5.419's showToast/setText cross-platform sweep). Returns 0; Hone'sembedNSView(hone_editor_nsview(0))becomes a no-op chain that link-resolves and runs without crashing. The editor renders blank but the app boots.Option B (proper): create
crates/perry-ui-harmonyosas a parallel toperry-ui-androidetc, exporting everyperry_ui_*FFI that user library code might reference. Codegen-arkts continues to handle the harvest path; this crate handles the residue. Bigger refactor, follows the existing per-platform UI crate convention. Probably the right long-term direction.To find the full list of
perry_ui_*symbols that can leak: build a Mango-shaped corpus (any Perry app pulling in a third-party widget library) for--target harmonyosand runllvm-nm -D --undefined-onlyover the resulting.so.Affected versions
Found on Perry v0.5.471 (HarmonyOS bringup landed in v0.5.399 / v0.5.418-v0.5.447, sequence of Phase 2 v1-v13). All HarmonyOS releases are affected; this gap was masked until Hone's HarmonyOS no-op stub crate landed and pushed the next undefined symbol into view.
Blocking
This is the next blocker after PerryTS/hone#TBD ("Hone editor on HarmonyOS no-op stub") — once
perry/uiexports are present on HarmonyOS, Mango (and any Perry app embedding a Perry-widget-using third-party library) should at minimum boot to the auto-generated ArkUI Index.ets page on the emulator.