# Building Chanora v0.2.0-beta.1 on Windows via Azure VM **Document type:** Release / Platform Build Instructions **Version:** 0.1.0 **Status:** Draft **Language:** English **Product:** Chanora **Repo path:** `docs/release/windows-build.md` --- ## 1. Purpose This document gives exact step-by-step instructions for building the Chanora `v0.2.0-beta.1` Internal Beta on a Windows host, using an Azure Virtual Machine. It exists because the development host is Linux; `flutter build windows` requires a Windows host with Visual Studio 2022 and cannot be cross-compiled. After following this doc you will have: - `chanora_flutter.exe` — the Windows desktop binary. - `chanora_bridge.dll` — the Rust cdylib loaded by the .exe via FFI. - A complete release bundle directory the app needs at runtime. The doc assumes you have: - An Azure subscription with permission to create VMs. - An RDP client (Windows: built-in; macOS: Microsoft Remote Desktop; Linux: `remmina` or `rdesktop`). - The Chanora source code locally (this repository). --- ## 2. Toolchain versions pinned for this build | Tool | Version | Why | |---|---|---| | Windows Server | 2022 Datacenter | LTS, plenty of Azure images, ships PowerShell 5.1 + Server Core APIs | | Visual Studio 2022 | Build Tools (Community works too) | Required by `flutter build windows`; provides MSVC, Windows SDK, CMake, link.exe | | Visual Studio workload | "Desktop development with C++" | Provides MSVC v143, Windows 10/11 SDK, CMake tools, C++ ATL | | Flutter SDK | 3.41.9 stable | Matches the Linux/Beta build; bridge codegen is version-sensitive | | Dart SDK | 3.11.5 | Comes with Flutter 3.41.9 | | Rust toolchain | stable 1.95 (or newer) | Workspace `rust-version = "1.95"` | | Rust target | `x86_64-pc-windows-msvc` | Native Windows ABI; produces MSVC-compatible .dll | | `cargo-ndk` | N/A | Not needed for Windows; only Android needs it | | Opus library | bundled via `audiopus_sys` build script + cmake | On Windows there is no system libopus by default; we build it from source | | Git for Windows | latest | Convenient `git` + the bundled Bash for running `flutter` if needed | | 7-Zip (optional) | latest | Convenient for unpacking the source bundle if you uploaded it as zip | --- ## 3. Azure VM provisioning ### 3.1 Recommended SKU | Setting | Value | Rationale | |---|---|---| | Image | `Windows Server 2022 Datacenter — x64 Gen2` | Most common LTS Windows image | | Size | `Standard_D4s_v5` (4 vCPU, 16 GiB) or larger | The Cargo cold build pulls hundreds of crates; 4 cores keeps the build under 30 minutes | | OS disk | Premium SSD 128 GiB | Default 128 GiB is enough for VS 2022 (~10 GiB), Flutter SDK (~2 GiB), Rust toolchain (~1 GiB), source + build artefacts (~15 GiB) | | Auth | Password (you'll RDP in) | Sufficient for a short-lived build VM | | Inbound port rules | Allow **RDP (3389)** only from your IP | Lock RDP to your IP via NSG; never open to 0.0.0.0/0 | | Networking | New VNet + public IP | Standard for an ad-hoc build host | | Auto-shutdown | Enable, 19:00 local time | Stops you forgetting and burning hours | ### 3.2 Estimated cost `Standard_D4s_v5` in West US 2 is about **USD $0.20/hour** for the compute plus ~USD $0.01/hour for the disk. A first cold build (provision → install everything → compile → archive) is typically 2–3 hours. Total: under **USD $1** per build session if you deallocate after. > **Cost gotcha:** *Stopped (deallocated)* VMs do not bill for > compute; *Stopped* (in the OS shutdown sense, but not deallocated > in Azure) still bills compute. Always check the Azure portal shows > the VM as **Stopped (deallocated)**. ### 3.3 Provisioning checklist 1. Azure Portal → **Create a resource** → **Windows Server 2022 Datacenter (x64 Gen2)**. 2. Choose region near you. 3. Size: `Standard_D4s_v5`. 4. Administrator account: pick a username (e.g. `chanora`) + a strong password. 5. Inbound ports: RDP only, **restricted to your public IP**. 6. Disks: keep Premium SSD 128 GiB. 7. Networking: defaults; ensure auto-assign public IP. 8. Management → Auto-shutdown: **On**, time = end of your work day, notification = email. 9. Review + create. ### 3.4 First RDP login 1. Get the VM's public IP from the Azure portal. 2. RDP in as `chanora` / your password. 3. (Optional) Open Server Manager → Local Server → IE Enhanced Security Configuration → turn **Off** for Administrators so the downloads in §4 don't get blocked. --- ## 4. Install the toolchain (one-time per VM) Run all of these in an **elevated PowerShell** (right-click PowerShell → Run as Administrator). ### 4.1 Visual Studio 2022 Build Tools + workload ```powershell # Download the VS 2022 Build Tools bootstrapper Invoke-WebRequest -Uri 'https://aka.ms/vs/17/release/vs_buildtools.exe' ` -OutFile "$env:TEMP\vs_buildtools.exe" # Install with the C++ desktop workload (this is what Flutter requires). # --quiet suppresses UI; --wait blocks until done; takes 10-15 minutes. & "$env:TEMP\vs_buildtools.exe" --quiet --wait --norestart ` --add Microsoft.VisualStudio.Workload.VCTools ` --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ` --add Microsoft.VisualStudio.Component.Windows11SDK.22621 ` --add Microsoft.VisualStudio.Component.VC.CMake.Project ` --add Microsoft.VisualStudio.Component.VC.ATL ` --includeRecommended ``` When this completes, **reboot the VM** (Visual Studio Build Tools needs it for environment variables). ### 4.2 Git for Windows ```powershell winget install --id Git.Git --silent --accept-source-agreements --accept-package-agreements ``` ### 4.3 Rust (stable, with the MSVC target) ```powershell # Download rustup-init for Windows. Invoke-WebRequest -Uri 'https://win.rustup.rs/x86_64' ` -OutFile "$env:TEMP\rustup-init.exe" # Install the default toolchain (stable-x86_64-pc-windows-msvc). & "$env:TEMP\rustup-init.exe" -y --default-toolchain stable --profile minimal # Open a NEW PowerShell so PATH picks up cargo. # Then verify: cargo --version rustc --version ``` Expected output: `cargo 1.95.0` (or newer), `rustc 1.95.0`. The default target on Windows is `x86_64-pc-windows-msvc` — this is what we want. ### 4.4 Flutter SDK (pinned to 3.41.9 stable) ```powershell # Download Flutter SDK $flutter = 'https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.41.9-stable.zip' Invoke-WebRequest -Uri $flutter -OutFile "$env:TEMP\flutter.zip" Expand-Archive "$env:TEMP\flutter.zip" -DestinationPath 'C:\' # Add to PATH for the current user (persists across sessions). [Environment]::SetEnvironmentVariable( 'Path', [Environment]::GetEnvironmentVariable('Path', 'User') + ';C:\flutter\bin', 'User' ) # Open a NEW PowerShell so PATH applies, then: flutter --version flutter doctor ``` `flutter doctor` should show green on: - ✓ Flutter (Channel stable, 3.41.9, on Microsoft Windows …) - ✓ Windows Version (Windows … 10.0.20348 or later) - ✓ Visual Studio - develop Windows apps (Visual Studio Build Tools 2022 …) Yellow on Android Studio / Chrome is fine — we're only building Windows. ### 4.5 `flutter_rust_bridge_codegen` and Dart deps ```powershell cargo install flutter_rust_bridge_codegen --version "=2.12.0" ``` Takes ~5 minutes (compiles `flutter_rust_bridge_codegen` from source). ### 4.6 Opus build dependency The `audiopus` Rust crate wraps the C Opus library. On Windows there is no system Opus, so the `audiopus_sys` build script will attempt to build Opus from source via CMake (which the VS workload already provided). No extra action is required — but verify CMake is on PATH: ```powershell cmake --version ``` Expected: `cmake version 3.x` (any 3.x ≥ 3.18 is fine). If CMake is not found, install it explicitly: ```powershell winget install --id Kitware.CMake --silent ``` --- ## 5. Get the source onto the VM Two options. Pick whichever is easier for you. ### Option A — Push the repo to a temporary git remote On the Linux host where the repo lives: ```bash # E.g. create a private GitHub repo and push: git remote add origin https://github.com//chanora.git git push --all git push --tags ``` Then on the Windows VM: ```powershell cd C:\ git clone https://github.com//chanora.git cd chanora git checkout v0.2.0-beta.1 ``` ### Option B — Upload the source as a zip via RDP clipboard On Linux: ```bash cd /home/milkice git -C chanora archive --format=zip --output=/tmp/chanora-v0.2.0-beta.1.zip v0.2.0-beta.1 ``` Copy `/tmp/chanora-v0.2.0-beta.1.zip` into the RDP session (clipboard or shared drive), unzip into `C:\chanora\`. Either way, you end up with the working tree at `C:\chanora\`, checked out at the `v0.2.0-beta.1` tag. --- ## 6. Add the Windows platform to the Flutter app The product Flutter app was created with `--platforms=linux,android`, so the `windows/` platform folder does not yet exist. Add it once on the build VM: ```powershell cd C:\chanora\apps\chanora_flutter flutter create --platforms=windows . ``` This creates `apps/chanora_flutter/windows/` containing: ``` windows/ CMakeLists.txt flutter/ CMakeLists.txt generated_plugin_registrant.cc ... runner/ main.cpp Runner.rc chanora_flutter.exe.manifest ... ``` > **Important:** Do **not** commit this `windows/` folder back to the > repo from the VM unless you also do the corresponding edits the > source-of-truth host uses (icon, manifest, etc.). For Beta it is > fine to keep it VM-only. --- ## 7. Build the Rust cdylib for Windows ```powershell cd C:\chanora cargo build --release -p chanora_bridge ``` This builds the workspace, including: - The whole `tsclientlib` git dependency tree (slow first time — expect ~5–10 minutes for the first compile of `audiopus_sys` + `tsproto` etc.). - `chanora_bridge` as a `cdylib` + `staticlib` + `rlib`. Expected output location: ``` C:\chanora\target\release\chanora_bridge.dll ``` (Note: no `lib` prefix on Windows MSVC.) Verify: ```powershell Get-Item C:\chanora\target\release\chanora_bridge.dll | Format-List Name, Length, LastWriteTime ``` The DLL is typically ~16–18 MiB. --- ## 8. Regenerate the FRB bindings (optional — only if you changed the bridge API) The Linux build already produced `lib/src/rust/*.dart` and `crates/chanora_bridge/src/frb_generated.rs`. The bindings are platform-agnostic Dart + Rust source, so **they do not need regenerating on Windows**. Skip §8 unless you modified `crates/chanora_bridge/src/api.rs` after `v0.2.0-beta.1`. If you do need to regenerate: ```powershell cd C:\chanora flutter_rust_bridge_codegen generate ``` Takes ~5–10 minutes the first time on Windows. --- ## 9. Build the Flutter Windows binary ```powershell cd C:\chanora\apps\chanora_flutter flutter pub get flutter build windows --release ``` `flutter build windows`: 1. Invokes CMake on `apps/chanora_flutter/windows/`. 2. Builds `chanora_flutter.exe` via MSVC. 3. Bundles the Flutter engine DLL (`flutter_windows.dll`), ICU data, Dart-AOT-compiled `app.so` (delivered as `data\app.so`), the Flutter `data\` directory, and platform-specific resources. Build time: ~3–5 minutes on `Standard_D4s_v5` once dependencies are cached. Expected output location: ``` C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\ ``` Contents: | File | Size (approx) | Notes | |---|---|---| | `chanora_flutter.exe` | ~10 MiB | The launcher .exe | | `flutter_windows.dll` | ~17 MiB | Flutter engine | | `data\icudtl.dat` | ~10 MiB | Unicode tables | | `data\app.so` | varies | AOT-compiled Dart code | | `data\flutter_assets\` | varies | Images, fonts, ARB-derived .json | --- ## 10. Add the Rust DLL to the bundle The Flutter app loads `chanora_bridge.dll` at runtime via `dart:ffi`. Drop the DLL next to the .exe (the same directory): ```powershell $src = 'C:\chanora\target\release\chanora_bridge.dll' $dst = 'C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\' Copy-Item $src $dst -Force ``` Verify everything is in place: ```powershell Get-ChildItem $dst -Recurse | Select-Object FullName, Length | Format-Table -AutoSize ``` You should see: ``` C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\chanora_flutter.exe C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\chanora_bridge.dll C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\flutter_windows.dll C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\data\app.so C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\data\icudtl.dat C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\data\flutter_assets\... ``` --- ## 11. Smoke test on the VM Double-click `chanora_flutter.exe` (or `& '...\chanora_flutter.exe'` in PowerShell). The Beta UI should appear: - Banner: "Beta build — voice in/out wired; not production ready." - Form: `cn.teamspeak.app` + `ChanoraBeta` pre-populated. - Connect button. Press **Connect** → after a few seconds you should see the channel tree of `cn.teamspeak.app` (Vigorous Pro). Press **Start audio** → PTT button appears. Hold it to transmit (a Windows mic permission prompt may appear). > **Network gotcha:** Some Azure regions block UDP 9987 outbound by > default. If Connect times out, check the VM's NSG (outbound rules) > and the regional firewall. --- ## 12. Package the release artefact ```powershell $src = 'C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release' $out = 'C:\chanora-v0.2.0-beta.1-windows-x64.zip' Compress-Archive -Path "$src\*" -DestinationPath $out -Force Get-Item $out | Format-List Name, Length ``` Expected size: ~50–80 MiB. --- ## 13. Download to your local host From your local machine (Linux/macOS/Windows): ```bash # Use Azure CLI to copy via SAS, or just RDP the file out. # Simplest: in the RDP session enable clipboard file transfer # (mstsc /control or Remmina's "share local folder"), then drag the # zip out. ``` Or use Azure Blob Storage if you want versioned hosting. --- ## 14. Final artefact paths (what you actually produce) Inside the VM, after a successful build: | Artefact | Path on the VM | |---|---| | Bridge DLL | `C:\chanora\target\release\chanora_bridge.dll` | | Flutter EXE | `C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\chanora_flutter.exe` | | Complete runtime bundle | `C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\` | | Release zip | `C:\chanora-v0.2.0-beta.1-windows-x64.zip` | --- ## 15. After the build — deallocate the VM ```powershell # In the Azure CLI on your local host, OR via the portal: az vm deallocate --resource-group --name ``` Verify the portal says **Stopped (deallocated)**. --- ## 16. Known issues and caveats | Issue | Workaround | |---|---| | `audiopus_sys` build fails with "cmake not found" | Re-run §4.6's `winget install Kitware.CMake` and open a new PowerShell. | | `flutter build windows` complains about Long Paths | `Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Value 1`, then reboot. | | Microsoft Defender quarantines `chanora_bridge.dll` | Add `C:\chanora\target\release\` to Defender exclusions before the cargo build. | | The build VM cannot reach `cn.teamspeak.app` on UDP 9987 | Confirm Azure regional firewall allows outbound UDP. The Linux dev host's verification doesn't translate to Azure VMs automatically. | | First `cargo build` takes > 30 minutes | Normal. Subsequent builds reuse `target/` and are ~1 minute. | | `flutter pub get` fails behind a corporate proxy | Set `HTTPS_PROXY` and `HTTP_PROXY` environment variables before running. | | The `windows/` folder created by `flutter create` is missing icons | Replace `windows\runner\resources\app_icon.ico` with a Chanora icon. The default Flutter icon ships otherwise. Cosmetic only for Beta. | --- ## 17. Reproducibility note This build process is **not bit-reproducible** on Windows in the current state: - The `audiopus_sys` build script picks the CMake-discovered MSVC toolchain, which embeds its version into the DLL. - Dart AOT compilation embeds a Dart kernel hash. - Windows resource compilation embeds a build timestamp. If true reproducibility is required for a future External Beta or MVP Public release, that is Beta+ work; the build above is sufficient for an Internal Beta milestone per DEC-001. --- ## 18. Change History | Version | Date | Description | |---|---|---| | 0.1.0 | 2026-05-14 | Initial Windows build instructions for Chanora `v0.2.0-beta.1`. Targets Azure VM `Standard_D4s_v5` running Windows Server 2022, Visual Studio 2022 Build Tools with the C++ desktop workload, Rust 1.95 stable (`x86_64-pc-windows-msvc`), Flutter 3.41.9 stable, `flutter_rust_bridge` 2.12.0. Produces `chanora_flutter.exe` + `chanora_bridge.dll` packaged into `chanora-v0.2.0-beta.1-windows-x64.zip`. |