build: bundle vcpkg as a git submodule, pinned to the manifest baseline
Some checks failed
Build Linux Binaries / linux/amd64 (push) Has been cancelled
Build Linux Binaries / linux/arm64 (push) Has been cancelled

Adds vcpkg as a submodule at vcpkg/, pinned to the exact commit vcpkg.json
already declares as builtin-baseline, so the bundled checkout and the
manifest's resolved port versions can never drift apart.

cmake/voicecat-toolchain.cmake, scripts/common.sh, and
clients/apple/scripts/build-xcframework.sh now resolve vcpkg as:
VCPKG_ROOT env var (external checkout) > bundled submodule. Docs updated
to describe the new one-time setup.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 10:42:42 +01:00
parent bba605401d
commit 5c03e5f261
12 changed files with 98 additions and 33 deletions

3
.gitignore vendored
View File

@@ -14,9 +14,8 @@
*.exe
*.pdb
# vcpkg
# vcpkg (bundled as a submodule at /vcpkg — see docs/building.md §2)
/vcpkg_installed/
/vcpkg/
# Generated protobuf
*.pb.cc

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "vcpkg"]
path = vcpkg
url = https://github.com/microsoft/vcpkg.git

View File

@@ -38,15 +38,20 @@ making progress.
## Build
Default development preset (real deps via vcpkg — works on Windows/Linux/macOS):
Default development preset (real deps via vcpkg — works on Windows/Linux/macOS). vcpkg is
bundled as a git submodule at `vcpkg/`, pinned to `vcpkg.json`'s `builtin-baseline`:
```bash
export VCPKG_ROOT=/path/to/vcpkg # bootstrap vcpkg first; cross-platform
git submodule update --init vcpkg # one-time, after cloning
./vcpkg/bootstrap-vcpkg.sh # .bat on Windows
cmake --preset dev
cmake --build --preset dev
ctest --preset dev
```
To use an external vcpkg checkout instead, `export VCPKG_ROOT=/path/to/vcpkg` — it always
takes priority over the bundled submodule.
Skeleton (no third-party deps — works immediately, no vcpkg needed):
```bash
@@ -68,7 +73,8 @@ 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).
by [`cmake/voicecat-toolchain.cmake`](cmake/voicecat-toolchain.cmake), which also resolves
`VCPKG_ROOT` (env var override, else the bundled `vcpkg/` submodule).
## Where each subsystem lives (and its doc)

View File

@@ -68,10 +68,18 @@ Vcpkg triplet is auto-resolved from the host platform by
Windows, `x64-linux` on Linux, `arm64-osx` on Apple Silicon. See docs/building.md §1
"Platform matrix" for details.
One-time vcpkg setup:
vcpkg is bundled as a git submodule at `vcpkg/`, pinned to the commit in `vcpkg.json`'s
`builtin-baseline`. One-time setup after cloning:
```bash
git submodule update --init vcpkg
./vcpkg/bootstrap-vcpkg.sh # .bat on Windows
```
To use an external vcpkg checkout instead (e.g. one shared across projects), set
`VCPKG_ROOT` — it always takes priority over the bundled submodule:
```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
```

View File

@@ -5,7 +5,7 @@
{
"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.",
"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. Resolves vcpkg from the bundled git submodule (vcpkg/) unless VCPKG_ROOT points at an external checkout.",
"generator": "Ninja",
"toolchainFile": "${sourceDir}/cmake/voicecat-toolchain.cmake",
"cacheVariables": {
@@ -15,7 +15,7 @@
{
"name": "dev",
"displayName": "Dev (full real-deps build, vcpkg)",
"description": "Day-to-day development preset. Real protocol, crypto, voice, server. Builds server + tools + tests. Auto-triplet: x64-mingw-static on Windows, x64-linux on Linux, arm64-osx on Apple Silicon. Requires VCPKG_ROOT.",
"description": "Day-to-day development preset. Real protocol, crypto, voice, server. Builds server + tools + tests. Auto-triplet: x64-mingw-static on Windows, x64-linux on Linux, arm64-osx on Apple Silicon. Requires vcpkg bootstrapped (bundled submodule or VCPKG_ROOT).",
"inherits": "vcpkg-common",
"binaryDir": "${sourceDir}/build/dev",
"cacheVariables": {
@@ -27,7 +27,7 @@
{
"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.",
"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 bootstrapped (bundled submodule or VCPKG_ROOT).",
"inherits": "vcpkg-common",
"binaryDir": "${sourceDir}/build/release",
"cacheVariables": {
@@ -39,7 +39,7 @@
{
"name": "server-release",
"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.",
"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 bootstrapped (bundled submodule or VCPKG_ROOT).",
"inherits": "vcpkg-common",
"binaryDir": "${sourceDir}/build/server-release",
"cacheVariables": {
@@ -67,7 +67,7 @@
{
"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.",
"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 bootstrapped (bundled submodule or VCPKG_ROOT).",
"inherits": "vcpkg-common",
"binaryDir": "${sourceDir}/build/apple-dev",
"cacheVariables": {
@@ -80,7 +80,7 @@
{
"name": "apple-ios",
"displayName": "Apple iOS device (XCFramework slice)",
"description": "Cross-compiles a static libvoicecat.a for iOS device (arm64). One slice of the XCFramework. Server/tools/tests off. Requires VCPKG_ROOT and a macOS host with iOS SDK. Uses cmake/vcpkg-overlays/triplets/arm64-ios.cmake (release-only, correct autoconf host triple).",
"description": "Cross-compiles a static libvoicecat.a for iOS device (arm64). One slice of the XCFramework. Server/tools/tests off. Requires vcpkg bootstrapped (bundled submodule or VCPKG_ROOT) and a macOS host with iOS SDK. Uses cmake/vcpkg-overlays/triplets/arm64-ios.cmake (release-only, correct autoconf host triple).",
"inherits": "vcpkg-common",
"binaryDir": "${sourceDir}/build/apple-ios",
"cacheVariables": {
@@ -100,7 +100,7 @@
{
"name": "apple-ios-sim",
"displayName": "Apple iOS simulator (XCFramework slice)",
"description": "Cross-compiles a static libvoicecat.a for iOS simulator (arm64-ios-simulator). One slice of the XCFramework. Server/tools/tests off. Requires VCPKG_ROOT and a macOS host with iOS simulator SDK. Uses cmake/vcpkg-overlays/triplets/arm64-ios-simulator.cmake (release-only, correct autoconf host triple).",
"description": "Cross-compiles a static libvoicecat.a for iOS simulator (arm64-ios-simulator). One slice of the XCFramework. Server/tools/tests off. Requires vcpkg bootstrapped (bundled submodule or VCPKG_ROOT) and a macOS host with iOS simulator SDK. Uses cmake/vcpkg-overlays/triplets/arm64-ios-simulator.cmake (release-only, correct autoconf host triple).",
"inherits": "vcpkg-common",
"binaryDir": "${sourceDir}/build/apple-ios-sim",
"cacheVariables": {

View File

@@ -23,9 +23,9 @@ The default development preset is **`dev`** — it builds everything (server + t
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
# one-time vcpkg setup (bundled as a submodule, pinned to vcpkg.json's builtin-baseline):
git submodule update --init vcpkg
./vcpkg/bootstrap-vcpkg.sh # .bat on Windows
# configure + build + test:
cmake --preset dev
@@ -33,6 +33,9 @@ cmake --build --preset dev
ctest --preset dev # 21 behavior tests
```
To use an external vcpkg checkout instead, set `VCPKG_ROOT=/path/to/vcpkg` (or
`$env:VCPKG_ROOT` on PowerShell) — it always takes priority over the bundled submodule.
Artifacts land in `build/dev/bin/` (`voicecat-server`, `vccli`, `voicecat-admin`).
The `skeleton` preset (no vcpkg deps, stubs only) is a fast smoke check that needs no

