feat(macos): validate dev + apple-dev presets on macOS, fix 3 cross-platform bugs

macOS port groundwork — core, server, tools, and tests now build and run on
macOS 26.5 / Apple Silicon. ctest --preset dev green 21/21 (2 consecutive runs).
apple-dev produces valid arm64 libvoicecat.a + XCFramework for the Swift Package.

Three real cross-platform bugs found and fixed (all latent on Windows/Linux):

1. test_m2_voice.cpp POSIX branch missing <netdb.h> — Linux glibc transitively
   includes it, macOS doesn't. Would fail on any strict POSIX system.

2. SIGPIPE killing processes on macOS — writing to a closed TCP socket raises
   SIGPIPE by default (doesn't exist on Windows, benign on Linux). Fixed by
   ignoring SIGPIPE in both core client init and server startup (POSIX-only,
   #ifndef _WIN32). Production fix, not just tests.

3. Use-after-free of Asio's kqueue reactor on server shutdown — the
   deterministic test_tofu_flow segfault. TcpServerConn's tls_read_loop runs on
   a blocking-I/O thread; when Server::run() returned, io_context was destroyed
   while those threads were still running. On macOS kqueue the reactor pointer
   is null'd immediately -> segfault in socket.close(). Latent on Windows IOCP
   and Linux epoll. Fix: TcpAcceptor now tracks connections; new shutdown()
   closes all + joins threads before io is destroyed; Server::stop() now closes
   acceptor + media_relay too (was just io.stop()).

Verified: dev + apple-dev presets build green, 21/21 tests pass, server starts
+ two vccli text chat over TLS (M1 on Mac), vccli --voice starts MIC stream via
CoreAudio (M2 protocol-level), vccli --list-devices enumerates CoreAudio
devices, xcodebuild -create-xcframework produces valid VoiceCatCore.xcframework.

No ABI or proto changes. Docs updated: building.md, clients/apple/README.md,
PROGRESS.md, CLAUDE.md status line.
This commit is contained in:
2026-06-18 13:24:42 +02:00
parent bcb7ae8ccb
commit b2af1a3001
9 changed files with 187 additions and 16 deletions

View File

@@ -18,11 +18,22 @@ Planned shape (see [`docs/architecture.md`](../../docs/architecture.md) §4 and
Nothing here yet — the core must reach M2 (working voice) before the GUI is worth building.
## Building the core for Apple platforms (scaffolding)
## Building the core for Apple platforms
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):
slices for the Swift Package / XCFramework.
**`apple-dev` (macOS slice) is validated** — builds green on macOS 26.5 / Apple Silicon
(Apple clang 21, vcpkg `arm64-osx` triplet) and produces a valid 1.9 MB arm64 static library
with 167 exported C ABI symbols (correct visibility). The XCFramework creation path is also
verified — `xcodebuild -create-xcframework` produces a valid `VoiceCatCore.xcframework`
with the `.a` + `voicecat.h` headers, ready for a Swift Package binary target.
**`apple-ios` and `apple-ios-sim` (iOS slices) are scaffolding** — not yet CI-validated.
The vcpkg `arm64-ios` / `arm64-ios-sim` triplets for all 8 deps need verification.
Prerequisites: `VCPKG_ROOT` set, Xcode + iOS SDK installed, and Homebrew `autoconf-archive`
(needed by vcpkg's libsodium port — `brew install autoconf-archive`).
```bash
# Prerequisites: VCPKG_ROOT set, Xcode + iOS SDK installed
@@ -51,6 +62,8 @@ xcodebuild -create-xcframework \
-output build/VoiceCatCore.xcframework
```
The XCFramework is then consumed by the Swift Package as a binary target. Actual
The XCFramework is then consumed by the Swift Package as a binary target. The macOS-only
XCFramework (single `apple-dev` slice) is verified to build now; the full 3-slice XCFramework
(macOS + iOS device + iOS simulator) waits for the iOS presets to be validated. 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.
UI work are tracked as follow-up tasks.