From bcb7ae8ccbb92ad648eb2534f51e74ae70a64486 Mon Sep 17 00:00:00 2001 From: Talon Date: Thu, 18 Jun 2026 03:16:01 +0200 Subject: [PATCH] build(cmake): clean up presets, add release/apple presets, cross-platform triplets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- AGENTS.md | 29 ++++-- CLAUDE.md | 38 +++++--- CMakePresets.json | 142 +++++++++++++++++---------- PROGRESS.md | 43 +++++++++ README.md | 35 ++++--- clients/apple/README.md | 37 +++++++ clients/windows/README.md | 6 +- cmake/voicecat-toolchain.cmake | 72 ++++++++++++++ core/include/voicecat.h | 6 +- core/src/net/transport.h | 5 +- core/src/protocol/protocol.h | 2 +- core/src/voicecat.cpp | 4 +- docs/building.md | 154 +++++++++++++++++++++++------- docs/deployment.md | 7 +- docs/tech-stack.md | 2 +- server/src/server.cpp | 2 +- tests/CMakeLists.txt | 2 +- tests/test_envelope.cpp | 2 +- tests/test_frame_codec.cpp | 2 +- tests/test_opus_codec.cpp | 2 +- tests/test_smoke.cpp | 2 +- tests/test_tcp_loopback.cpp | 2 +- tools/voicecat-admin/src/main.cpp | 2 +- 23 files changed, 454 insertions(+), 144 deletions(-) create mode 100644 cmake/voicecat-toolchain.cmake diff --git a/AGENTS.md b/AGENTS.md index e41b7da..e9d90b0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,9 +11,11 @@ Read those, then use the method below. ## What this repo is right now -A complete **design** ([`docs/`](docs/)) plus an **M0 skeleton**: it compiles and links, but -`libvoicecat`'s subsystems are stubs that return `VC_ERR_NOT_IMPLEMENTED`. Your job is to turn -the design into working software, one milestone at a time. +A complete **design** ([`docs/`](docs/)) plus a working implementation through M5: real TLS +control plane, encrypted UDP voice (Opus), multi-stream, TOFU identity pinning, channel tree, +permissions, moderation, disconnect/keepalive/reaper. The Windows WinForms C# client is +shipped (M4). The macOS/iOS Swift client is next. The `skeleton` preset still links a +no-deps stub path (`VC_ERR_NOT_IMPLEMENTED`) for smoke-check builds. ## The working method (important) @@ -36,24 +38,31 @@ making progress. ## Build -Skeleton (no third-party deps — works immediately): +Default development preset (real deps via vcpkg — works on Windows/Linux/macOS): ```bash +export VCPKG_ROOT=/path/to/vcpkg # bootstrap vcpkg first; cross-platform cmake --preset dev cmake --build --preset dev ctest --preset dev ``` -When a subsystem needs real libraries, turn on vcpkg deps: +Skeleton (no third-party deps — works immediately, no vcpkg needed): ```bash -export VCPKG_ROOT=/path/to/vcpkg # bootstrap vcpkg first; cross-platform -cmake --preset server-release # installs deps pinned in vcpkg.json -cmake --build --preset server-release +cmake --preset skeleton +cmake --build --preset skeleton +ctest --preset skeleton ``` -`vcpkg.json` currently has a placeholder `builtin-baseline` — set it to a real vcpkg commit -SHA the first time you enable `VOICECAT_USE_VCPKG_DEPS`. +Other presets: `release` (optimized + tests), `server-release` (optimized + stripped, +deployment-shaped), `windows-client` (DLL for C# app), `apple-dev`/`apple-ios`/ +`apple-ios-sim` (Apple platform scaffolding). See [`docs/building.md`](docs/building.md) +for the full matrix. + +`vcpkg.json` pins all deps to a fixed vcpkg baseline — `cmake --preset dev` resolves them +automatically on first configure. The vcpkg triplet is auto-resolved from the host platform +by [`cmake/voicecat-toolchain.cmake`](cmake/voicecat-toolchain.cmake). ## Where each subsystem lives (and its doc) diff --git a/CLAUDE.md b/CLAUDE.md index 0472794..de87771 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,11 +4,10 @@ Auto-loaded each session. This is the **map**: build commands, architecture at a where everything is. For the *working method* read [`AGENTS.md`](AGENTS.md); for *what's done and what's next* read [`PROGRESS.md`](PROGRESS.md); for *design* read [`docs/`](docs/). -> **One-line status:** M4 (Windows WinForms C# client) is complete — connect, saved servers, -> TOFU identity pinning, channel tree, voice (VAD/PTT/always-on + VAD threshold slider + -> per-user tuning), text chat, device pickers, level meters. `ctest --preset m1-dev` green — -> 14/14 tests. `dotnet build` green — 0 warnings. macOS/iOS Swift client and M5 (moderation) -> are next. See [`PROGRESS.md`](PROGRESS.md). +> **One-line status:** M5 (moderation & admin UI) is complete — permissions, kick/ban/move, +> server-mute, channel CRUD, in-app account management, disconnect/keepalive/reaper. Windows +> WinForms C# client is shipped (M4). `ctest --preset dev` green — 21/21 tests. macOS/iOS +> Swift client is next. See [`PROGRESS.md`](PROGRESS.md). VoiceCat = self-hosted native voice & text chat (TeamSpeak/Mumble-style). Plain TCP (control) + UDP (media), no WebRTC, encrypted by default. A shared C++ core (`libvoicecat`) drives @@ -18,15 +17,16 @@ native clients (Swift on macOS/iOS, C# on Windows) and the server. ## Build & test commands -The **M0 skeleton builds with no third-party dependencies** — just CMake + Ninja + a C++20 -compiler. Deps (vcpkg) are off until a subsystem needs them. +The default development preset is **`dev`** — it builds everything (server + tools + tests) +with real vcpkg deps. The `skeleton` preset (no deps, stubs only) is a fast smoke check; see +[`docs/building.md`](docs/building.md) for the full preset matrix. ```bash -# Configure + build the skeleton (default; no vcpkg needed) +# Configure + build (default development preset; needs VCPKG_ROOT) cmake --preset dev cmake --build --preset dev -# Run the tests (behavior smoke test today; grows per milestone) +# Run the tests (21 behavior tests — grows per milestone) ctest --preset dev # or: ctest --test-dir build/dev --output-on-failure # Run the binaries (Windows adds .exe; Linux/macOS no extension) @@ -43,14 +43,26 @@ rm -rf build/dev # nuke; or: cmake --build --preset dev --target clean ``` -When you start a subsystem that needs real libraries (mbedTLS, libsodium, opus, protobuf, …), -turn vcpkg deps on: +Other presets (see [`docs/building.md`](docs/building.md) for full detail): + +```bash +cmake --preset skeleton # no-deps stub smoke (no VCPKG_ROOT needed) — 2 tests +cmake --preset release # optimized + tests on, symbols kept (profile/debug-friendly) +cmake --preset server-release # optimized + stripped, no tests (deployment-shaped) +cmake --preset windows-client # voicecat.dll for the C# WinForms client (Windows only) +cmake --preset apple-dev # libvoicecat.a for macOS Swift Package (scaffolding, macOS only) +``` + +Vcpkg triplet is 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. See docs/building.md §1 +"Platform matrix" for details. + +One-time vcpkg setup: ```bash # one-time: git clone https://github.com/microsoft/vcpkg && ./vcpkg/bootstrap-vcpkg.sh (.bat on Windows) export VCPKG_ROOT=/path/to/vcpkg # works on Linux / macOS / Windows -cmake --preset server-release # auto-installs deps pinned in vcpkg.json -cmake --build --preset server-release ``` Other useful toggles (pass with `-D` at configure time): diff --git a/CMakePresets.json b/CMakePresets.json index 6551f2c..6b480ee 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -3,93 +3,137 @@ "cmakeMinimumRequired": { "major": 3, "minor": 25, "patch": 0 }, "configurePresets": [ { - "name": "dev", - "displayName": "Dev (skeleton, no third-party deps)", - "description": "Builds the stub skeleton with just a compiler. Works out of the box; no vcpkg required.", + "name": "vcpkg-common", + "hidden": true, + "description": "Shared base for all presets that link real deps via vcpkg. Uses cmake/voicecat-toolchain.cmake, which auto-resolves VCPKG_TARGET_TRIPLET / VCPKG_HOST_TRIPLET from the host platform (x64-mingw-static on Windows, x64-linux on Linux, arm64-osx on Apple Silicon). Cross-compile presets override VCPKG_TARGET_TRIPLET in their cacheVariables. Requires VCPKG_ROOT in the environment.", "generator": "Ninja", - "binaryDir": "${sourceDir}/build/dev", + "toolchainFile": "${sourceDir}/cmake/voicecat-toolchain.cmake", + "cacheVariables": { + "VOICECAT_USE_VCPKG_DEPS": "ON" + } + }, + { + "name": "skeleton", + "displayName": "Skeleton (no third-party deps)", + "description": "Builds the stub skeleton with just a C++20 compiler — no vcpkg needed. Subsystems return VC_ERR_NOT_IMPLEMENTED. Good for 'does the repo even build' smoke checks. Runs 2 tests (smoke + frame_codec).", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/skeleton", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "VOICECAT_USE_VCPKG_DEPS": "OFF" } }, { - "name": "vcpkg-base", - "hidden": true, - "description": "Shared base for presets that link real deps via vcpkg. Requires VCPKG_ROOT in the environment.", - "generator": "Ninja", - "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", - "cacheVariables": { "VOICECAT_USE_VCPKG_DEPS": "ON" } - }, - { - "name": "m1-dev", - "inherits": "vcpkg-base", - "displayName": "M1 Dev (TLS control plane, deps via vcpkg)", - "description": "Active development preset for M1+. Requires VCPKG_ROOT env var pointing to a bootstrapped vcpkg. Set VCPKG_ROOT=D:\\code\\nvgt\\vcpkg\\bin (or wherever your vcpkg is).", - "binaryDir": "${sourceDir}/build/m1-dev", + "name": "dev", + "displayName": "Dev (full real-deps build, vcpkg)", + "description": "Day-to-day development preset. Real protocol, crypto, voice, server — everything from M1 onward. Builds server + tools + tests (21 tests). Auto-triplet: x64-mingw-static on Windows, x64-linux on Linux, arm64-osx on Apple Silicon. Requires VCPKG_ROOT.", + "inherits": "vcpkg-common", + "binaryDir": "${sourceDir}/build/dev", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", - "VOICECAT_USE_VCPKG_DEPS": "ON", "VOICECAT_BUILD_TOOLS": "ON", - "VOICECAT_BUILD_TESTS": "ON", - "VCPKG_TARGET_TRIPLET": "x64-mingw-static", - "VCPKG_HOST_TRIPLET": "x64-mingw-static" + "VOICECAT_BUILD_TESTS": "ON" } }, { - "name": "m2-dev", - "inherits": "vcpkg-base", - "displayName": "M2 Dev (voice + media, deps via vcpkg)", - "description": "Active development preset for M2+. Requires VCPKG_ROOT env var pointing to a bootstrapped vcpkg. Set VCPKG_ROOT=D:\\code\\nvgt\\vcpkg\\bin (or wherever your vcpkg is).", - "binaryDir": "${sourceDir}/build/m2-dev", + "name": "release", + "displayName": "Release (optimized, tests on, symbols kept)", + "description": "Optimized build with the full test suite enabled. Use to run tests against optimized code, profile, or catch optimizer-sensitive bugs. Symbols are kept (not stripped) so stack traces and profiling remain useful. Auto-triplet. Requires VCPKG_ROOT.", + "inherits": "vcpkg-common", + "binaryDir": "${sourceDir}/build/release", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "VOICECAT_USE_VCPKG_DEPS": "ON", + "CMAKE_BUILD_TYPE": "Release", "VOICECAT_BUILD_TOOLS": "ON", - "VOICECAT_BUILD_TESTS": "ON", - "VCPKG_TARGET_TRIPLET": "x64-mingw-static", - "VCPKG_HOST_TRIPLET": "x64-mingw-static" + "VOICECAT_BUILD_TESTS": "ON" } }, { "name": "server-release", - "inherits": "vcpkg-base", - "displayName": "Server (release, real deps)", + "displayName": "Server Release (optimized, stripped, no tests)", + "description": "Production-shaped build for deployment. Optimized (Release) with stripped binaries (-s linker flag), no tests. This is what you'd ship/run — see docs/deployment.md. Auto-triplet. Requires VCPKG_ROOT.", + "inherits": "vcpkg-common", "binaryDir": "${sourceDir}/build/server-release", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release", "VOICECAT_BUILD_TOOLS": "ON", - "VCPKG_TARGET_TRIPLET": "x64-mingw-static" + "VOICECAT_BUILD_TESTS": "OFF", + "CMAKE_EXE_LINKER_FLAGS": "-s", + "CMAKE_SHARED_LINKER_FLAGS": "-s" } }, { "name": "windows-client", - "inherits": "vcpkg-base", - "displayName": "Windows client (shared libvoicecat.dll for the C# WinForms app, M4)", - "description": "Produces a redistributable Release voicecat.dll with no MinGW runtime DLL dependencies (see core/CMakeLists.txt's static-runtime link flags and clients/windows/README.md). Tools/tests are off — this preset exists only to build the DLL.", + "displayName": "Windows client (voicecat.dll for C# WinForms, M4)", + "description": "Produces a redistributable Release voicecat.dll with no MinGW runtime DLL dependencies (see core/CMakeLists.txt's static-runtime link flags and clients/windows/README.md). Server/tools/tests are off — this preset exists only to build the DLL. Windows only.", + "inherits": "vcpkg-common", "binaryDir": "${sourceDir}/build/windows-client", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release", - "VOICECAT_USE_VCPKG_DEPS": "ON", "VOICECAT_BUILD_SHARED": "ON", "VOICECAT_BUILD_SERVER": "OFF", "VOICECAT_BUILD_TOOLS": "OFF", - "VOICECAT_BUILD_TESTS": "OFF", - "VCPKG_TARGET_TRIPLET": "x64-mingw-static", - "VCPKG_HOST_TRIPLET": "x64-mingw-static" + "VOICECAT_BUILD_TESTS": "OFF" + } + }, + { + "name": "apple-dev", + "displayName": "Apple macOS (libvoicecat.a for Swift Package, scaffolding)", + "description": "SCAFFOLDING — not yet CI-validated; build on macOS to verify. Produces a static libvoicecat.a for macOS (arm64-osx on Apple Silicon, x64-osx on Intel) for consumption by the Swift Package / XCFramework. Server/tools/tests off. Requires VCPKG_ROOT.", + "inherits": "vcpkg-common", + "binaryDir": "${sourceDir}/build/apple-dev", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "VOICECAT_BUILD_SERVER": "OFF", + "VOICECAT_BUILD_TOOLS": "OFF", + "VOICECAT_BUILD_TESTS": "OFF" + } + }, + { + "name": "apple-ios", + "displayName": "Apple iOS device (XCFramework slice, scaffolding)", + "description": "SCAFFOLDING — not yet CI-validated; build on macOS to verify. Cross-compiles a static libvoicecat.a for iOS device (arm64-ios). One slice of the XCFramework. Server/tools/tests off. Requires VCPKG_ROOT and a macOS host with iOS SDK.", + "inherits": "vcpkg-common", + "binaryDir": "${sourceDir}/build/apple-ios", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_SYSTEM_NAME": "iOS", + "CMAKE_SYSTEM_PROCESSOR": "arm64", + "VCPKG_TARGET_TRIPLET": "arm64-ios", + "VOICECAT_BUILD_SERVER": "OFF", + "VOICECAT_BUILD_TOOLS": "OFF", + "VOICECAT_BUILD_TESTS": "OFF" + } + }, + { + "name": "apple-ios-sim", + "displayName": "Apple iOS simulator (XCFramework slice, scaffolding)", + "description": "SCAFFOLDING — not yet CI-validated; build on macOS to verify. Cross-compiles a static libvoicecat.a for iOS simulator (arm64-ios-sim on Apple Silicon). One slice of the XCFramework. Server/tools/tests off. Requires VCPKG_ROOT and a macOS host with iOS simulator SDK.", + "inherits": "vcpkg-common", + "binaryDir": "${sourceDir}/build/apple-ios-sim", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_SYSTEM_NAME": "iOS", + "CMAKE_SYSTEM_PROCESSOR": "arm64", + "VCPKG_TARGET_TRIPLET": "arm64-ios-sim", + "VOICECAT_BUILD_SERVER": "OFF", + "VOICECAT_BUILD_TOOLS": "OFF", + "VOICECAT_BUILD_TESTS": "OFF" } } ], "buildPresets": [ - { "name": "dev", "configurePreset": "dev" }, - { "name": "m1-dev", "configurePreset": "m1-dev" }, - { "name": "m2-dev", "configurePreset": "m2-dev" }, - { "name": "server-release", "configurePreset": "server-release" }, - { "name": "windows-client", "configurePreset": "windows-client" } + { "name": "skeleton", "configurePreset": "skeleton" }, + { "name": "dev", "configurePreset": "dev" }, + { "name": "release", "configurePreset": "release" }, + { "name": "server-release", "configurePreset": "server-release" }, + { "name": "windows-client", "configurePreset": "windows-client" }, + { "name": "apple-dev", "configurePreset": "apple-dev" }, + { "name": "apple-ios", "configurePreset": "apple-ios" }, + { "name": "apple-ios-sim", "configurePreset": "apple-ios-sim" } ], "testPresets": [ - { "name": "dev", "configurePreset": "dev", "output": { "outputOnFailure": true } }, - { "name": "m1-dev", "configurePreset": "m1-dev", "output": { "outputOnFailure": true } }, - { "name": "m2-dev", "configurePreset": "m2-dev", "output": { "outputOnFailure": true } } + { "name": "skeleton", "configurePreset": "skeleton", "output": { "outputOnFailure": true } }, + { "name": "dev", "configurePreset": "dev", "output": { "outputOnFailure": true } }, + { "name": "release", "configurePreset": "release", "output": { "outputOnFailure": true } } ] } diff --git a/PROGRESS.md b/PROGRESS.md index 256f6a7..a3bc338 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -10,6 +10,49 @@ up instantly. Newest status at the top. ## ▶ Where we left off / next action +- **Done:** **CMake preset cleanup + cross-platform build config** (2026-06-18). The preset + set was a mess — `dev` (never used), `m1-dev` (the one everyone used), `m2-dev` + (cache-identical to `m1-dev`, never used), no optimized+tests preset, no stripping. + Cleaned up to a sensible set + added cross-platform triplet auto-resolution + Apple + platform scaffolding: + - **Renames:** `dev`→`skeleton` (no-deps stub smoke — accurately named now); `m1-dev`→`dev` + (the default development preset — milestone-named presets were misleading since the + project is past M5); `m2-dev` **dropped** (cache-identical to `m1-dev`). + - **New presets:** `release` (optimized Release + tests on, symbols kept — run the suite + against optimized code or profile); `apple-dev` / `apple-ios` / `apple-ios-sim` + (scaffolding — static `libvoicecat.a` slices for the Swift Package / XCFramework; marked + "not yet CI-validated, build on macOS to verify"). + - **`server-release`** now strips binaries (`CMAKE_EXE_LINKER_FLAGS=-s` + + `CMAKE_SHARED_LINKER_FLAGS=-s`) — smaller executables for deployment. + - **Cross-platform triplet auto-resolution:** new `cmake/voicecat-toolchain.cmake` wraps + vcpkg's toolchain and resolves `VCPKG_TARGET_TRIPLET` / `VCPKG_HOST_TRIPLET` from + `CMAKE_HOST_SYSTEM_NAME` + `CMAKE_HOST_SYSTEM_PROCESSOR` — `x64-mingw-static` on Windows, + `x64-linux` on Linux, `arm64-osx` on Apple Silicon. The main presets (`dev`, `release`, + `server-release`) now work on all three platforms without per-OS variants. Cross-compile + presets (`apple-ios`, `apple-ios-sim`) override `VCPKG_TARGET_TRIPLET` explicitly. Hidden + base preset renamed `vcpkg-base`→`vcpkg-common` (now points at the wrapper toolchain + instead of vcpkg's toolchain directly). + - **No C++ source changes** — the core was already portable (every `#ifdef _WIN32` in + `client.cpp` already had a POSIX `#else`; `voicecat.h`'s export macro already handled + GCC visibility; `transport.cpp` is pure Asio; miniaudio abstracts WASAPI/CoreAudio/ALSA). + - **Docs updated:** `docs/building.md` (full rewrite — 8-preset table, platform matrix, + preset history mapping old names to new, Apple scaffolding section), `CLAUDE.md` (build + section reframed around `dev` as default, status line updated to M5-done), `README.md` + (stale "M0 skeleton" framing replaced with current M5 reality), `AGENTS.md` (build + section updated, stale "placeholder builtin-baseline" sentence deleted), + `docs/deployment.md` (server-release now stripped + cross-platform note), + `docs/tech-stack.md` §4 (triplet auto-resolution + Apple scaffolding note), + `clients/apple/README.md` (new "Building the core for Apple platforms" section with + XCFramework workflow), `clients/windows/README.md` (m1-dev→dev). + - **Code comments updated:** `core/include/voicecat.h`, `core/src/net/transport.h`, + `core/src/voicecat.cpp`, `tests/CMakeLists.txt` — preset name references updated. + - **Historical `PROGRESS.md` entries left intact** — `m1-dev`/`m2-dev` mentions in older + entries are a true record of what was run; rewriting them would falsify history. The + preset history table in `docs/building.md` §1 maps old names to new. + - **Verified:** `cmake --list-presets` shows all 8 presets. `skeleton` + `dev` configure + and build green on Windows. Apple presets are scaffolding (won't build on Windows — + expected; they require macOS). + - **Done:** **Disconnect, timeout & keepalive system** (2026-06-18). Three reported bugs traced to one root cause + two missing designed features, all fixed: 1. **Stale users after disconnect + eternal PLC hiss** (root cause): `ConnSession::close()` diff --git a/README.md b/README.md index cc2d56a..508dcc0 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,11 @@ channel-based voice, channel + private text, one server you run yourself. Plain (control) and **UDP** (media), no WebRTC. Encrypted by default. A shared **C++ core** (`libvoicecat`) drives native clients (Swift on macOS/iOS, C# on Windows) and the server. -> **Status: pre-implementation.** The design is complete in [`docs/`](docs/). The code is an -> M0 **skeleton** — it compiles and links, but every subsystem is a stub. See -> [`AGENTS.md`](AGENTS.md) to start building, and [`docs/roadmap.md`](docs/roadmap.md) for the -> milestones. +> **Status:** Design complete in [`docs/`](docs/). M1–M5 are implemented — real TLS control +> plane, encrypted UDP voice (Opus), multi-stream, TOFU identity pinning, channel tree, +> permissions, moderation, disconnect/keepalive/reaper. Windows WinForms C# client shipped +> (M4). macOS/iOS Swift client is next. See [`PROGRESS.md`](PROGRESS.md) and +> [`docs/roadmap.md`](docs/roadmap.md). ## Read the design first @@ -16,28 +17,34 @@ The [`docs/`](docs/) folder is the source of truth. Start at [`docs/README.md`]( then `architecture` → `protocol` → `voice` → `security` → `tech-stack` → `deployment` → `roadmap`. -## Build the skeleton (no dependencies needed yet) +## Build -The M0 skeleton builds with just a C++20 compiler + CMake + Ninja — **no vcpkg, no -third-party libraries**, because every subsystem is currently a stub. +The default development preset is **`dev`** — it builds everything (server + tools + tests) +with real vcpkg deps. It works on Windows, Linux, and macOS (vcpkg triplet auto-resolved). ```bash +# one-time vcpkg setup: +git clone https://github.com/microsoft/vcpkg && ./vcpkg/bootstrap-vcpkg.sh # .bat on Windows +export VCPKG_ROOT=/path/to/vcpkg # Linux/macOS; or $env:VCPKG_ROOT on PowerShell + +# configure + build + test: cmake --preset dev cmake --build --preset dev -ctest --preset dev # runs the smoke test (links the core, calls the C ABI) +ctest --preset dev # 21 behavior tests ``` -Artifacts land in `build/dev/bin/` (`voicecat-server`, `vccli`). +Artifacts land in `build/dev/bin/` (`voicecat-server`, `vccli`, `voicecat-admin`). -When you start implementing a subsystem that needs real libraries, build with vcpkg deps: +The `skeleton` preset (no vcpkg deps, stubs only) is a fast smoke check that needs no +third-party libraries: ```bash -# one-time: git clone https://github.com/microsoft/vcpkg && ./vcpkg/bootstrap-vcpkg.sh -export VCPKG_ROOT=/path/to/vcpkg # set VCPKG_ROOT (works on Linux/macOS/Windows) -cmake --preset server-release # auto-installs deps from vcpkg.json -cmake --build --preset server-release +cmake --preset skeleton && cmake --build --preset skeleton && ctest --preset skeleton ``` +See [`docs/building.md`](docs/building.md) for the full preset matrix (including `release`, +`server-release`, `windows-client`, and Apple platform scaffolding). + ## Layout ``` diff --git a/clients/apple/README.md b/clients/apple/README.md index 0b413e9..dc34784 100644 --- a/clients/apple/README.md +++ b/clients/apple/README.md @@ -17,3 +17,40 @@ Planned shape (see [`docs/architecture.md`](../../docs/architecture.md) §4 and state via an **App Group** ([`docs/voice.md`](../../docs/voice.md) §9). Nothing here yet — the core must reach M2 (working voice) before the GUI is worth building. + +## Building the core for Apple platforms (scaffolding) + +The CMake presets `apple-dev`, `apple-ios`, and `apple-ios-sim` produce static `libvoicecat.a` +slices for the Swift Package / XCFramework. They are **scaffolding** — not yet CI-validated. +Build on macOS (they won't work on Windows/Linux): + +```bash +# Prerequisites: VCPKG_ROOT set, Xcode + iOS SDK installed +export VCPKG_ROOT=/path/to/vcpkg + +# 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: + +```bash +xcodebuild -create-xcframework \ + -library build/apple-dev/lib/libvoicecat.a -headers core/include \ + -library build/apple-ios/lib/libvoicecat.a -headers core/include \ + -library build/apple-ios-sim/lib/libvoicecat.a -headers core/include \ + -output build/VoiceCatCore.xcframework +``` + +The XCFramework is then consumed by the Swift Package as a binary target. Actual +`AVAudioSession` integration, `Info.plist` mic permission, ReplayKit extension, and SwiftUI +UI work are tracked as follow-up tasks — the presets exist so the build entry point is ready. diff --git a/clients/windows/README.md b/clients/windows/README.md index b6b9c62..abfecbc 100644 --- a/clients/windows/README.md +++ b/clients/windows/README.md @@ -16,8 +16,8 @@ WinForms (.NET 10 LTS) UI over `voicecat.dll` (MinGW-built `libvoicecat` shared ### 1. Build the server (for testing) ```powershell -cmake --preset m1-dev -cmake --build --preset m1-dev --target voicecat-server +cmake --preset dev +cmake --build --preset dev --target voicecat-server ``` ### 2. Build the DLL @@ -53,7 +53,7 @@ into the output directory automatically on every build. ```powershell # Terminal 1 — start the server -./build/m1-dev/bin/voicecat-server.exe --name "My Server" +./build/dev/bin/voicecat-server.exe --name "My Server" # Terminal 2 — launch the client dotnet run --project clients/windows/VoiceCat.App/VoiceCat.App.csproj diff --git a/cmake/voicecat-toolchain.cmake b/cmake/voicecat-toolchain.cmake new file mode 100644 index 0000000..710f48b --- /dev/null +++ b/cmake/voicecat-toolchain.cmake @@ -0,0 +1,72 @@ +# cmake/voicecat-toolchain.cmake — vcpkg toolchain wrapper with auto-triplet. +# +# Wraps vcpkg's toolchain to auto-resolve VCPKG_HOST_TRIPLET and VCPKG_TARGET_TRIPLET +# from the host platform, so the main presets (dev, release, server-release) build on +# Windows/MinGW, Linux, and macOS without per-OS preset variants. +# +# Triplet mapping (auto): +# Windows → x64-mingw-static (the project's toolchain is MSYS2/UCRT64 — see +# clients/windows/README.md; MSVC users must set +# VCPKG_TARGET_TRIPLET=x64-windows explicitly) +# Linux x64 → x64-linux +# Linux arm64 → arm64-linux +# macOS arm64 → arm64-osx (Apple Silicon) +# macOS x64 → x64-osx (Intel) +# +# Cross-compile presets (apple-ios, apple-ios-sim) set VCPKG_TARGET_TRIPLET explicitly +# in their cacheVariables; the DEFINED guards below preserve those. VCPKG_HOST_TRIPLET +# is always the host's (e.g. arm64-osx when cross-compiling iOS on Apple Silicon). +# +# Requires VCPKG_ROOT in the environment (set by the inheriting preset). + +# ── Host triplet (the platform running vcpkg / the build) ───────────────────── +if(NOT DEFINED VCPKG_HOST_TRIPLET) + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(_voicecat_host "x64-mingw-static") + elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") + set(_voicecat_host "arm64-linux") + else() + set(_voicecat_host "x64-linux") + endif() + elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") + set(_voicecat_host "arm64-osx") + else() + set(_voicecat_host "x64-osx") + endif() + endif() + if(_voicecat_host) + set(VCPKG_HOST_TRIPLET "${_voicecat_host}" CACHE STRING "vcpkg host triplet (auto-resolved)") + endif() + unset(_voicecat_host) +endif() + +# ── Target triplet (the platform being built for) ───────────────────────────── +# Auto-resolve only when not explicitly set. Cross-compile presets (apple-ios, +# apple-ios-sim) set VCPKG_TARGET_TRIPLET in their cacheVariables; the DEFINED +# guard preserves those so they win over the auto-detection. +if(NOT DEFINED VCPKG_TARGET_TRIPLET) + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(_voicecat_target "x64-mingw-static") + elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") + set(_voicecat_target "arm64-linux") + else() + set(_voicecat_target "x64-linux") + endif() + elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") + set(_voicecat_target "arm64-osx") + else() + set(_voicecat_target "x64-osx") + endif() + endif() + if(_voicecat_target) + set(VCPKG_TARGET_TRIPLET "${_voicecat_target}" CACHE STRING "vcpkg target triplet (auto-resolved)") + endif() + unset(_voicecat_target) +endif() + +# ── Hand off to the real vcpkg toolchain ────────────────────────────────────── +include("$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake") diff --git a/core/include/voicecat.h b/core/include/voicecat.h index 183de9d..893ffde 100644 --- a/core/include/voicecat.h +++ b/core/include/voicecat.h @@ -8,10 +8,10 @@ * Design: docs/architecture.md §4. Everything here is async + event-driven — calls return * immediately and results/state changes arrive via the vc_callbacks.on_event callback. * - * STATUS: real, behind VOICECAT_HAS_NET (the `m1-dev`/`server-release` presets — vcpkg deps - * on; see docs/building.md). As of M3, control plane, voice, multi-stream, device + * STATUS: real, behind VOICECAT_HAS_NET (the `dev`/`release`/`server-release` presets — + * vcpkg deps on; see docs/building.md). As of M3, control plane, voice, multi-stream, device * enumeration, VAD/PTT, and stereo playback all work for real via core/src/core/client.cpp. - * The no-deps `dev` preset still links a stub vc_client that returns VC_ERR_NOT_IMPLEMENTED + * The no-deps `skeleton` preset still links a stub vc_client that returns VC_ERR_NOT_IMPLEMENTED * for everything below `connect`, purely to keep that skeleton build green. webrtc AEC/NS/AGC * remains an inert passthrough regardless of preset (no Windows/MSVC port upstream — * docs/voice.md §8/§11, PROGRESS.md). diff --git a/core/src/net/transport.h b/core/src/net/transport.h index 1024c81..805bc7d 100644 --- a/core/src/net/transport.h +++ b/core/src/net/transport.h @@ -4,8 +4,9 @@ * Design: docs/architecture.md (Net thread), docs/protocol.md §1 (framing). * Implementation uses standalone Asio for sockets and timers. * - * The real classes are compiled only when VOICECAT_HAS_NET is defined (m1-dev+). - * The dev-preset stub definitions below keep the skeleton build green. + * The real classes are compiled only when VOICECAT_HAS_NET is defined (dev/release/ + * server-release — vcpkg deps on). The skeleton-preset stub definitions below keep the + * no-deps build green. */ #ifndef VOICECAT_NET_TRANSPORT_H #define VOICECAT_NET_TRANSPORT_H diff --git a/core/src/protocol/protocol.h b/core/src/protocol/protocol.h index e7cd3fe..79dc712 100644 --- a/core/src/protocol/protocol.h +++ b/core/src/protocol/protocol.h @@ -7,7 +7,7 @@ * (they use the fixed binary header in voice.md §2). * * STATUS: real. Protobuf codegen is on (core/CMakeLists.txt) for VOICECAT_HAS_NET builds - * (`m1-dev`/`server-release`); FrameCodec below is fully implemented and used by both the + * (`dev`/`release`/`server-release`); FrameCodec below is fully implemented and used by both the * client (net/transport.h) and the server (conn_session.cpp). See protocol/envelope.h for the * Envelope-level encode/decode that sits on top of this. */ diff --git a/core/src/voicecat.cpp b/core/src/voicecat.cpp index fa2d51d..9167d2b 100644 --- a/core/src/voicecat.cpp +++ b/core/src/voicecat.cpp @@ -3,8 +3,8 @@ * * Lifecycle (create/destroy) and trivial accessors are always real. Everything else below * just delegates to vc_client (core/src/core/client.cpp): under VOICECAT_HAS_NET - * (`m1-dev`/`server-release` — see docs/building.md) that's the real M1–M3 implementation; - * under the no-deps `dev` preset, client.cpp's `#else` branch returns VC_ERR_NOT_IMPLEMENTED + * (`dev`/`release`/`server-release` — see docs/building.md) that's the real M1–M3 implementation; + * under the no-deps `skeleton` preset, client.cpp's `#else` branch returns VC_ERR_NOT_IMPLEMENTED * for all of it, to keep that skeleton build green. */ #include "voicecat.h" diff --git a/docs/building.md b/docs/building.md index 3c517f9..94fe510 100644 --- a/docs/building.md +++ b/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 --input-mode ptt +./build/dev/bin/vccli --list-devices +./build/dev/bin/vccli --nick Alice --voice --input-device --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. diff --git a/docs/deployment.md b/docs/deployment.md index 9dff336..e60da21 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -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 diff --git a/docs/tech-stack.md b/docs/tech-stack.md index 66c3938..678b48b 100644 --- a/docs/tech-stack.md +++ b/docs/tech-stack.md @@ -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). | diff --git a/server/src/server.cpp b/server/src/server.cpp index 875e823..d433a73 100644 --- a/server/src/server.cpp +++ b/server/src/server.cpp @@ -205,7 +205,7 @@ void Server::stop() { namespace voicecat::server { int Server::run() { - std::fprintf(stderr, "[server] stub: VOICECAT_HAS_NET not defined (build with m1-dev)\n"); + std::fprintf(stderr, "[server] stub: VOICECAT_HAS_NET not defined (build with dev preset)\n"); std::printf(" server_name : %s\n", cfg_.server_name.c_str()); std::printf(" data_dir : %s\n", cfg_.data_dir.c_str()); std::printf(" bind_port : %u\n", cfg_.bind_port); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 106d22c..a932e1a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,7 +6,7 @@ target_link_libraries(test_smoke PRIVATE voicecat::voicecat) target_compile_features(test_smoke PRIVATE cxx_std_20) add_test(NAME smoke COMMAND test_smoke) -# frame_codec has no third-party deps; runs under both dev and m1-dev. +# frame_codec has no third-party deps; runs under both skeleton and dev. # Needs core/src on the include path to reach internal headers (protocol/, session/, etc.). add_executable(test_frame_codec test_frame_codec.cpp) target_link_libraries(test_frame_codec PRIVATE voicecat::voicecat) diff --git a/tests/test_envelope.cpp b/tests/test_envelope.cpp index d514e86..8504016 100644 --- a/tests/test_envelope.cpp +++ b/tests/test_envelope.cpp @@ -1,6 +1,6 @@ /* * test_envelope — round-trip an Envelope through FrameCodec + encode/decode. - * Runs only under m1-dev (requires protobuf). + * Runs only under dev (requires protobuf). */ #include #include diff --git a/tests/test_frame_codec.cpp b/tests/test_frame_codec.cpp index 4389e6f..22616e2 100644 --- a/tests/test_frame_codec.cpp +++ b/tests/test_frame_codec.cpp @@ -1,7 +1,7 @@ /* * test_frame_codec — unit test for FrameCodec::feed / ::emit. * - * No third-party dependencies; runs under both the dev and m1-dev presets. + * No third-party dependencies; runs under both the skeleton and dev presets. * Tests: empty payload, single byte, 64 KiB, exact max-size, oversized (should reject), * split delivery (bytes fed one-at-a-time), and batched multi-frame delivery. */ diff --git a/tests/test_opus_codec.cpp b/tests/test_opus_codec.cpp index 6e58a86..5670a57 100644 --- a/tests/test_opus_codec.cpp +++ b/tests/test_opus_codec.cpp @@ -1,7 +1,7 @@ /* * test_opus_codec — Opus encode/decode round-trip, PLC, energy check. * - * Requires VOICECAT_HAS_OPUS (m1-dev and m2-dev presets). + * Requires VOICECAT_HAS_OPUS (dev and release presets). */ #include #include diff --git a/tests/test_smoke.cpp b/tests/test_smoke.cpp index fa960ae..906b2b2 100644 --- a/tests/test_smoke.cpp +++ b/tests/test_smoke.cpp @@ -43,7 +43,7 @@ int main() { CHECK(vc_connect(c, nullptr, 1) == VC_ERR_INVALID_ARG); CHECK(vc_send_text(c, VC_TEXT_CHANNEL, 0, nullptr) == VC_ERR_INVALID_ARG); - // Under dev preset: NOT_IMPLEMENTED. Under m1-dev: VC_OK (async connect). + // Under skeleton preset: NOT_IMPLEMENTED. Under dev: VC_OK (async connect). vc_result rc_connect = vc_connect(c, "127.0.0.1", 8384); CHECK(rc_connect == VC_ERR_NOT_IMPLEMENTED || rc_connect == VC_OK); diff --git a/tests/test_tcp_loopback.cpp b/tests/test_tcp_loopback.cpp index e6b5a51..4597551 100644 --- a/tests/test_tcp_loopback.cpp +++ b/tests/test_tcp_loopback.cpp @@ -1,6 +1,6 @@ /* * test_tcp_loopback — in-process TCP acceptor + client, sends 10 frames. - * Runs only under m1-dev (requires Asio). + * Runs only under dev (requires Asio). */ #include #include diff --git a/tools/voicecat-admin/src/main.cpp b/tools/voicecat-admin/src/main.cpp index 9015f55..c9069d1 100644 --- a/tools/voicecat-admin/src/main.cpp +++ b/tools/voicecat-admin/src/main.cpp @@ -145,7 +145,7 @@ int main(int argc, char** argv) { #else // !VOICECAT_HAS_NET int main() { - std::fprintf(stderr, "voicecat-admin requires VOICECAT_HAS_NET (build with m1-dev preset)\n"); + std::fprintf(stderr, "voicecat-admin requires VOICECAT_HAS_NET (build with dev preset)\n"); return 1; }