Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6560b8b
Trying a build without cpp-linter ignore
alan-george-lk Apr 23, 2026
b9b4a35
See if CI matches local
alan-george-lk Apr 23, 2026
2336dca
Additional fixes
alan-george-lk Apr 23, 2026
2a57f85
Try custom clang CI job
alan-george-lk Apr 23, 2026
54599fb
Merge branch 'main' into bugfix/clang-tidy
alan-george-lk Apr 23, 2026
897fcfa
Another run with issues fixed
alan-george-lk Apr 23, 2026
aedb6f4
Merge branch 'bugfix/clang-tidy' of github.com:livekit/client-sdk-cpp…
alan-george-lk Apr 23, 2026
73f9d26
Guard against missing protobuf files
alan-george-lk Apr 24, 2026
47d5b3c
Add link to table
alan-george-lk Apr 24, 2026
12572fd
Try linking to issues
alan-george-lk Apr 24, 2026
156f47e
No type traits, actually stream clang-tidy output locally, easy fixes
alan-george-lk Apr 24, 2026
b087b08
Induce error to see how CI performs
alan-george-lk Apr 24, 2026
ed9408c
Fix formatting
alan-george-lk Apr 27, 2026
9b10e20
Induce warnings for CI
alan-george-lk Apr 27, 2026
a63bd36
Try iconography
alan-george-lk Apr 27, 2026
64cb6cf
Adjust script name/location/output
alan-george-lk Apr 27, 2026
4d1fbb7
Many clang fixes, reduce bash version required on script, added unit …
alan-george-lk Apr 28, 2026
29d4451
Final fixes/CI adjustments
alan-george-lk Apr 28, 2026
d7da2e0
Adjustments from self-PR review, reducing AI-noise
alan-george-lk Apr 28, 2026
815ff9a
Fix unit test
alan-george-lk Apr 29, 2026
62f010d
Revert unintended line-ending change in CMakePresets.json
alan-george-lk Apr 29, 2026
e5c7b62
Merge branch 'main' of github.com:livekit/client-sdk-cpp into bugfix/…
alan-george-lk Apr 29, 2026
0430a0f
Add copyright/help
alan-george-lk Apr 29, 2026
fea9018
Fix for subscription data frame callback ID
alan-george-lk Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Checks: >
-bugprone-easily-swappable-parameters,
-modernize-use-trailing-return-type,
-modernize-avoid-c-arrays,
-modernize-type-traits,
-modernize-use-auto,
-modernize-use-nodiscard,
-modernize-return-braced-init-list,
Expand All @@ -29,7 +30,8 @@ WarningsAsErrors: >
bugprone-string-literal-with-embedded-nul,
bugprone-suspicious-memset-usage,

HeaderFilterRegex: '(include/livekit|src|examples)'
HeaderFilterRegex: '.*/(include/livekit|src)/.*\.(h|hpp)$'
ExcludeHeaderFilterRegex: '(.*/src/tests/.*)|(.*/_deps/.*)|(.*/build-[^/]*/.*)'

FormatStyle: file

Expand Down
59 changes: 27 additions & 32 deletions .github/workflows/builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,6 @@ jobs:
continue-on-error: false
permissions:
contents: read
pull-requests: write

steps:
- name: Checkout (with submodules)
Expand All @@ -568,8 +567,28 @@ jobs:
sudo apt-get update
sudo apt-get install -y \
build-essential cmake ninja-build pkg-config \
llvm-dev libclang-dev clang clang-tidy \
libssl-dev
llvm-dev libclang-dev clang \
libssl-dev wget ca-certificates gnupg

- name: Install clang-tidy 19 (for ExcludeHeaderFilterRegex support)
run: |
set -eux
# Ubuntu 24.04 apt ships clang-tidy 18, which doesn't understand
# ExcludeHeaderFilterRegex (added in 19). Pull clang-tidy 19 from
# the upstream LLVM apt repository and pin the unversioned names.
sudo install -m 0755 -d /etc/apt/keyrings
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key \
| sudo tee /etc/apt/keyrings/llvm.asc >/dev/null
sudo chmod a+r /etc/apt/keyrings/llvm.asc
codename=$(lsb_release -cs)
echo "deb [signed-by=/etc/apt/keyrings/llvm.asc] http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-19 main" \
| sudo tee /etc/apt/sources.list.d/llvm-19.list >/dev/null
sudo apt-get update
sudo apt-get install -y clang-tidy-19 clang-tools-19
sudo ln -sf /usr/bin/clang-tidy-19 /usr/local/bin/clang-tidy
sudo ln -sf /usr/bin/run-clang-tidy-19 /usr/local/bin/run-clang-tidy
clang-tidy --version
run-clang-tidy --help | head -1 || true

