diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index b998be8f..28b23309 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -7,6 +7,7 @@ on:
- src/**
- include/**
- client-sdk-rust/**
+ - cmake/**
- CMakeLists.txt
- CMakePresets.json
- build.sh
@@ -20,6 +21,7 @@ on:
- src/**
- include/**
- client-sdk-rust/**
+ - cmake/**
- CMakeLists.txt
- CMakePresets.json
- build.sh
diff --git a/AGENTS.md b/AGENTS.md
index e234ec3a..63c27ce7 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -335,11 +335,37 @@ Adhere to clang-tidy checks configured in `.clang-tidy`. Run `./scripts/clang-ti
| Dependency | Scope | Notes |
|------------|-------|-------|
-| protobuf | Private (built-in) | Vendored via FetchContent (Unix) or vcpkg (Windows) |
+| protobuf-lite | Private (built-in) | Vendored via FetchContent (Unix) or vcpkg (Windows). The SDK links **only** against `protobuf::libprotobuf-lite`; the generated FFI code uses `MessageLite`. See "Protobuf runtime" below. |
| spdlog | **Private** | FetchContent or system package; must NOT leak into public API |
| client-sdk-rust | Build-time | Git submodule, built via cargo during CMake build |
| Google Test | Test only | FetchContent in `src/tests/CMakeLists.txt` |
+### Protobuf runtime
+
+The C++ SDK uses the **protobuf-lite** runtime, not the full protobuf runtime.
+The FFI `.proto` files in `client-sdk-rust/livekit-ffi/protocol/` do not opt
+into lite themselves (they are shared with the Rust and Node FFI generators).
+Instead, the C++ build copies them into the build tree and appends
+`option optimize_for = LITE_RUNTIME;` before running `protoc`. See
+`cmake/patch_protos_for_lite.cmake` and the `PATCHED_PROTO_FILES` custom
+command in the top-level `CMakeLists.txt`. The original `.proto` files in the
+submodule are never modified.
+
+Consequences for code in `src/`:
+
+- The generated `proto::*` classes extend `google::protobuf::MessageLite`, not
+ `Message`. Only the lite subset of the protobuf API is available.
+- Allowed: `set_*` / `mutable_*` / `add_*` / `has_*` / `clear_*` / `*_size()` /
+ oneof `_case()` accessors, `SerializeToString`, `ParseFromArray`, `CopyFrom`,
+ assignment, `google::protobuf::RepeatedField`/`RepeatedPtrField`.
+- **Not available**: `DebugString` / `ShortDebugString` / `Utf8DebugString`,
+ `TextFormat`, `JsonStringToMessage` / `MessageToJsonString`, `GetReflection`,
+ `GetDescriptor`, `DescriptorPool`, `MessageFactory`, Well-Known Types
+ (`Any` / `Timestamp` / `Duration` / `Struct` / `FieldMask` / `Empty`),
+ reflection-based copy/merge utilities. Do not introduce code that needs them.
+- If you ever need a human-readable dump of a proto message for logging, build
+ a hand-written formatter — do not reach for `DebugString()`.
+
When adding a new private/vendored dependency to this table, also add a
forbidden symbol pattern for it to
`.github/scripts/check_no_private_symbols.py` so the "Symbol leak check"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ebfeeeb9..3e0d3356 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -71,25 +71,56 @@ if(LIVEKIT_IS_TOPLEVEL)
endif()
set(FFI_PROTO_DIR ${LIVEKIT_ROOT_DIR}/client-sdk-rust/livekit-ffi/protocol)
-set(FFI_PROTO_FILES
- ${FFI_PROTO_DIR}/handle.proto
- ${FFI_PROTO_DIR}/ffi.proto
- ${FFI_PROTO_DIR}/participant.proto
- ${FFI_PROTO_DIR}/room.proto
- ${FFI_PROTO_DIR}/track.proto
- ${FFI_PROTO_DIR}/video_frame.proto
- ${FFI_PROTO_DIR}/audio_frame.proto
- ${FFI_PROTO_DIR}/e2ee.proto
- ${FFI_PROTO_DIR}/stats.proto
- ${FFI_PROTO_DIR}/data_stream.proto
- ${FFI_PROTO_DIR}/data_track.proto
- ${FFI_PROTO_DIR}/rpc.proto
- ${FFI_PROTO_DIR}/track_publication.proto
+set(FFI_PROTO_NAMES
+ handle.proto
+ ffi.proto
+ participant.proto
+ room.proto
+ track.proto
+ video_frame.proto
+ audio_frame.proto
+ e2ee.proto
+ stats.proto
+ data_stream.proto
+ data_track.proto
+ rpc.proto
+ track_publication.proto
)
+set(FFI_PROTO_FILES)
+foreach(_p ${FFI_PROTO_NAMES})
+ list(APPEND FFI_PROTO_FILES "${FFI_PROTO_DIR}/${_p}")
+endforeach()
set(PROTO_BINARY_DIR ${LIVEKIT_BINARY_DIR}/generated)
file(MAKE_DIRECTORY ${PROTO_BINARY_DIR})
-# Livekit static protobuf.
+# Staging area for protobuf-lite-patched copies of the FFI .proto files.
+# We never modify the originals (they're shared with the Rust submodule and
+# other language wrappers); instead we copy them here and append
+# `option optimize_for = LITE_RUNTIME;` so protoc emits MessageLite-based code
+# that links only against libprotobuf-lite.
+set(PROTO_LITE_SRC_DIR ${PROTO_BINARY_DIR}/proto-lite)
+file(MAKE_DIRECTORY ${PROTO_LITE_SRC_DIR})
+
+set(PATCHED_PROTO_FILES)
+foreach(_p ${FFI_PROTO_NAMES})
+ list(APPEND PATCHED_PROTO_FILES "${PROTO_LITE_SRC_DIR}/${_p}")
+endforeach()
+
+add_custom_command(
+ OUTPUT ${PATCHED_PROTO_FILES}
+ COMMAND ${CMAKE_COMMAND}
+ -DIN_DIR=${FFI_PROTO_DIR}
+ -DOUT_DIR=${PROTO_LITE_SRC_DIR}
+ "-DFILES=${FFI_PROTO_NAMES}"
+ -P ${LIVEKIT_ROOT_DIR}/cmake/patch_protos_for_lite.cmake
+ DEPENDS
+ ${FFI_PROTO_FILES}
+ ${LIVEKIT_ROOT_DIR}/cmake/patch_protos_for_lite.cmake
+ COMMENT "Patching .proto files with optimize_for = LITE_RUNTIME (C++ build only)"
+ VERBATIM
+)
+
+# Protobuf toolchain and lite runtime.
include(protobuf)
# spdlog logging library (PRIVATE dependency).
include(spdlog)
@@ -101,7 +132,7 @@ elseif(NOT Protobuf_PROTOC_EXECUTABLE)
endif()
message(STATUS "Using protoc: ${Protobuf_PROTOC_EXECUTABLE}")
-add_library(livekit_proto OBJECT ${FFI_PROTO_FILES})
+add_library(livekit_proto OBJECT ${PATCHED_PROTO_FILES})
# livekit_proto is compiled into liblivekit; apply the same hidden visibility
# policy so generated protobuf code does not leak into the SDK's exported ABI.
set_target_properties(livekit_proto PROPERTIES
@@ -109,10 +140,16 @@ set_target_properties(livekit_proto PROPERTIES
C_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
)
-if(TARGET protobuf::libprotobuf)
- set(LIVEKIT_PROTOBUF_TARGET protobuf::libprotobuf)
+# The C++ build links against protobuf-lite only. Generated code uses
+# MessageLite (no Reflection/Descriptor/TextFormat/JSON), and the SDK does
+# not use any of those APIs. See cmake/patch_protos_for_lite.cmake.
+if(TARGET protobuf::libprotobuf-lite)
+ set(LIVEKIT_PROTOBUF_TARGET protobuf::libprotobuf-lite)
else()
- message(FATAL_ERROR "No protobuf library target found (expected protobuf::libprotobuf)")
+ message(FATAL_ERROR
+ "protobuf::libprotobuf-lite target not found. The LiveKit C++ SDK requires "
+ "protobuf-lite. On Linux/macOS this comes from the vendored protobuf build; "
+ "on Windows it comes from the vcpkg protobuf port.")
endif()
set(LIVEKIT_PROTOBUF_DEP_INCLUDE_DIRS ${Protobuf_INCLUDE_DIRS})
if(TARGET absl::base)
@@ -136,12 +173,15 @@ target_include_directories(livekit_proto PRIVATE
)
target_link_libraries(livekit_proto PRIVATE ${LIVEKIT_PROTOBUF_TARGET})
livekit_disable_warnings(livekit_proto)
+message(STATUS "Using protobuf runtime target: ${LIVEKIT_PROTOBUF_TARGET}")
-# Manually generate protobuf files to avoid path prefix issues
+# Manually generate protobuf files to avoid path prefix issues. The inputs are
+# the patched copies in ${PROTO_LITE_SRC_DIR}, not the originals — see the
+# PATCHED_PROTO_FILES custom command above.
set(PROTO_SRCS)
set(PROTO_HDRS)
-foreach(PROTO_FILE ${FFI_PROTO_FILES})
- get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE)
+foreach(_name ${FFI_PROTO_NAMES})
+ get_filename_component(PROTO_NAME "${_name}" NAME_WE)
list(APPEND PROTO_SRCS "${PROTO_BINARY_DIR}/${PROTO_NAME}.pb.cc")
list(APPEND PROTO_HDRS "${PROTO_BINARY_DIR}/${PROTO_NAME}.pb.h")
endforeach()
@@ -149,11 +189,11 @@ endforeach()
add_custom_command(
OUTPUT ${PROTO_SRCS} ${PROTO_HDRS}
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
- --proto_path=${FFI_PROTO_DIR}
+ --proto_path=${PROTO_LITE_SRC_DIR}
--cpp_out=${PROTO_BINARY_DIR}
- ${FFI_PROTO_FILES}
- DEPENDS ${FFI_PROTO_FILES}
- COMMENT "Generating C++ protobuf files"
+ ${PATCHED_PROTO_FILES}
+ DEPENDS ${PATCHED_PROTO_FILES}
+ COMMENT "Generating C++ protobuf files (lite runtime)"
VERBATIM
)
diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md
index eb223af9..b24467f8 100644
--- a/DEPENDENCIES.md
+++ b/DEPENDENCIES.md
@@ -16,7 +16,7 @@ The SDK uses different distribution strategies per platform:
✅ **Ready to use** - All dependencies included:
- `livekit.lib` - Main SDK static library
- `livekit_ffi.dll` + `livekit_ffi.dll.lib` - Rust FFI dynamic library
-- `libprotobuf.dll` + `libprotobuf.lib` - Protocol Buffers runtime
+- `libprotobuf-lite.dll` + `libprotobuf-lite.lib` - Protocol Buffers lite runtime
- `abseil_dll.dll` + `abseil_dll.lib` - Abseil C++ library
**User action**: Copy all DLLs alongside your executable. No additional installation required.
@@ -25,7 +25,7 @@ The SDK uses different distribution strategies per platform:
⚠️ **Requires system dependencies**:
- `liblivekit.a` - Main SDK static library (included)
- `liblivekit_ffi.so` - Rust FFI dynamic library (included, **must be placed alongside your executable**)
-- `libprotobuf` - Must install via `apt install libprotobuf-dev`
+- `libprotobuf-lite` - provided by `apt install libprotobuf-dev`
- `libssl` - Must install via `apt install libssl-dev`
- `libabsl` - Only if built with Protobuf 6.0+: `apt install libabsl-dev`
@@ -175,8 +175,8 @@ target_link_libraries(your_app PRIVATE
livekit
livekit_ffi
- # Protobuf (REQUIRED)
- protobuf::libprotobuf
+ # Protobuf lite runtime (REQUIRED)
+ protobuf::libprotobuf-lite
# Linux system libraries (REQUIRED)
OpenSSL::SSL
@@ -196,7 +196,7 @@ g++ your_app.cpp \
-I/path/to/livekit/include \
-L/path/to/livekit/lib \
-llivekit -llivekit_ffi \
- -lprotobuf -lssl -lcrypto -lpthread -ldl
+ -lprotobuf-lite -lssl -lcrypto -lpthread -ldl
```
---
diff --git a/README.md b/README.md
index d9fd9d71..0506d252 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ cd client-sdk-cpp
```
Building requires a stable Rust toolchain and platform-specific build
-deps (`protobuf`, `abseil`, `openssl` on Linux). See [docs/building.md](docs/building.md)
+deps (`protobuf` for `protoc`/protobuf-lite, `abseil`, `openssl` on Linux). See [docs/building.md](docs/building.md)
for full prerequisites table, Docker recipe, CMake presets, and troubleshooting.
### Hello, LiveKit
diff --git a/cmake/patch_protos_for_lite.cmake b/cmake/patch_protos_for_lite.cmake
new file mode 100644
index 00000000..112a9589
--- /dev/null
+++ b/cmake/patch_protos_for_lite.cmake
@@ -0,0 +1,61 @@
+# cmake/patch_protos_for_lite.cmake
+#
+# Copy upstream .proto files (from client-sdk-rust/livekit-ffi/protocol/) into
+# a build-tree staging directory and append `option optimize_for = LITE_RUNTIME;`
+# to each one. The C++ SDK then compiles the patched copies, which causes
+# protoc to emit code linking only against libprotobuf-lite (no reflection,
+# no descriptors, no text-format, no JSON).
+#
+# This patches *only* the copies used by the C++ build. The original .proto
+# files in the client-sdk-rust submodule are untouched, so prost (Rust) and
+# protobuf-es (Node) generators continue to see the unmodified sources.
+#
+# Usage (invoked via `cmake -P`):
+# cmake -DIN_DIR=
-DOUT_DIR= "-DFILES=a.proto;b.proto;..." \
+# -P patch_protos_for_lite.cmake
+
+if(NOT DEFINED IN_DIR OR IN_DIR STREQUAL "")
+ message(FATAL_ERROR "patch_protos_for_lite.cmake: IN_DIR is required")
+endif()
+if(NOT DEFINED OUT_DIR OR OUT_DIR STREQUAL "")
+ message(FATAL_ERROR "patch_protos_for_lite.cmake: OUT_DIR is required")
+endif()
+if(NOT DEFINED FILES OR FILES STREQUAL "")
+ message(FATAL_ERROR "patch_protos_for_lite.cmake: FILES is required")
+endif()
+
+file(MAKE_DIRECTORY "${OUT_DIR}")
+
+set(_marker "// --- appended by client-sdk-cpp: force lite runtime for C++ codegen ---")
+set(_option_line "option optimize_for = LITE_RUNTIME;")
+
+foreach(_name IN LISTS FILES)
+ set(_src "${IN_DIR}/${_name}")
+ set(_dst "${OUT_DIR}/${_name}")
+
+ if(NOT EXISTS "${_src}")
+ message(FATAL_ERROR "patch_protos_for_lite.cmake: missing source ${_src}")
+ endif()
+
+ file(READ "${_src}" _content)
+
+ # If upstream already opts into lite, keep the file unchanged. If it chooses
+ # another runtime, fail rather than silently overriding that choice.
+ string(REGEX MATCH "(^|\n)[ \t]*option[ \t]+optimize_for[ \t]*=[ \t]*LITE_RUNTIME[ \t]*;" _existing_lite "${_content}")
+ if(_existing_lite)
+ file(WRITE "${_dst}" "${_content}")
+ continue()
+ endif()
+
+ string(REGEX MATCH "(^|\n)[ \t]*option[ \t]+optimize_for[ \t]*=" _existing_runtime "${_content}")
+ if(_existing_runtime)
+ message(FATAL_ERROR
+ "patch_protos_for_lite.cmake: ${_name} declares a non-lite optimize_for. "
+ "The LiveKit C++ SDK requires LITE_RUNTIME.")
+ endif()
+
+ # Append the option as a trailing line. File-level options have no ordering
+ # requirement in protobuf grammar, so this is always safe.
+ file(WRITE "${_dst}"
+ "${_content}\n${_marker}\n${_option_line}\n")
+endforeach()
diff --git a/cmake/protobuf.cmake b/cmake/protobuf.cmake
index 3e0fa33c..5fba4137 100644
--- a/cmake/protobuf.cmake
+++ b/cmake/protobuf.cmake
@@ -1,12 +1,13 @@
# cmake/protobuf.cmake
#
# Windows: use vcpkg Protobuf (static-md triplet) + vcpkg protoc
-# macOS/Linux: vendored Protobuf (static) + vendored Abseil + vendored protoc
+# macOS/Linux: vendored Protobuf + vendored Abseil + vendored protoc
+# The SDK links generated FFI code against protobuf-lite only.
#
# Exposes:
# - Protobuf_PROTOC_EXECUTABLE
# - Protobuf_INCLUDE_DIRS
-# - Target protobuf::libprotobuf (and optionally protobuf::libprotobuf-lite)
+# - Target protobuf::libprotobuf-lite
# - Target protobuf::protoc (on vendored path; on Windows we may only have an executable)
include(FetchContent)
@@ -17,8 +18,35 @@ option(LIVEKIT_USE_SYSTEM_PROTOBUF "Use system-installed Protobuf instead of ven
set(LIVEKIT_PROTOBUF_VERSION "25.3" CACHE STRING "Vendored Protobuf version")
set(LIVEKIT_ABSEIL_VERSION "20240116.2" CACHE STRING "Vendored Abseil version")
+function(livekit_require_protobuf_lite context)
+ if(TARGET protobuf::libprotobuf-lite)
+ # ok
+ elseif(TARGET libprotobuf-lite)
+ add_library(protobuf::libprotobuf-lite ALIAS libprotobuf-lite)
+ else()
+ message(FATAL_ERROR
+ "${context} Protobuf package did not provide protobuf::libprotobuf-lite. "
+ "The LiveKit C++ SDK requires protobuf-lite because generated FFI code is "
+ "compiled with option optimize_for = LITE_RUNTIME.")
+ endif()
+
+ livekit_treat_as_external(protobuf::libprotobuf-lite)
+ livekit_get_interface_includes(protobuf::libprotobuf-lite _pb_lite_includes)
+ if(_pb_lite_includes)
+ set(Protobuf_INCLUDE_DIRS "${_pb_lite_includes}" CACHE STRING "Protobuf include dirs" FORCE)
+ elseif(Protobuf_INCLUDE_DIRS)
+ set(Protobuf_INCLUDE_DIRS "${Protobuf_INCLUDE_DIRS}" CACHE STRING "Protobuf include dirs" FORCE)
+ elseif(DEFINED livekit_protobuf_SOURCE_DIR)
+ set(Protobuf_INCLUDE_DIRS "${livekit_protobuf_SOURCE_DIR}/src" CACHE STRING "Protobuf include dirs" FORCE)
+ else()
+ message(FATAL_ERROR
+ "${context} protobuf-lite target does not expose include directories and "
+ "Protobuf_INCLUDE_DIRS is empty.")
+ endif()
+endfunction()
+
# ---------------------------------------------------------------------------
-# Windows path: prefer vcpkg static-md protobuf to avoid /MT vs /MD mismatches.
+# Windows path: prefer vcpkg static-md protobuf-lite to avoid /MT vs /MD mismatches.
# This assumes you configure CMake with:
# -DCMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake
# -DVCPKG_TARGET_TRIPLET=x64-windows-static-md
@@ -29,7 +57,7 @@ if(WIN32 AND NOT LIVEKIT_USE_SYSTEM_PROTOBUF)
# If the user forgot the triplet, fail fast with a helpful message.
if(DEFINED VCPKG_TARGET_TRIPLET AND NOT VCPKG_TARGET_TRIPLET STREQUAL "x64-windows-static-md")
message(FATAL_ERROR
- "On Windows, LiveKit expects vcpkg triplet x64-windows-static-md for static protobuf + /MD.\n"
+ "On Windows, LiveKit expects vcpkg triplet x64-windows-static-md for static protobuf-lite + /MD.\n"
"You have VCPKG_TARGET_TRIPLET='${VCPKG_TARGET_TRIPLET}'.\n"
"Reconfigure with -DVCPKG_TARGET_TRIPLET=x64-windows-static-md."
)
@@ -37,7 +65,7 @@ if(WIN32 AND NOT LIVEKIT_USE_SYSTEM_PROTOBUF)
message(WARNING
"VCPKG_TARGET_TRIPLET is not set. On Windows you should configure with:\n"
" -DVCPKG_TARGET_TRIPLET=x64-windows-static-md\n"
- "to get static protobuf built against /MD."
+ "to get static protobuf-lite built against /MD."
)
endif()
@@ -47,7 +75,7 @@ if(WIN32 AND NOT LIVEKIT_USE_SYSTEM_PROTOBUF)
endif()
# Use vcpkg's Protobuf package (CONFIG mode provides imported targets).
- # This should give protobuf::libprotobuf and protobuf::protoc.
+ # This must provide protobuf::libprotobuf-lite and protobuf::protoc.
find_package(Protobuf CONFIG REQUIRED)
# Prefer protoc target if available; else fall back to locating protoc.
@@ -61,22 +89,10 @@ if(WIN32 AND NOT LIVEKIT_USE_SYSTEM_PROTOBUF)
set(Protobuf_PROTOC_EXECUTABLE "${Protobuf_PROTOC_EXECUTABLE}" CACHE STRING "protoc (found)" FORCE)
endif()
- # Include dirs: prefer the imported target usage requirements.
- if(TARGET protobuf::libprotobuf)
- get_target_property(_pb_includes protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
- livekit_treat_as_external(protobuf::libprotobuf)
- elseif(TARGET protobuf::protobuf) # some protobuf builds use protobuf::protobuf
- get_target_property(_pb_includes protobuf::protobuf INTERFACE_INCLUDE_DIRECTORIES)
- livekit_treat_as_external(protobuf::protobuf)
- endif()
+ livekit_require_protobuf_lite("Windows/vcpkg")
if(TARGET protobuf::protoc)
livekit_treat_as_external(protobuf::protoc)
endif()
- if(NOT _pb_includes)
- # Best-effort fallback: Protobuf_INCLUDE_DIRS is commonly set by ProtobufConfig
- set(_pb_includes "${Protobuf_INCLUDE_DIRS}")
- endif()
- set(Protobuf_INCLUDE_DIRS "${_pb_includes}" CACHE STRING "Protobuf include dirs" FORCE)
message(STATUS "Windows: using vcpkg Protobuf (expect triplet x64-windows-static-md)")
message(STATUS "Windows: protoc = ${Protobuf_PROTOC_EXECUTABLE}")
@@ -95,11 +111,7 @@ if(LIVEKIT_USE_SYSTEM_PROTOBUF)
if(NOT Protobuf_PROTOC_EXECUTABLE)
find_program(Protobuf_PROTOC_EXECUTABLE NAMES protoc REQUIRED)
endif()
- if(TARGET protobuf::libprotobuf)
- livekit_treat_as_external(protobuf::libprotobuf)
- elseif(TARGET protobuf::protobuf)
- livekit_treat_as_external(protobuf::protobuf)
- endif()
+ livekit_require_protobuf_lite("System")
if(TARGET protobuf::protoc)
livekit_treat_as_external(protobuf::protoc)
endif()
@@ -206,23 +218,7 @@ else()
message(FATAL_ERROR "Vendored protobuf did not create a protoc target")
endif()
-# Prefer protobuf-lite (optional; keep libprotobuf around too)
-if(TARGET protobuf::libprotobuf-lite)
- # ok
-elseif(TARGET libprotobuf-lite)
- add_library(protobuf::libprotobuf-lite ALIAS libprotobuf-lite)
-else()
- message(WARNING "Vendored protobuf did not create protobuf-lite target; continuing with libprotobuf only")
-endif()
-
-# Include dirs: prefer target usage; keep this var for your existing CMakeLists.
-if(TARGET protobuf::libprotobuf)
- livekit_get_interface_includes(protobuf::libprotobuf _pb_includes)
-endif()
-if(NOT _pb_includes)
- set(_pb_includes "${livekit_protobuf_SOURCE_DIR}/src")
-endif()
-set(Protobuf_INCLUDE_DIRS "${_pb_includes}" CACHE STRING "Protobuf include dirs" FORCE)
+livekit_require_protobuf_lite("Vendored")
message(STATUS "macOS/Linux: using vendored Protobuf v${LIVEKIT_PROTOBUF_VERSION}")
message(STATUS "macOS/Linux: vendored protoc: ${Protobuf_PROTOC_EXECUTABLE}")
diff --git a/docs/building.md b/docs/building.md
index 60f08a71..68e0a4c5 100644
--- a/docs/building.md
+++ b/docs/building.md
@@ -12,7 +12,7 @@ CMake/vcpkg flows, and Docker.
- **Rust / Cargo** — latest stable toolchain (for building the Rust FFI layer).
Install via [rustup](https://rustup.rs/).
- **Git LFS** — required for examples that pull test media assets.
-- **Protobuf** ≥ 5.29
+- **Protobuf** ≥ 5.29 — provides `protoc`; the SDK links against protobuf-lite.
- **Abseil** — always required (used by Protobuf 5.x+)
### Platform-specific toolchains
@@ -204,7 +204,7 @@ export PATH=$HOME/cmake-3.31/bin:$PATH
| Option | Default | Description |
|--------|---------|-------------|
| `LIVEKIT_BUILD_EXAMPLES` | OFF | Build example applications |
-| `LIVEKIT_USE_SYSTEM_PROTOBUF` | OFF | Use system Protobuf instead of vcpkg's |
+| `LIVEKIT_USE_SYSTEM_PROTOBUF` | OFF | Use system Protobuf instead of the vendored package |
| `LIVEKIT_LOG_LEVEL` | `TRACE` | Compile-time log threshold (see [logging.md](logging.md)) |
| `LIVEKIT_VERSION` | repo-derived | SDK version string baked into the binary |
@@ -288,17 +288,17 @@ OpenSSL::SSL OpenSSL::Crypto
### Runtime dependencies of prebuilt artifacts
-Whether protobuf / abseil / openssl need to be installed on the target
+Whether protobuf-lite / abseil / openssl need to be installed on the target
machine depends on how the SDK binary was built:
- **Windows** release artifacts use vcpkg triplet `x64-windows-static-md` —
- protobuf and abseil are statically linked into the DLLs; no runtime install
+ protobuf-lite and abseil are statically linked into the DLLs; no runtime install
needed.
- **macOS** release artifacts (from our CI) do **not** dynamically depend on
- protobuf / abseil / openssl. You can verify with `otool -L liblivekit.dylib`.
+ protobuf-lite / abseil / openssl. You can verify with `otool -L liblivekit.dylib`.
- **Linux** depends on packaging. Check with `ldd liblivekit_ffi.so`; if any
of those are listed, install the corresponding `-dev` (build) or runtime
- package (`libprotobuf32` / `libabsl` / `libssl3`) as appropriate.
+ package (`libprotobuf-lite32` / `libabsl` / `libssl3`) as appropriate.
## Troubleshooting
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 9583af73..20a9e6bb 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -79,9 +79,8 @@ if(UNIT_TEST_SOURCES)
)
# liblivekit no longer re-exports protobuf/absl symbols (hidden visibility +
- # --exclude-libs,ALL). Tests that touch livekit::proto::* types or absl
- # helpers must link the proto object library and the libprotobuf static
- # archive directly.
+ # --exclude-libs,ALL). Tests that touch livekit::proto::* types or absl
+ # helpers must link the proto object library and protobuf-lite directly.
if(TARGET livekit_proto)
target_sources(livekit_unit_tests PRIVATE $)
endif()
@@ -172,9 +171,8 @@ if(INTEGRATION_TEST_SOURCES)
)
# liblivekit no longer re-exports protobuf/absl symbols (hidden visibility +
- # --exclude-libs,ALL). Tests that touch livekit::proto::* types or absl
- # helpers must link the proto object library and the libprotobuf static
- # archive directly.
+ # --exclude-libs,ALL). Tests that touch livekit::proto::* types or absl
+ # helpers must link the proto object library and protobuf-lite directly.
if(TARGET livekit_proto)
target_sources(livekit_integration_tests PRIVATE $)
endif()