build(cmake): clean up presets, add release/apple presets, cross-platform triplets
Rationalize the preset set to match the project's actual state (past M5): - Rename dev->skeleton (no-deps stub smoke), m1-dev->dev (default dev preset) - Drop m2-dev (cache-identical to m1-dev) - Add release preset (optimized + tests on, symbols kept) - Strip server-release binaries (-s linker flag) - Add apple-dev/apple-ios/apple-ios-sim scaffolding presets for XCFramework Add cmake/voicecat-toolchain.cmake wrapper that auto-resolves the vcpkg triplet from the host platform (x64-mingw-static/x64-linux/arm64-osx) so the main presets work on Windows/Linux/macOS without per-OS variants. Update all docs (building.md, CLAUDE.md, README.md, AGENTS.md, deployment.md, tech-stack.md, client READMEs) and stale preset-name references in code comments. No C++ behavior changes — the core was already portable.
This commit is contained in:
154
docs/building.md
154
docs/building.md
@@ -4,28 +4,69 @@ This doc explains what each CMake preset in [`CMakePresets.json`](../CMakePreset
|
||||
*for*, which one to actually use day-to-day, and the commands to stand up a real server +
|
||||
`vccli` clients against each other for manual testing. For the one-paragraph quick-start see
|
||||
[`CLAUDE.md`](../CLAUDE.md); for `ctest` targets see [`AGENTS.md`](../AGENTS.md). This doc is
|
||||
the missing middle: *how the presets relate to each other*, and *how to drive the binaries by
|
||||
hand*.
|
||||
the missing middle: *how the presets relate to each other*, *which platform each targets*,
|
||||
and *how to drive the binaries by hand*.
|
||||
|
||||
## 1. What each preset is for
|
||||
|
||||
| Preset | Binary dir | Deps | What it's actually for |
|
||||
|--------|-----------|------|-------------------------|
|
||||
| `dev` | `build/dev` | none (`VOICECAT_USE_VCPKG_DEPS=OFF`) | The M0 skeleton. Compiles with just a C++20 compiler — no `VCPKG_ROOT` needed. Subsystems are stubs (`VC_ERR_NOT_IMPLEMENTED`). Good for "does the repo even build" sanity checks, not for testing real voice/control behavior. |
|
||||
| `vcpkg-base` | — | real deps via vcpkg | Hidden base preset, not used directly. Requires `VCPKG_ROOT` in the environment; every preset below inherits it. |
|
||||
| `m1-dev` | `build/m1-dev` | real deps | **The one you actually want.** Despite the name, this is the live development preset for everything from M1 onward — M1, M2, and M3 were all built, tested, and manually verified against `build/m1-dev` (see `PROGRESS.md`). Builds tools + tests. |
|
||||
| `m2-dev` | `build/m2-dev` | real deps | Cache-identical to `m1-dev` (same `VOICECAT_BUILD_TOOLS=ON`, `VOICECAT_BUILD_TESTS=ON`, same triplet) — the only difference is the binary dir. It exists from when the project briefly split a preset per milestone; that convention was dropped in practice. Use it only if you want a second, isolated build tree (e.g. to compare two branches) — there's no behavioral reason to prefer it over `m1-dev`. |
|
||||
| *(no `m3-dev`)* | — | — | M3 work used `m1-dev` directly; no separate preset was ever added for it. If you see `m3-dev` mentioned anywhere, it doesn't exist — use `m1-dev`. |
|
||||
| `server-release` | `build/server-release` | real deps, `Release` | Production-shaped build (docs/deployment.md "from source" path): `CMAKE_BUILD_TYPE=Release`, tools on, **tests off**. This is what you'd actually ship/run, not what you iterate against. |
|
||||
| Preset | Binary dir | Deps | Build type | Server | Tools | Tests | Strip | Platform | What it's for |
|
||||
|--------|-----------|------|------------|--------|-------|-------|-------|----------|---------------|
|
||||
| `vcpkg-common` | — | vcpkg | — | — | — | — | — | all | Hidden base. Sets the vcpkg toolchain wrapper ([`cmake/voicecat-toolchain.cmake`](../cmake/voicecat-toolchain.cmake)) which auto-resolves the triplet from the host platform. Not used directly. |
|
||||
| `skeleton` | `build/skeleton` | none | Debug | ON | ON | ON | no | all | The M0 skeleton. Compiles with just a C++20 compiler — no `VCPKG_ROOT` needed. Subsystems are stubs (`VC_ERR_NOT_IMPLEMENTED`). Good for "does the repo even build" sanity checks. Runs 2 tests (smoke + frame_codec). |
|
||||
| `dev` | `build/dev` | vcpkg | Debug | ON | ON | ON | no | all | **The one you actually want.** Day-to-day development: real protocol, crypto, voice, server — everything. Builds server + tools + tests (21 tests). Works on Windows, Linux, and macOS (triplet auto-resolved). |
|
||||
| `release` | `build/release` | vcpkg | Release | ON | ON | ON | no | all | Optimized build with the full test suite. Use to run tests against optimized code, profile, or catch optimizer-sensitive bugs. Symbols kept (not stripped) so stack traces and profiling remain useful. |
|
||||
| `server-release` | `build/server-release` | vcpkg | Release | ON | ON | OFF | **yes** | all | Production-shaped build for deployment. Optimized + stripped binaries (`-s`), no tests. This is what you'd ship/run — see [docs/deployment.md](deployment.md). |
|
||||
| `windows-client` | `build/windows-client` | vcpkg | Release | OFF | OFF | OFF | no | Windows | Produces a redistributable `voicecat.dll` for the C# WinForms client (M4). Static MinGW runtime — no `libgcc_s_seh-1.dll` etc. See [clients/windows/README.md](../clients/windows/README.md). |
|
||||
| `apple-dev` | `build/apple-dev` | vcpkg | Release | OFF | OFF | OFF | no | macOS | **Scaffolding** — static `libvoicecat.a` for the Swift Package / XCFramework (macOS slice). Not yet CI-validated; build on macOS to verify. See [clients/apple/README.md](../clients/apple/README.md). |
|
||||
| `apple-ios` | `build/apple-ios` | vcpkg | Release | OFF | OFF | OFF | no | macOS→iOS | **Scaffolding** — cross-compiled static `libvoicecat.a` for iOS device (`arm64-ios`). One XCFramework slice. Not yet CI-validated. |
|
||||
| `apple-ios-sim` | `build/apple-ios-sim` | vcpkg | Release | OFF | OFF | OFF | no | macOS→iOS sim | **Scaffolding** — cross-compiled static `libvoicecat.a` for iOS simulator (`arm64-ios-sim`). One XCFramework slice. Not yet CI-validated. |
|
||||
|
||||
So in practice there are really only two presets that matter:
|
||||
- **`dev`** — fast no-deps build to confirm the skeleton compiles.
|
||||
- **`m1-dev`** — everything else: real protocol, real voice, real manual testing.
|
||||
So in practice there are three presets that matter for day-to-day work:
|
||||
- **`dev`** — everything: real protocol, real voice, real manual testing. This is the loop you run constantly.
|
||||
- **`release`** — same suite, optimized. Run it when you want to check optimized behavior or profile.
|
||||
- **`skeleton`** — fast no-deps build to confirm the stub path still compiles (CI smoke check).
|
||||
|
||||
The rest are purpose-specific: `server-release` for deployment, `windows-client` for the DLL,
|
||||
`apple-*` for Apple platform slices.
|
||||
|
||||
### Platform matrix
|
||||
|
||||
The vcpkg presets (`dev`, `release`, `server-release`, `windows-client`, `apple-*`) auto-resolve
|
||||
the vcpkg triplet via [`cmake/voicecat-toolchain.cmake`](../cmake/voicecat-toolchain.cmake):
|
||||
|
||||
| Host platform | Auto-resolved triplet | Notes |
|
||||
|---------------|----------------------|-------|
|
||||
| Windows (MinGW/MSYS2) | `x64-mingw-static` | The project's Windows toolchain. MSVC users must set `VCPKG_TARGET_TRIPLET=x64-windows` explicitly. |
|
||||
| Linux x64 | `x64-linux` | Server's primary deployment target (Docker, systemd). |
|
||||
| Linux arm64 | `arm64-linux` | Raspberry Pi / ARM VPS. |
|
||||
| macOS (Apple Silicon) | `arm64-osx` | `apple-dev` uses this automatically. |
|
||||
| macOS (Intel) | `x64-osx` | `apple-dev` uses this automatically. |
|
||||
|
||||
Cross-compile presets (`apple-ios`, `apple-ios-sim`) override `VCPKG_TARGET_TRIPLET` explicitly;
|
||||
`VCPKG_HOST_TRIPLET` stays the host's (e.g. `arm64-osx` when building iOS on Apple Silicon).
|
||||
|
||||
### Preset history
|
||||
|
||||
The preset set was cleaned up on 2026-06-18 (see `PROGRESS.md`). The old names map as follows:
|
||||
|
||||
| Old name | New name | Notes |
|
||||
|----------|----------|-------|
|
||||
| `dev` | `skeleton` | Renamed to reflect its actual purpose (no-deps stub smoke check). |
|
||||
| `m1-dev` | `dev` | Renamed — the project is past M5, so milestone-named presets were misleading. This is now the default development preset. |
|
||||
| `m2-dev` | *(dropped)* | Was cache-identical to `m1-dev` (same flags, same triplet, only the binary dir differed). Removed. |
|
||||
| `server-release` | `server-release` | Unchanged name; now stripped (`-s`) and auto-triplet. |
|
||||
| *(new)* | `release` | New: optimized build with tests on, symbols kept. |
|
||||
| `windows-client` | `windows-client` | Unchanged name; triplet now auto-resolved. |
|
||||
| *(new)* | `apple-dev`, `apple-ios`, `apple-ios-sim` | New: Apple platform scaffolding. |
|
||||
|
||||
If you see `m1-dev` or `m2-dev` in old scripts, commits, or `PROGRESS.md` history entries,
|
||||
use `dev` instead. Historical `PROGRESS.md` entries are left intact as a true record of what
|
||||
was run.
|
||||
|
||||
## 2. One-time setup for the real-deps presets
|
||||
|
||||
`m1-dev`, `m2-dev`, and `server-release` all need `VCPKG_ROOT` pointing at a bootstrapped
|
||||
vcpkg checkout:
|
||||
`dev`, `release`, `server-release`, `windows-client`, and `apple-*` all need `VCPKG_ROOT`
|
||||
pointing at a bootstrapped vcpkg checkout:
|
||||
|
||||
```bash
|
||||
# once:
|
||||
@@ -34,34 +75,44 @@ git clone https://github.com/microsoft/vcpkg
|
||||
|
||||
# every shell session (PowerShell):
|
||||
$env:VCPKG_ROOT = "D:\path\to\vcpkg"
|
||||
|
||||
# or on Linux/macOS:
|
||||
export VCPKG_ROOT=/path/to/vcpkg
|
||||
```
|
||||
|
||||
`vcpkg.json` (manifest mode) pins every dependency (protobuf, mbedTLS, libsodium, asio,
|
||||
sqlite3, spdlog, opus, miniaudio) — `cmake --preset m1-dev` resolves and builds them
|
||||
sqlite3, spdlog, opus, miniaudio) — `cmake --preset dev` resolves and builds them
|
||||
automatically on first configure. That first configure is slow (vcpkg building from source);
|
||||
subsequent ones are cached.
|
||||
|
||||
## 3. Build + test (the loop you'll run constantly)
|
||||
|
||||
```bash
|
||||
cmake --preset m1-dev
|
||||
cmake --build --preset m1-dev
|
||||
ctest --test-dir build/m1-dev --output-on-failure
|
||||
cmake --preset dev
|
||||
cmake --build --preset dev
|
||||
ctest --preset dev
|
||||
```
|
||||
|
||||
(`ctest --preset m1-dev` is equivalent — both are wired up in `CMakePresets.json`.) Binaries
|
||||
land in `build/m1-dev/bin/` (`.exe` suffix on Windows):
|
||||
Binaries land in `build/dev/bin/` (`.exe` suffix on Windows):
|
||||
|
||||
- `build/m1-dev/bin/voicecat-server`
|
||||
- `build/m1-dev/bin/vccli`
|
||||
- `build/m1-dev/bin/voicecat-admin`
|
||||
- `build/dev/bin/voicecat-server`
|
||||
- `build/dev/bin/vccli`
|
||||
- `build/dev/bin/voicecat-admin`
|
||||
|
||||
To run the same suite against optimized code:
|
||||
|
||||
```bash
|
||||
cmake --preset release
|
||||
cmake --build --preset release
|
||||
ctest --preset release
|
||||
```
|
||||
|
||||
## 4. Manual testing: server + two clients
|
||||
|
||||
### Start the server
|
||||
|
||||
```bash
|
||||
./build/m1-dev/bin/voicecat-server --name "Test Server" --data-dir ./voicecat-data
|
||||
./build/dev/bin/voicecat-server --name "Test Server" --data-dir ./voicecat-data
|
||||
```
|
||||
|
||||
First run generates an Ed25519 identity + self-signed cert under `--data-dir`, creates the
|
||||
@@ -105,20 +156,20 @@ toggle the input gate live.
|
||||
|
||||
```bash
|
||||
# terminal A
|
||||
./build/m1-dev/bin/vccli --nick Alice --text "hello from Alice"
|
||||
./build/dev/bin/vccli --nick Alice --text "hello from Alice"
|
||||
|
||||
# terminal B (separate window, after A confirms it sent)
|
||||
./build/m1-dev/bin/vccli --nick Bob --text "hello from Bob"
|
||||
./build/dev/bin/vccli --nick Bob --text "hello from Bob"
|
||||
```
|
||||
|
||||
**Real voice between two clients (needs working mic/speakers, two terminals):**
|
||||
|
||||
```bash
|
||||
# terminal A
|
||||
./build/m1-dev/bin/vccli --nick Alice --voice
|
||||
./build/dev/bin/vccli --nick Alice --voice
|
||||
|
||||
# terminal B
|
||||
./build/m1-dev/bin/vccli --nick Bob --voice
|
||||
./build/dev/bin/vccli --nick Bob --voice
|
||||
```
|
||||
|
||||
Speak into the mic on one side; you should hear it on the other. Ctrl+C to disconnect.
|
||||
@@ -126,21 +177,22 @@ Speak into the mic on one side; you should hear it on the other. Ctrl+C to disco
|
||||
**Enumerate audio devices before picking one:**
|
||||
|
||||
```bash
|
||||
./build/m1-dev/bin/vccli --list-devices
|
||||
./build/m1-dev/bin/vccli --nick Alice --voice --input-device <ID> --input-mode ptt
|
||||
./build/dev/bin/vccli --list-devices
|
||||
./build/dev/bin/vccli --nick Alice --voice --input-device <ID> --input-mode ptt
|
||||
```
|
||||
|
||||
**Provisioning a non-guest account** (if the server was started with `--no-guests`):
|
||||
|
||||
```bash
|
||||
./build/m1-dev/bin/voicecat-admin --data-dir ./voicecat-data account add alice --password secret
|
||||
./build/m1-dev/bin/voicecat-admin --data-dir ./voicecat-data account list
|
||||
./build/dev/bin/voicecat-admin --data-dir ./voicecat-data account add alice --password secret
|
||||
./build/dev/bin/voicecat-admin --data-dir ./voicecat-data account list
|
||||
```
|
||||
|
||||
## 5. `server-release` (production-shaped build)
|
||||
|
||||
Same dependency story, but `Release` build type and no tests — this is the closest local
|
||||
analogue to what `docs/deployment.md`'s "from source" path produces:
|
||||
Same dependency story, but `Release` build type, stripped binaries, and no tests — this is the
|
||||
closest local analogue to what [docs/deployment.md](deployment.md)'s "from source" path
|
||||
produces:
|
||||
|
||||
```bash
|
||||
cmake --preset server-release
|
||||
@@ -149,4 +201,34 @@ cmake --build --preset server-release
|
||||
```
|
||||
|
||||
Use this to sanity-check release-mode behavior (e.g. perf, optimized codepaths) — not for
|
||||
day-to-day development, since it has no test target wired up.
|
||||
day-to-day development, since it has no test target wired up. The `-s` linker flag strips
|
||||
symbol tables from the binaries, producing smaller executables suitable for distribution.
|
||||
|
||||
## 6. Apple platform builds (scaffolding)
|
||||
|
||||
The `apple-dev`, `apple-ios`, and `apple-ios-sim` presets produce static `libvoicecat.a`
|
||||
slices for the Swift Package / XCFramework. They are **scaffolding** — not yet CI-validated
|
||||
and won't build on Windows. Build on macOS:
|
||||
|
||||
```bash
|
||||
# macOS slice (arm64-osx on Apple Silicon, x64-osx on Intel)
|
||||
cmake --preset apple-dev
|
||||
cmake --build --preset apple-dev
|
||||
# → build/apple-dev/lib/libvoicecat.a
|
||||
|
||||
# iOS device slice
|
||||
cmake --preset apple-ios
|
||||
cmake --build --preset apple-ios
|
||||
# → build/apple-ios/lib/libvoicecat.a
|
||||
|
||||
# iOS simulator slice
|
||||
cmake --preset apple-ios-sim
|
||||
cmake --build --preset apple-ios-sim
|
||||
# → build/apple-ios-sim/lib/libvoicecat.a
|
||||
```
|
||||
|
||||
The three `.a` files are then stitched into an XCFramework via `xcodebuild
|
||||
-create-xcframework` (see [clients/apple/README.md](../clients/apple/README.md) for the
|
||||
planned workflow). Actual XCFramework stitching, `AVAudioSession` integration, and iOS
|
||||
UI work are tracked as follow-up tasks — the presets exist so the build entry point is ready
|
||||
when that work starts.
|
||||
|
||||
@@ -38,12 +38,15 @@ package manager. Linux (primary), macOS, and Windows builds.
|
||||
|
||||
```bash
|
||||
git clone … && cd voice-cat
|
||||
cmake --preset server-release # vcpkg fetches & pins all deps
|
||||
cmake --preset server-release # vcpkg fetches & pins all deps; auto-triplet (Linux/macOS/Windows)
|
||||
cmake --build --preset server-release
|
||||
./build/voicecat-server
|
||||
./build/server-release/bin/voicecat-server
|
||||
```
|
||||
|
||||
One `cmake` invocation; vcpkg (manifest mode) resolves the dependency graph reproducibly.
|
||||
The `server-release` preset produces an optimized, **stripped** binary (`-s` linker flag) —
|
||||
smaller executables suitable for distribution. Works on Linux (primary), macOS, and Windows;
|
||||
the vcpkg triplet is auto-resolved by [`cmake/voicecat-toolchain.cmake`](../cmake/voicecat-toolchain.cmake).
|
||||
No system packages to chase.
|
||||
|
||||
## 2. Zero-config defaults
|
||||
|
||||
@@ -58,7 +58,7 @@ explicit resampling (speexdsp/libsamplerate) is only needed when a device can't
|
||||
| Tool | Use |
|
||||
|------|-----|
|
||||
| **CMake** (3.25+) | One build graph for core + server + test CLI; UI projects consume the built core. |
|
||||
| **vcpkg** (manifest mode) | Pin C/C++ deps (opus, libsodium, mbedtls, protobuf, sqlite3, spdlog, asio, miniaudio — see `vcpkg.json`). `webrtc-audio-processing`/`speexdsp` are **not** in the manifest: no working vcpkg port / no working Windows/MSVC build exists upstream for the former; the latter was never actually wired up (the lightweight VAD needs no resampler). Reproducible across OSes. |
|
||||
| **vcpkg** (manifest mode) | Pin C/C++ deps (opus, libsodium, mbedtls, protobuf, sqlite3, spdlog, asio, miniaudio — see `vcpkg.json`). `webrtc-audio-processing`/`speexdsp` are **not** in the manifest: no working vcpkg port / no working Windows/MSVC build exists upstream for the former; the latter was never actually wired up (the lightweight VAD needs no resampler). Reproducible across OSes. Triplet auto-resolved from the host platform by [`cmake/voicecat-toolchain.cmake`](../cmake/voicecat-toolchain.cmake) — `x64-mingw-static` on Windows, `x64-linux` on Linux, `arm64-osx` on Apple Silicon. Apple platform scaffolding presets (`apple-dev`/`apple-ios`/`apple-ios-sim`) produce static `libvoicecat.a` slices for XCFramework consumption. |
|
||||
| **protoc** | Generate C++/C#/Swift from `core/proto/*.proto` (single source of truth). |
|
||||
| **clang-format / clang-tidy** | Style + static analysis on the core. |
|
||||
| **CTest + a fuzz target** | Unit/integration tests; fuzz the frame parser and protobuf boundary (security-sensitive). |
|
||||
|
||||
Reference in New Issue
Block a user