- name: Install Rust (stable)
uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
Expand All @@ -590,33 +609,9 @@ jobs:
run: cmake --build build-release --target livekit_proto

- name: Run clang-tidy
uses: cpp-linter/cpp-linter-action@77c390c5ba9c947ebc185a3e49cc754f1558abb5 # v2.18.0
id: linter
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
style: ''
tidy-checks: ''
database: build-release
files-changed-only: false
lines-changed-only: true
extensions: 'c,cpp,cc,cxx'
ignore: 'build-*|cpp-example-collection|client-sdk-rust|vcpkg_installed|src/tests|bridge|src/room_event_converter.cpp'
file-annotations: true
thread-comments: false
step-summary: true
tidy-review: false
no-lgtm: true
jobs: 0 # 0 == use all available CPU cores

- name: Check warning thresholds
env:
TIDY_FINDINGS: ${{ steps.linter.outputs.clang-tidy-checks-failed }}
MAX_TIDY_FINDINGS: '0'
run: |
echo "clang-tidy findings: ${TIDY_FINDINGS}"
if [ "${TIDY_FINDINGS}" -gt "${MAX_TIDY_FINDINGS}" ]; then
echo "::warning::clang-tidy found ${TIDY_FINDINGS} issue(s), threshold is ${MAX_TIDY_FINDINGS}"
exit 1
fi
echo "clang-tidy findings within threshold"
TIDY_BLOB_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
# This script is intended to be run locally and in CI. It will auto-detect
# the GHA environment and add PR annotations and a run summary.
# As of writing all warnings are treateded as errors to avoid tech debt build up
run: ./scripts/clang-tidy.sh --fail-on-warning
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ lib/
*.dylib
*.dll
*.exe
livekit.log
*.log
Comment thread
alan-george-lk marked this conversation as resolved.
web/
*trace.json
compile_commands.json
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Be sure to update the directory layout in this file if the directory layout chan
| `client-sdk-rust/livekit-ffi/protocol/*.proto` | FFI contract (protobuf definitions, read-only reference) |
| `cmake/` | Build helpers (`protobuf.cmake`, `spdlog.cmake`, `LiveKitConfig.cmake.in`) |
| `docker/` | Dockerfile for CI and SDK distribution images |
| `scripts/` | Developer / CI helper scripts (e.g. `clang-tidy.sh`) |
Comment thread
alan-george-lk marked this conversation as resolved.
| `.github/workflows/` | GitHub Actions CI workflows |

### Key Types
Expand Down
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -522,13 +522,28 @@ sudo apt-get install clang-format clang-tidy clang-tools

To run:

1. Run a build script command, such that `compile_command.json` is present at the root of the repository
2. Run:
1. Generate `compile_commands.json` and the protobuf headers via a release build:

```bash
clang-tidy -p . src/*.cpp
./build.sh release
```

1. Run the clang-tidy wrapper, which uses the same file set, regex filters, and `.clang-tidy` config as CI:

```bash
./scripts/clang-tidy.sh
```

The wrapper forwards extra arguments to `run-clang-tidy`, examples below:

```bash
./scripts/clang-tidy.sh -j 4 # Change number of cores used
./scripts/clang-tidy.sh -checks='-*,misc-const-correctness' # Only run certain checks
./scripts/clang-tidy.sh -fix # Apply fixes automatically
```

Output is captured to `clang-tidy.log` at the repo root. This is done as a convenience feature, as often times the terminal buffer is not large enough for all the output.

### Memory Checks

Run valgrind on various examples or tests to check for memory leaks and other issues.
Expand Down
4 changes: 4 additions & 0 deletions include/livekit/audio_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ class FfiEvent;
* This struct wraps an AudioFrame and is used as the output type when
* reading from an AudioStream.
*/
// NOLINTBEGIN(bugprone-exception-escape)
// AudioFrame can throw in various places monitored by bugprone-exception-escape
// Suppressing for now, would require significant refactor to fix
struct AudioFrameEvent {
AudioFrame frame; ///< The decoded PCM audio frame.
};
// NOLINTEND(bugprone-exception-escape)

