Porting Log: Linux, macOS and Android
Status: ✅ Shipped
| Platform | RID | Shipped in |
|---|---|---|
| Windows x64 / arm64 | win-x64 / win-arm64 |
v0.1 / v0.8.x |
| Linux x64 / arm64 | linux-x64 / linux-arm64 |
v0.8.6 / v1.2.0 |
| macOS x64 / arm64 | osx-x64 / osx-arm64 |
v0.8.6 |
| Android arm64 | android-arm64 |
v2.0.0 |
All release artifacts are built and published via CI (see Architecture → CI). The Android port is a full portrait-first app documented in the Android Architecture and Mobile Guide. What follows is the original Linux/macOS plan — kept for historical reference.
Original Objective
- Enable building, publishing, and running XBVault on Linux and macOS for development and testing (does not cover final packaging like macOS notarization).
Verified Assumptions
- Project uses .NET 10 + Avalonia (supports Linux/macOS).
- Currently has dependencies and scripts assuming Windows (WinExe, absolute dotnet path, PublishReadyToRun, BuiltInComInteropSupport).
High-Level Checklist (Executable Order)
1. Quick Experiment (prove app launches)
- On a Linux machine with .NET 10 installed:
dotnet publish XBVault -c Release -r linux-x64 --self-contained false -o out ./out/XBVault - On macOS, replace
-rwithosx-x64orosx-arm64and run./out/XBVaultoropen out/XBVault.appif bundled. - Install native libs if app fails (see “Native Dependencies” section).
2. Harden csproj (minimal changes)
- Add RuntimeIdentifiers:
win-x64;linux-x64;osx-x64;osx-arm64. - Conditionalize Windows-only props:
OutputTypecan beExeinstead ofWinExefor cross-platform.- Move
BuiltInComInteropSupporttoCondition="'$(RuntimeIdentifier)'=='win-*'".
- Don’t remove Avalonia; just make props conditional.
3. Make scripts multi-OS / document alternatives
- Don’t rely on
"C:\Program Files\dotnet\dotnet.exe"in scripts. Options:- Update scripts to use
dotnetfrom PATH (cross-OS). - Or clearly document how to run
dotnet publishdirectly (see commands above).
- Update scripts to use
4. Guard Windows-specific code
- Search for P/Invoke, COM, registry, or hard-coded paths:
rg "DllImport|ComInterop|Registry|RegistryKey|PInvoke|BuiltInComInteropSupport|RuntimeInformation" -S - Wrap/conditionalize with
RuntimeInformation.IsOSPlatform(OSPlatform.Windows).
5. Native Dependencies (install for dev/test)
- Linux (Debian/Ubuntu example):
sudo apt install -y libgtk-3-0 libgdk-pixbuf2.0-0 libx11-6 libc6 libharfbuzz0b libfontconfig1 - macOS: install via Homebrew libs recommended by Avalonia (gtk3/homebrew formulas) and configure DISPLAY if using remote GUI.
6. Smoke Tests and Validation
- Simple CI job per OS:
dotnet publish+ try to run the binary (exit code 0) inside the runner. - Manual tests: open UI and quickly navigate through critical screens (Settings, Browse, Installed).
7. CI
- Add matrix job (windows-latest, ubuntu-latest, macos-latest) that runs:
dotnet --infodotnet restoredotnet publish XBVault -c Release -r <rid> --self-contained false -o out- Run smoke executable (where possible)
8. Packaging and Distribution (separate)
- Linux: AppImage / deb / flatpak — needs to package native dependencies correctly.
- macOS: .app bundle, codesign and notarize for public distribution.
Quick Estimate
- Local experimentation (prove publish + open): 1–2 hours.
- Remove/conditionalize Windows-only and adjust csproj/scripts: 2–6 hours.
- Configure multi-OS CI + smoke runs: 1–3 hours.
- Cross-platform packaging (prod): days → weeks (depends on target quality).
Minimum PR Checklist
- csproj: RuntimeIdentifiers and conditionals applied.
- Build scripts: don’t use absolute dotnet path or document alternatives.
- Code: runtime-guarded where necessary; no raw Windows P/Invoke without guards.
- Docs: update AGENTS.md and add quick instructions on how to test on Linux/macOS.
- CI: job matrix with publish + smoke run.
Final Notes
- Prioritize quick experiment to know if problems are just native libs. If UI fails immediately, problem is env (dependencies) not .NET code.
- I can open a PR with conditional csproj and a sample CI workflow if you want — let me know which option you prefer.