Files
voice-cat/docs/building.md
Talon 845f995826 docs: add build/manual-testing guide, fix stale M0 stub claims in headers
- docs/building.md: explains what each CMake preset (dev, m1-dev, m2-dev,
  server-release) is actually for, and how to build voicecat-server + vccli
  for manual testing. Linked from CLAUDE.md's doc index.
- core/include/voicecat.h, core/src/voicecat.cpp, core/src/protocol/protocol.h,
  server/src/main.cpp: doc-header comments still claimed M0-skeleton/stub
  behavior (VC_ERR_NOT_IMPLEMENTED everywhere, "prints what it would do",
  protobuf codegen "commented") that M1-M3 made real. Updated to describe
  current behavior, with the dev-preset stub fallback noted explicitly where
  it still applies.
2026-06-16 16:30:07 +02:00

6.7 KiB

Building & Manual Testing

This doc explains what each CMake preset in CMakePresets.json is 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; for ctest targets see AGENTS.md. This doc is the missing middle: how the presets relate to each other, 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.

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.

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:

# once:
git clone https://github.com/microsoft/vcpkg
./vcpkg/bootstrap-vcpkg.sh        # .bat on Windows

# every shell session (PowerShell):
$env:VCPKG_ROOT = "D:\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 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)

cmake --preset m1-dev
cmake --build --preset m1-dev
ctest --test-dir build/m1-dev --output-on-failure

(ctest --preset m1-dev is equivalent — both are wired up in CMakePresets.json.) Binaries land in build/m1-dev/bin/ (.exe suffix on Windows):

  • build/m1-dev/bin/voicecat-server
  • build/m1-dev/bin/vccli
  • build/m1-dev/bin/voicecat-admin

4. Manual testing: server + two clients

Start the server

./build/m1-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 SQLite store, and creates a default "Lobby" channel. Other server flags:

--port <n>          control+media port (default 8384)
--data-dir <path>   data directory (default ./voicecat-data)
--name <name>       server name
--no-guests         disable guest access (then provision accounts via voicecat-admin)
--print-config      print effective config and exit
--version           print version and exit

Drive it with vccli

vccli is the headless client used to exercise the protocol by hand. Full flag list:

vccli [--host H] [--port P] [--nick NAME] [--channel ID]
      [--voice] [--mute] [--text MSG] [--list-devices]
      [--input-device ID] [--input-mode vad|ptt] [--share-screen-audio]

  --host H              server host (default 127.0.0.1)
  --port P              server TCP port (default 8384)
  --nick NAME           guest nickname (default vccli-test)
  --channel ID          channel to join after auth (default 1, Lobby)
  --voice               start a MIC stream and stay connected until Ctrl+C
  --mute                start with the mic muted (only meaningful with --voice)
  --text MSG            send MSG to the channel, then exit
  --list-devices        print input/output devices (vc_list_devices) and exit
  --input-device ID     use device ID (from --list-devices) for the MIC stream
  --input-mode vad|ptt  send-side input gate mode (default vad)
  --share-screen-audio  also start a SCREEN_AUDIO stream (WASAPI loopback on Windows)

While --voice is running, stdin accepts ptt on, ptt off, mode vad, mode ptt to toggle the input gate live.

Smoke test — two clients talking:

# terminal A
./build/m1-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"

Real voice between two clients (needs working mic/speakers, two terminals):

# terminal A
./build/m1-dev/bin/vccli --nick Alice --voice

# terminal B
./build/m1-dev/bin/vccli --nick Bob --voice

Speak into the mic on one side; you should hear it on the other. Ctrl+C to disconnect.

Enumerate audio devices before picking one:

./build/m1-dev/bin/vccli --list-devices
./build/m1-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):

./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

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:

cmake --preset server-release
cmake --build --preset server-release
./build/server-release/bin/voicecat-server

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.