fix(v3): unblock iOS and Android cross-compiles (5 build-tag/API bugs) - #5908
fix(v3): unblock iOS and Android cross-compiles (5 build-tag/API bugs)#5908mgueregath wants to merge 3 commits into
Conversation
Five small build-tag/API-mismatch bugs kept `GOOS=ios` and `GOOS=android`
builds from compiling at all, discovered while cross-compiling a real
third-party app against v3.0.0-alpha.98:
- pkg/application/linux_cgo.{c,h}: build tag was missing `&& !android`.
Go implicitly sets the `linux` tag for GOOS=android (Android is
Linux-based), so these GTK-dependent cgo files were being pulled into
Android builds and failing on a missing gtk/gtk.h.
- pkg/application/messageprocessor_ios.go /
messageprocessor_android.go: messageprocessor.go references both
`androidMethodNames` and `iosMethodNames` unconditionally (for its
Debug logging switch), but each platform-specific file only defined
its own map. Added the missing empty map on each side, matching the
existing stub pattern for `processAndroidMethod`/`processIOSMethod`.
- pkg/events/events.go: events_common_ios.go references the exported
`events.IOS`, but the package only defined the unexported `iOS` — an
apparent partial rename. Exported it.
- pkg/application/application_android.go: the Android JNI page-finished
handler called `runtime.Core()` with no arguments, while every other
platform (darwin/windows/linux) calls
`runtime.Core(globalApplication.impl.GetFlags(globalApplication.options))`.
`androidApp.GetFlags` already existed but wasn't wired up here.
- pkg/events/events.go: events_common_android.go references
`events.Android.ActivityCreated`, but no `Android` events var existed
at all. Added a minimal `androidEvents` struct with just the field
that's actually referenced.
Verified end-to-end, not just compile-only: built both targets, packaged
an iOS .app and installed+launched it in the iOS Simulator, and built an
Android debug APK and installed+launched it in an arm64 emulator. Logs on
both platforms show the app boots, the Go runtime starts, and (on
Android) the exact previously-crashing `runtime.Core()` call site
executes successfully via the real JNI nativeOnPageFinished callback.
WalkthroughThe change fixes Android and iOS cross-compilation and startup issues. It updates platform build constraints, mobile symbols, Android runtime flags, iOS webview URL loading, and iOS bundle executable settings. ChangesMobile cross-compilation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1⚔️ Resolve merge conflicts 💡
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…lsapp"
Both Info.plist.tmpl and Info.dev.plist.tmpl render CFBundleExecutable
from {{.BinaryName}}, but ios_xcode_gen.go never wires that field to
anything config-derived ("BinaryName remains default unless we later
add config support") — it's permanently the literal "wailsapp" default,
regardless of the app's actual product/binary name.
Since the app's real executable name always matches whatever
PRODUCT_NAME/EXECUTABLE_NAME the Xcode build produces (which IS
correctly derived from build/config.yml via ProductName), the robust
fix is to stop hardcoding a Go-side value at generation time and use
Xcode's own $(EXECUTABLE_NAME) build variable instead — the standard
approach any Xcode-created project uses, and it can never drift out of
sync with the actual build output.
Without this fix, `xcrun devicectl device install app` (and Xcode's own
device install/run) fails with:
The item at <name>.app is not a valid bundle.
Failure Reason: The path to the provided bundle's main executable
could not be determined.
because CFBundleExecutable names a file ("wailsapp") that doesn't exist
anywhere in the bundle. Reproduced and fixed while installing a real app
(product name "tacataca-udp-poc") on a physical iPhone — confirmed
`plutil -p .../Info.plist` now reports the correct executable name and
`xcrun devicectl device install app` + `device process launch` both
succeed.
|
Added one more fix to this branch (pushed as a follow-up commit) while actually installing and running the iOS build on a physical device, not just the simulator.
This breaks real-device installs outright:
Fixed by switching both templates to Xcode's own |
…y blank iosWebviewWindow.run() creates the native WKWebView (ios_create_webview_with_id) and applies the background colour, but never tells it to navigate anywhere. Every other platform's run() does this — see webview_window_darwin.go, which resolves options.URL via assetserver.GetStartURL() and calls w.setURL() right after creating the native window. Without this, the WKWebView is created (so BackgroundColour shows) but sits permanently blank regardless of whether the Go asset server is serving correctly — confirmed via full log capture (AssetFileServerFS logs show index.html/style.css/assets/*.js all being served successfully, and the JS runtime even sends wails:runtime:ready), the page was never actually loaded because nothing ever called WKWebView loadRequest. Fixed by mirroring macOS's run(): resolve the start URL and call setURL() immediately after creating the native handle. Verified end-to-end: built, installed, and launched a real app in the iOS Simulator — screenshot confirms the app's actual UI (not a blank page) renders correctly.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@v3/pkg/application/webview_window_ios.go`:
- Around line 228-231: Update the iOS initialization flow around
assetserver.GetStartURL to handle non-nil errors through the existing iOS
fatal-error handler, matching the macOS error path and stopping initialization
before attempting setURL. Preserve setURL only for successfully resolved start
URLs.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 00c8bfc7-abde-4aa6-9810-debe9f13bd0b
📒 Files selected for processing (1)
v3/pkg/application/webview_window_ios.go
| startURL, err := assetserver.GetStartURL(w.parent.options.URL) | ||
| if err == nil { | ||
| w.setURL(startURL) | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Handle GetStartURL errors before continuing.
assetserver.GetStartURL returns an error for malformed FRONTEND_DEVSERVER_URL or options.URL. The current if err == nil branch discards that error. setURL is then skipped, so the iOS application can remain blank with no startup diagnostic. Follow the macOS error path and route the error through the iOS fatal-error handler before stopping initialization.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@v3/pkg/application/webview_window_ios.go` around lines 228 - 231, Update the
iOS initialization flow around assetserver.GetStartURL to handle non-nil errors
through the existing iOS fatal-error handler, matching the macOS error path and
stopping initialization before attempting setURL. Preserve setURL only for
successfully resolved start URLs.
|
Two more fixes on this branch, both found while actually getting a real app to render (not just compile) on iOS Simulator and an Android emulator — both were stuck on a permanently blank/white screen even though everything else (bindings, native bridge handshake) worked. iOS:
|
|
Closing this — while working through the merge conflicts I found that #5562/#5602 (merged since this PR was opened against
Verified directly: built and ran real apps on both platforms against Thanks for the mobile rewrite — sorry for the noise on an already-fixed issue. |
Fixes #5907.
Five small, independent bugs that keep
GOOS=iosandGOOS=androidfrom compiling at all onv3.0.0-alpha.98, found while cross-compiling a real third-party app (Go service backend + plain HTML/JS frontend, nothing exotic).What's fixed
pkg/application/linux_cgo.c/linux_cgo.h: build tag waslinux && !gtk3 && !server, missing&& !android. Go implicitly sets thelinuxtag whenGOOS=android(Android is Linux-based under the hood), so these GTK-dependent cgo files were pulled into Android builds and failed on a missinggtk/gtk.h. The.gocounterparts (application_linux.go,linux_cgo.go) already excluded!androidcorrectly — only the cgo files were missed.pkg/application/messageprocessor_ios.go: added the (empty)androidMethodNamesmap.messageprocessor.go's Debug-logging switch references bothiosMethodNamesandandroidMethodNamesunconditionally, but the iOS file only defined its own map, leavingandroidMethodNamesundefined on iOS builds — even thoughprocessAndroidMethodalready has an iOS-side stub right next to it.pkg/application/messageprocessor_android.go: same fix, mirrored — added the emptyiosMethodNamesmap so Android builds don't fail on the same reference in reverse.pkg/events/events.go: exportediOS→IOS.events_common_ios.goreferencesevents.IOS.ApplicationDidFinishLaunching, but the package only defined the lowercase, unexportediOS— every sibling (Common,Linux,Mac,Windows) is already exported, so this reads like a partial rename that never got finished. Confirmed no other internal references to the lowercase name exist.pkg/events/events.go: added a minimalAndroidevents var (androidEvents{ ActivityCreated }) —events_common_android.goreferencesevents.Android.ActivityCreated, but noAndroidvar existed at all inpkg/events. Kept intentionally minimal (just the one field that's actually referenced) rather than guessing at a fuller Android lifecycle event set.pkg/application/application_android.go: wiredglobalApplication.impl.GetFlags(globalApplication.options)into the JNI page-finished handler'sruntime.Core(...)call. Every other platform (webview_window_darwin.go,webview_window_windows.go,webview_window_linux.go) already callsruntime.Core(globalApplication.impl.GetFlags(globalApplication.options)); the Android call site calledruntime.Core()with no arguments, which doesn't matchruntime.Core(flags map[string]any) string's signature.androidApp.GetFlagsalready existed, just wasn't being used here.Verification
Not just compile-clean — built and ran both targets end to end:
go build -buildmode=c-archive -tags ios,debug ...succeeds, linked into a.appwithclang, installed and launched in the iOS Simulator (xcrun simctl install/launch) viacodesign --sign -.simctllogs show the app boots,application_ios.go'sprocessApplicationEventfires forApplicationDidBecomeActive(the exactevents.IOS.*path from bug Port init #4) with no crash.go build -buildmode=c-shared -tags android,debug ...succeeds against NDK r27 (aarch64-linux-android21-clang), packaged into a debug APK via the generated Gradle project, installed and launched on an arm64-v8a emulator (Pixel 9 Pro API 35).adb logcatshowsWailsBridgeinitializing, the JNInativeOnPageFinishedcallback firing, andruntime.Core()'s log line executing successfully — the exact call site from bug Initial Port #6 — with noFATAL/crash.Both apps render a blank page in this test (an unrelated debug-mode asset-serving issue,
WailsPathHandler: Asset not found: /index.html— happening because I built the c-archive/c-shared manually instead of throughwails3 dev's asset pipeline, not something this PR touches), but the Go runtime itself boots and the native bridge handshake completes cleanly on both platforms, which is what these five bugs were blocking.Notes
wails3 ios overlay:genfailing outside the Wails monorepo, ininternal/commands/ios_overlay_gen.go'srepoRoot()) is not fixed by this PR — it's a CLI tooling issue, not a build-tag bug, and felt like a separate fix. Happy to take a pass at that in a follow-up if useful.events.Androidlifecycle event set beyondActivityCreatedsince I don't have visibility into what the Android-side native code actually emits — kept the fix scoped to what's referenced today.Summary by CodeRabbit
New Features
Bug Fixes