View File

@@ -54,7 +54,8 @@ done
# ── Resolve VCPKG_ROOT ───────────────────────────────────────────────────────────
# The apple-dev CMake cache records the vcpkg root it was configured with (Z_VCPKG_ROOT_DIR);
# reuse that so a developer who already configured `cmake --preset dev` doesn't need VCPKG_ROOT
# in their shell env to run this script.
# in their shell env to run this script. Falls back to the bundled submodule at
# <repo-root>/vcpkg if neither the env var nor the cache resolve it.
if [[ -z "${VCPKG_ROOT:-}" ]]; then
cache="$REPO_ROOT/build/apple-dev/CMakeCache.txt"
if [[ -f "$cache" ]]; then
@@ -64,9 +65,16 @@ if [[ -z "${VCPKG_ROOT:-}" ]]; then
fi
fi
fi
if [[ -z "${VCPKG_ROOT:-}" ]]; then
bundled="$REPO_ROOT/vcpkg"
if [[ -f "$bundled/scripts/buildsystems/vcpkg.cmake" ]]; then
export VCPKG_ROOT="$bundled"
fi
fi
if [[ -z "${VCPKG_ROOT:-}" || ! -d "$VCPKG_ROOT" ]]; then
echo "error: VCPKG_ROOT is not set or does not exist." >&2
echo " bootstrap vcpkg (https://vcpkg.io) then: export VCPKG_ROOT=/path/to/vcpkg" >&2
echo " either init the bundled submodule: git submodule update --init vcpkg" >&2
echo " or point at an external checkout: export VCPKG_ROOT=/path/to/vcpkg" >&2
exit 1
fi
echo "[build-xcframework] VCPKG_ROOT=$VCPKG_ROOT"

View File

