diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f9d7ca0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,38 @@ +# Copyright 2026 LiveKit +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Rust build output (huge; rebuilt inside image) +client-sdk-rust/target/ + +# Git and IDE +.git +.gitignore +.gitmodules +.cursor +.vscode +*.swp +*~ + +# Build outputs and caches +build/ +*.log +__pycache__/ + +# Docker +Dockerfile +.dockerignore + +# Docs and misc (optional; uncomment if you never need these in the image) +# README.md +# *.md diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index a0a92e6..ee510c1 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -7,12 +7,14 @@ on: - src/** - include/** - examples/** + - bridge/** - client-sdk-rust/** - CMakeLists.txt - build.sh - build.cmd - vcpkg.json - CMakePresets.json + - docker/Dockerfile - .github/workflows/** pull_request: branches: ["main"] @@ -20,12 +22,14 @@ on: - src/** - include/** - examples/** + - bridge/** - client-sdk-rust/** - CMakeLists.txt - build.sh - build.cmd - vcpkg.json - CMakePresets.json + - docker/Dockerfile - .github/workflows/** workflow_dispatch: @@ -246,3 +250,25 @@ jobs: else ./build.sh clean-all || true fi + + docker-build: + name: Build (docker-linux-x64) + runs-on: ubuntu-latest + + steps: + - name: Checkout (with submodules) + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker image + run: docker build -t livekit-cpp-sdk:${{ github.sha }} . -f docker/Dockerfile + + - name: Build SDK inside Docker + run: | + docker run --rm livekit-cpp-sdk:${{ github.sha }} bash -c \ + 'cd /client-sdk-cpp && chmod +x build.sh && ./build.sh release-examples' diff --git a/README.md b/README.md index fcd8178..eb473f2 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,7 @@ Use this SDK to add realtime video, audio and data features to your C++ app. By connecting to LiveKit Cloud or a self-hosted server, you can quickly build applications such as multi-modal AI, live streaming, or video calls with just a few lines of code. -## Build & Installation Guide - -This page covers how to build and install the LiveKit C++ Client SDK for real-time audio/video communication. - ---- - -### ๐Ÿ“ฆ Requirements +## ๐Ÿ“ฆ Requirements - **CMake** โ‰ฅ 3.20 - **Rust / Cargo** (latest stable toolchain) - **Git LFS** (required for examples) @@ -31,19 +25,19 @@ This page covers how to build and install the LiveKit C++ Client SDK for real-ti **Platform-Specific Requirements:** -#### For Building the SDK: +### For Building the SDK: - **Windows:** Visual Studio 2019+, vcpkg - **Linux:** `sudo apt install libprotobuf-dev libssl-dev` (protobuf 3.x) - **macOS:** `brew install protobuf` (protobuf 3.x) -#### For Using the Pre-built SDK: +### For Using the Pre-built SDK: - **Windows:** โœ… All dependencies included (DLLs bundled) - ready to use - **Linux:** โš ๏ธ Requires `libprotobuf` and `libssl-dev`; deploy `liblivekit_ffi.so` with your executable - **macOS:** โš ๏ธ Requires `protobuf`; deploy `liblivekit_ffi.dylib` with your executable > **Note**: If the SDK was built with Protobuf 6.0+, you also need `libabsl-dev` (Linux) or `abseil` (macOS). -### ๐Ÿงฉ Clone the Repository +## ๐Ÿงฉ Clone the Repository Make sure to initialize the Rust submodule (`client-sdk-rust`): @@ -57,9 +51,9 @@ cd client-sdk-cpp git submodule update --init --recursive ``` -### โš™๏ธ BUILD +## โš™๏ธ BUILD -#### Quick Build (Using Build Scripts) +### Quick Build (Using Build Scripts) **Linux/macOS:** ```bash @@ -71,6 +65,17 @@ git submodule update --init --recursive ./build.sh release-tests # Build Release with tests ``` **Windows** +Using build scripts: +```powershell +.\build.cmd clean # Clean CMake build artifacts +.\build.cmd clean-all # Deep clean (C++ + Rust + generated files) +.\build.cmd debug # Build Debug version +.\build.cmd release # Build Release version +.\build.cmd debug-tests # Build Debug with tests +.\build.cmd release-tests # Build Release with tests +``` + +### Windows build using cmake/vcpkg ```bash cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE="$PWD/vcpkg/scripts/buildsystems/vcpkg.cmake" # Generate Makefiles in build folder # Build (Release or Debug) @@ -86,17 +91,7 @@ You must install protobuf via vcpkg (so CMake can find ProtobufConfig.cmake and .\vcpkg\vcpkg install protobuf:x64-windows ``` -**Windows:** -```powershell -.\build.cmd clean # Clean CMake build artifacts -.\build.cmd clean-all # Deep clean (C++ + Rust + generated files) -.\build.cmd debug # Build Debug version -.\build.cmd release # Build Release version -.\build.cmd debug-tests # Build Debug with tests -.\build.cmd release-tests # Build Release with tests -``` - -#### Advanced Build (Using CMake Presets) +### Advanced Build (Using CMake Presets) For more control and platform-specific builds, see the detailed instructions in [README_BUILD.md](README_BUILD.md). @@ -128,7 +123,24 @@ cmake --build --preset macos-release ๐Ÿ“– **For complete build instructions, troubleshooting, and platform-specific notes, see [README_BUILD.md](README_BUILD.md)** -### ๐Ÿงช Run Example +### Building with Docker +The Dockerfile COPYs folders/files required to build the CPP SDK into the image. + **NOTE:** this has only been tested on Linux +```bash +docker build -t livekit-cpp-sdk . -f docker/Dockerfile +docker run -it --network host livekit-cpp-sdk:latest bash +``` + +__NOTE:__ if you are building your own Dockerfile, you will likely need to set the same `ENV` variables as in `docker/Dockerfile`, but to the relevant directories: +```bash +export CC=$HOME/gcc-14/bin/gcc +export CXX=$HOME/gcc-14/bin/g++ +export LD_LIBRARY_PATH=$HOME/gcc-14/lib64:$LD_LIBRARY_PATH +export PATH=$HOME/.cargo/bin:$PATH +export PATH=$HOME/cmake-3.31/bin:$PATH +``` + +## ๐Ÿงช Run Example ### Generate Tokens Before running any participant, create JWT tokens with the proper identity and room name, example @@ -136,7 +148,7 @@ Before running any participant, create JWT tokens with the proper identity and r lk token create -r test -i your_own_identity --join --valid-for 99999h --dev --room=your_own_room ``` -#### SimpleRoom +### SimpleRoom ```bash ./build/examples/SimpleRoom --url $URL --token @@ -164,7 +176,7 @@ If the E2EE keys do not match between participants: Press Ctrl-C to exit the example. -#### SimpleRpc +### SimpleRpc The SimpleRpc example demonstrates how to: - Connect multiple participants to the same LiveKit room - Register RPC handlers (e.g., arrival, square-root, divide, long-calculation) @@ -172,7 +184,7 @@ The SimpleRpc example demonstrates how to: - Handle success, application errors, unsupported methods, and timeouts - Observe round-trip times (RTT) for each RPC call -##### ๐Ÿ”‘ Generate Tokens +#### ๐Ÿ”‘ Generate Tokens Before running any participant, create JWT tokens with **caller**, **greeter** and **math-genius** identities and room name. ```bash lk token create -r test -i caller --join --valid-for 99999h --dev --room=your_own_room @@ -180,7 +192,7 @@ lk token create -r test -i greeter --join --valid-for 99999h --dev --room=your_o lk token create -r test -i math-genius --join --valid-for 99999h --dev --room=your_own_room ``` -##### โ–ถ Start Participants +#### โ–ถ Start Participants Every participant is run as a separate terminal process, note --role needs to match the token identity. ```bash ./build/examples/SimpleRpc --url $URL --token --role=math-genius @@ -191,7 +203,7 @@ The caller will automatically: - Print round-trip times - Annotate expected successes or expected failures -#### SimpleDataStream +### SimpleDataStream - The SimpleDataStream example demonstrates how to: - Connect multiple participants to the same LiveKit room - Register text stream and byte stream handlers by topic (e.g. "chat", "files") @@ -201,14 +213,14 @@ The caller will automatically: - Measure and print one-way latency on the receiver using sender timestamps - Receive streamed chunks and reconstruct the full payload on the receiver -##### ๐Ÿ”‘ Generate Tokens +#### ๐Ÿ”‘ Generate Tokens Before running any participant, create JWT tokens with caller and greeter identities and your room name. ```bash lk token create -r test -i caller --join --valid-for 99999h --dev --room=your_own_room lk token create -r test -i greeter --join --valid-for 99999h --dev --room=your_own_room ``` -##### โ–ถ Start Participants +#### โ–ถ Start Participants Start the receiver first (so it registers stream handlers before messages arrive): ```bash ./build/examples/SimpleDataStream --url $URL --token @@ -312,7 +324,7 @@ and a **ROS2 bridge** that maps `LogLevel` to `RCLCPP_*` macros. --- -### ๐Ÿงช Integration & Stress Tests +## ๐Ÿงช Integration & Stress Tests The SDK includes integration and stress tests using Google Test (gtest). @@ -330,7 +342,7 @@ The SDK includes integration and stress tests using Google Test (gtest). .\build.cmd release-tests ``` -#### Run Tests +### Run Tests After building, run tests using ctest or directly: @@ -348,7 +360,7 @@ ctest --output-on-failure ./build-debug/bin/livekit_stress_tests --gtest_filter="*MaxPayloadStress*" ``` -#### Test Types +### Test Types | Executable | Description | |------------|-------------| @@ -376,7 +388,7 @@ lk token create -r test -i rpc-caller --join --valid-for 99999h --dev --room=rpc lk token create -r test -i rpc-receiver --join --valid-for 99999h --dev --room=rpc-test-room ``` -#### Test Coverage +### Test Coverage - **SDK Initialization**: Initialize/shutdown lifecycle - **Room**: Room creation, options, connection @@ -384,21 +396,21 @@ lk token create -r test -i rpc-receiver --join --valid-for 99999h --dev --room=r - **RPC**: Round-trip calls, max payload (15KB), timeouts, errors, concurrent calls - **Stress Tests**: High throughput, bidirectional RPC, memory pressure -### ๐Ÿงฐ Recommended Setup -#### macOS +## ๐Ÿงฐ Recommended Setup +### macOS ```bash brew install cmake protobuf rust ``` -#### Ubuntu / Debian +### Ubuntu / Debian ```bash sudo apt update sudo apt install -y cmake protobuf-compiler build-essential curl https://sh.rustup.rs -sSf | sh ``` -### ๐Ÿ› ๏ธ Development Tips -#### Update Rust version +## ๐Ÿ› ๏ธ Development Tips +### Update Rust version ```bash cd client-sdk-cpp git fetch origin @@ -417,19 +429,19 @@ git -C client-sdk-rust/yuv-sys submodule update --init --recursive --checkout git submodule status --recursive ``` -#### If yuv-sys fails to build +### If yuv-sys fails to build ```bash cargo clean -p yuv-sys cargo build -p yuv-sys -vv ``` -#### Full clean (Rust + C++ build folders) +### Full clean (Rust + C++ build folders) In some cases, you may need to perform a full clean that deletes all build artifacts from both the Rust and C++ folders: ```bash ./build.sh clean-all ``` -#### Clang format +### Clang format CPP SDK is using clang C++ format ```bash brew install clang-format diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..647f46f --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,123 @@ +# Copyright 2026 LiveKit +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Build with: +# docker build -t livekit-cpp-sdk . -f docker/Dockerfile +# From repo root. +# Run with: +# docker run -it --network host livekit-cpp-sdk:latest bash + +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive +ENV HOME=/root + +# Install make, pkg-config, and base build deps (pkg-config + libglib2.0-dev for Rust glib-sys, libasound2-dev for alsa-sys) +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + git \ + libasound2-dev \ + libclang-dev \ + libdrm-dev \ + libglib2.0-dev \ + libssl-dev \ + libunwind-dev \ + libusb-1.0-0-dev \ + libva-dev \ + make \ + ninja-build \ + pkg-config \ + wget \ + xz-utils \ + && rm -rf /var/lib/apt/lists/* + +# Install GCC 14 first (slow; keep early for better layer caching) +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + flex \ + libgmp-dev \ + libmpc-dev \ + libmpfr-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN cd $HOME \ + && wget https://ftp.gnu.org/gnu/gcc/gcc-14.2.0/gcc-14.2.0.tar.xz \ + && tar xf gcc-14.2.0.tar.xz \ + && cd gcc-14.2.0 \ + && ./configure --prefix=$HOME/gcc-14 --enable-languages=c,c++ --disable-multilib --disable-bootstrap \ + && make -j$(nproc) \ + && make install \ + && cd $HOME \ + && rm -rf gcc-14.2.0 gcc-14.2.0.tar.xz + +RUN mkdir -p /home/installs && cp -a $HOME/gcc-14/bin/* /home/installs/ + +ENV CC=$HOME/gcc-14/bin/gcc +ENV CXX=$HOME/gcc-14/bin/g++ +ENV LD_LIBRARY_PATH=$HOME/gcc-14/lib64 + +# Install CMake 3.31.5 for current architecture (prefix dir must exist before installer runs) +# TARGETARCH is set by Docker BuildKit when building (amd64 -> x86_64, arm64 -> aarch64) +ARG TARGETARCH +RUN mkdir -p $HOME/cmake-3.31 \ + && CMAKE_ARCH=$(case "$TARGETARCH" in amd64) echo x86_64 ;; arm64) echo aarch64 ;; *) echo "$TARGETARCH" ;; esac) \ + && wget -q "https://github.com/Kitware/CMake/releases/download/v3.31.5/cmake-3.31.5-linux-${CMAKE_ARCH}.sh" \ + -O cmake-installer.sh \ + && chmod +x cmake-installer.sh \ + && ./cmake-installer.sh --skip-license --prefix=$HOME/cmake-3.31 \ + && rm cmake-installer.sh + +ENV PATH=$HOME/cmake-3.31/bin:$PATH + +# Install Rust (non-interactive) +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ + && . $HOME/.cargo/env && rustup default stable + +ENV PATH=$HOME/.cargo/bin:$PATH + +# Deps for SDL (X11 + OpenGL/GLX for FindOpenGL) +RUN apt-get update && apt-get install -y --no-install-recommends \ + libgl1-mesa-dev \ + libx11-dev \ + libxcursor-dev \ + libxext-dev \ + libxfixes-dev \ + libxi-dev \ + libxrandr-dev \ + && rm -rf /var/lib/apt/lists/* + +# Copy project source (build context = repo root) +WORKDIR /client-sdk-cpp +RUN mkdir -p /client-sdk-cpp +COPY src /client-sdk-cpp/src +COPY include /client-sdk-cpp/include +COPY bridge /client-sdk-cpp/bridge +COPY build.sh /client-sdk-cpp/build.sh +COPY CMakePresets.json /client-sdk-cpp/CMakePresets.json +COPY build.cmd /client-sdk-cpp/build.cmd +COPY client-sdk-rust /client-sdk-cpp/client-sdk-rust +COPY data /client-sdk-cpp/data +COPY examples /client-sdk-cpp/examples +COPY cmake /client-sdk-cpp/cmake +COPY CMakeLists.txt /client-sdk-cpp/CMakeLists.txt +COPY build.h.in /client-sdk-cpp/build.h.in +COPY build.sh /client-sdk-cpp/build.sh +COPY build.cmd /client-sdk-cpp/build.cmd + +# Configure Rust linker: use full GCC path so liblto_plugin.so is found (not /home/installs/ which has no plugin) +RUN mkdir -p /client-sdk-cpp/client-sdk-rust/.cargo \ + && printf '%s\n' '[target.x86_64-unknown-linux-gnu]' 'linker = "/root/gcc-14/bin/g++"' \ + '[target.aarch64-unknown-linux-gnu]' 'linker = "/root/gcc-14/bin/g++"' > /client-sdk-cpp/client-sdk-rust/.cargo/config.toml +