/**
* Represents a pull-based stream of decoded PCM audio frames coming from
Expand Down
5 changes: 0 additions & 5 deletions include/livekit/local_track_publication.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,11 @@ namespace proto {
class OwnedTrackPublication;
}

class Track;

class LocalTrackPublication : public TrackPublication {
public:
/// Note, this LocalTrackPublication is constructed internally only;
/// safe to accept proto::OwnedTrackPublication.
explicit LocalTrackPublication(const proto::OwnedTrackPublication &owned);

/// Typed accessor for the attached LocalTrack (if any).
std::shared_ptr<Track> track() const noexcept;
};

} // namespace livekit
7 changes: 1 addition & 6 deletions include/livekit/remote_track_publication.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,12 @@ namespace proto {
class OwnedTrackPublication;
}

class Track;

class RemoteTrackPublication : public TrackPublication {
public:
/// Note, this RemoteTrackPublication is constructed internally only;
/// safe to accept proto::OwnedTrackPublication.
explicit RemoteTrackPublication(const proto::OwnedTrackPublication &owned);

/// Typed accessor for the attached RemoteTrack (if any).
std::shared_ptr<Track> track() const noexcept;


bool subscribed() const noexcept { return subscribed_; }

void setSubscribed(bool subscribed);
Expand Down
13 changes: 13 additions & 0 deletions include/livekit/result.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,49 +64,62 @@ template <typename T, typename E> class [[nodiscard]] Result {
/// Allows `if (result)` style success checks.
explicit operator bool() const noexcept { return ok(); }

// TODO (AEG): clang-tidy flagged these accessors because the signatures are marked
// noexcept, but std::get can throw a std::bad_variant_access exception on
// std::variant specifically. Investigate if this is actually a concern or if the types
// are safe within this class (unit test ideal).

/// Access the success value. Requires `ok() == true`.
// NOLINTNEXTLINE(bugprone-exception-escape)
T &value() & noexcept {
assert(ok());
return std::get<0>(storage_);
}

/// Access the success value. Requires `ok() == true`.
// NOLINTNEXTLINE(bugprone-exception-escape)
const T &value() const & noexcept {
assert(ok());
return std::get<0>(storage_);
}

/// Move the success value out. Requires `ok() == true`.
// NOLINTNEXTLINE(bugprone-exception-escape)
T &&value() && noexcept {
assert(ok());
return std::get<0>(std::move(storage_));
}

/// Move the success value out. Requires `ok() == true`.
// NOLINTNEXTLINE(bugprone-exception-escape)
const T &&value() const && noexcept {
assert(ok());
return std::get<0>(std::move(storage_));
}

/// Access the error value. Requires `has_error() == true`.
// NOLINTNEXTLINE(bugprone-exception-escape)
E &error() & noexcept {
assert(has_error());
return std::get<1>(storage_);
}

/// Access the error value. Requires `has_error() == true`.
// NOLINTNEXTLINE(bugprone-exception-escape)
const E &error() const & noexcept {
assert(has_error());
return std::get<1>(storage_);
}

/// Move the error value out. Requires `has_error() == true`.
// NOLINTNEXTLINE(bugprone-exception-escape)
E &&error() && noexcept {
assert(has_error());
return std::get<1>(std::move(storage_));
}

/// Move the error value out. Requires `has_error() == true`.
// NOLINTNEXTLINE(bugprone-exception-escape)
const E &&error() const && noexcept {
assert(has_error());
return std::get<1>(std::move(storage_));
Expand Down
2 changes: 1 addition & 1 deletion include/livekit/subscription_thread_dispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ class SubscriptionThreadDispatcher {
active_readers_;

/// Next auto-increment ID for data frame callbacks.
DataFrameCallbackId next_data_callback_id_;
DataFrameCallbackId next_data_callback_id_{0};

/// Registered data frame callbacks keyed by opaque callback ID.
std::unordered_map<DataFrameCallbackId, RegisteredDataCallback>
Expand Down
2 changes: 2 additions & 0 deletions include/livekit/track.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class Track {
std::optional<bool> simulcasted() const noexcept { return simulcasted_; }
std::optional<uint32_t> width() const noexcept { return width_; }
std::optional<uint32_t> height() const noexcept { return height_; }
// std::string can actually throw, suppressing for now to maintain API compatibility
// NOLINTNEXTLINE(bugprone-exception-escape)
std::optional<std::string> mime_type() const noexcept { return mime_type_; }

// Handle access
Expand Down
Loading
Loading