Porting Log: Linux and macOS
Status: ✅ Shipped in v0.8.6
Both Linux (x64) and macOS (x64 + arm64) release artifacts are built and published via CI. What follows is the original 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 8 + 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 8 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.