@@ -17,7 +17,9 @@
# 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).
# Resolution order: an explicit VCPKG_ROOT env var always wins (for developers pointing at
# their own external vcpkg checkout); otherwise this falls back to the bundled submodule at
# <repo-root>/vcpkg (`git submodule update --init vcpkg`).
# ── Host triplet (the platform running vcpkg / the build) ─────────────────────
if(NOT DEFINED VCPKG_HOST_TRIPLET)
@@ -78,5 +80,21 @@ if(NOT DEFINED VCPKG_OVERLAY_TRIPLETS)
CACHE STRING "vcpkg overlay triplets directory")
endif()
# ── Resolve vcpkg root ──────────────────────────────────────────────────────────
if(DEFINED ENV{VCPKG_ROOT} AND NOT "$ENV{VCPKG_ROOT}" STREQUAL "")
set(_voicecat_vcpkg_root "$ENV{VCPKG_ROOT}")
else()
set(_voicecat_vcpkg_root "${CMAKE_CURRENT_LIST_DIR}/../vcpkg")
endif()
if(NOT EXISTS "${_voicecat_vcpkg_root}/scripts/buildsystems/vcpkg.cmake")
message(FATAL_ERROR
"vcpkg not found at '${_voicecat_vcpkg_root}'.\n"
"Either init the bundled submodule:\n"
" git submodule update --init vcpkg\n"
"or point VCPKG_ROOT at an external vcpkg checkout.")
endif()
# ── Hand off to the real vcpkg toolchain ──────────────────────────────────────
include("$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
include("${_voicecat_vcpkg_root}/scripts/buildsystems/vcpkg.cmake")
unset(_voicecat_vcpkg_root)

View File

@@ -75,21 +75,32 @@ was run.
## 2. One-time setup for the real-deps presets
All presets except `vcpkg-common` need `VCPKG_ROOT`
pointing at a bootstrapped vcpkg checkout:
vcpkg is bundled as a git submodule at [`vcpkg/`](../vcpkg), pinned to the exact commit in
[`vcpkg.json`](../vcpkg.json)'s `builtin-baseline` — so the bundled checkout and the manifest's
resolved port versions can never drift apart. All presets except `vcpkg-common` need it
bootstrapped:
```bash
# once:
git clone https://github.com/microsoft/vcpkg
# once, after cloning:
git submodule update --init vcpkg
./vcpkg/bootstrap-vcpkg.sh # .bat on Windows
```
# every shell session (PowerShell):
`cmake/voicecat-toolchain.cmake` resolves the vcpkg root itself — no environment variable
needed. If you'd rather use an external vcpkg checkout (e.g. one shared across several
projects), set `VCPKG_ROOT` and it takes priority over the bundled submodule:
```bash
# PowerShell:
$env:VCPKG_ROOT = "D:\path\to\vcpkg"
# or on Linux/macOS:
# Linux/macOS:
export VCPKG_ROOT=/path/to/vcpkg
```
An external checkout must still be bootstrapped, and should be at (or compatible with)
`vcpkg.json`'s `builtin-baseline` commit to resolve the same port versions.
`vcpkg.json` (manifest mode) pins every dependency (protobuf, mbedTLS, libsodium, asio,
sqlite3, spdlog, opus, miniaudio) — `cmake --preset dev` resolves and builds them
automatically on first configure. That first configure is slow (vcpkg building from source);

View File

@@ -61,7 +61,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. 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. |
| **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. vcpkg itself is bundled as a git submodule at `vcpkg/`, pinned to `vcpkg.json`'s `builtin-baseline` commit — `VCPKG_ROOT` overrides it for an external checkout. See [building.md §2](building.md#2-one-time-setup-for-the-real-deps-presets). |
| **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). |

View File

@@ -79,10 +79,10 @@ vc_require_windows() {
}
# ── VCPKG_ROOT ──────────────────────────────────────────────────────────────────
# Honor the env var, else try to read it from an existing CMake cache
# (Z_VCPKG_ROOT_DIR) so a developer who already configured a preset doesn't need
# VCPKG_ROOT in their shell env. $1 = the preset whose cache to probe as a
# fallback (e.g. "dev" or "apple-dev").
# Resolution order: the env var, else an existing CMake cache (Z_VCPKG_ROOT_DIR) so a
# developer who already configured a preset doesn't need VCPKG_ROOT in their shell env,
# else the bundled submodule at <repo-root>/vcpkg. $1 = the preset whose cache to probe
# as a fallback (e.g. "dev" or "apple-dev").
vc_resolve_vcpkg_root() {
local fallback_preset="${1:-dev}"
if [[ -z "${VCPKG_ROOT:-}" ]]; then
@@ -95,9 +95,17 @@ vc_resolve_vcpkg_root() {
fi
fi
fi
if [[ -z "${VCPKG_ROOT:-}" ]]; then
local bundled="$VC_REPO_ROOT/vcpkg"
if [[ -f "$bundled/scripts/buildsystems/vcpkg.cmake" ]]; then
export VCPKG_ROOT="$bundled"
fi
fi
if [[ -z "${VCPKG_ROOT:-}" || ! -d "$VCPKG_ROOT" ]]; then
vc_die "VCPKG_ROOT is not set or does not exist.
bootstrap vcpkg (https://vcpkg.io) then:
either init the bundled submodule:
git submodule update --init vcpkg
or point at an external vcpkg checkout:
export VCPKG_ROOT=/path/to/vcpkg"
fi
vc_log "VCPKG_ROOT=$VCPKG_ROOT"

1
vcpkg Submodule

Submodule vcpkg added at d46283cf33