diff --git a/.gitignore b/.gitignore index 39bc171..55492c2 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a0a57f3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vcpkg"] + path = vcpkg + url = https://github.com/microsoft/vcpkg.git diff --git a/AGENTS.md b/AGENTS.md index 7cb284e..0231c32 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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) diff --git a/CLAUDE.md b/CLAUDE.md index 3c73fc8..96555d4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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 ``` diff --git a/CMakePresets.json b/CMakePresets.json index 65377c6..cd706e0 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -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": { diff --git a/README.md b/README.md index 508dcc0..a92ed74 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/clients/apple/scripts/build-xcframework.sh b/clients/apple/scripts/build-xcframework.sh index 222a16d..de7f544 100755 --- a/clients/apple/scripts/build-xcframework.sh +++ b/clients/apple/scripts/build-xcframework.sh @@ -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 +# /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" diff --git a/cmake/voicecat-toolchain.cmake b/cmake/voicecat-toolchain.cmake index 423e1cd..afce5dd 100644 --- a/cmake/voicecat-toolchain.cmake +++ b/cmake/voicecat-toolchain.cmake @@ -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 +# /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) diff --git a/docs/building.md b/docs/building.md index 924ee1d..bc40daf 100644 --- a/docs/building.md +++ b/docs/building.md @@ -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); diff --git a/docs/tech-stack.md b/docs/tech-stack.md index 8758427..3122245 100644 --- a/docs/tech-stack.md +++ b/docs/tech-stack.md @@ -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). | diff --git a/scripts/common.sh b/scripts/common.sh index f1170f7..0f6e572 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -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 /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" diff --git a/vcpkg b/vcpkg new file mode 160000 index 0000000..d46283c --- /dev/null +++ b/vcpkg @@ -0,0 +1 @@ +Subproject commit d46283cf33cf5de7bd88e12156ce03882be1f179