Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
5650af3
fix build for win.
cloudwebrtc Jul 27, 2026
da62c24
bump libwebrtc deps.
cloudwebrtc Jul 27, 2026
c7723dd
fix build on linux.
cloudwebrtc Jul 27, 2026
baae74a
fix build for android.
cloudwebrtc Jul 27, 2026
11f6bd0
Create feat_upgrade_libwebrtc_to_m150.md
cloudwebrtc Jul 28, 2026
49dbff1
bump libwebrtc to webrtc-a970b87 (m150 pre-release).
cloudwebrtc Jul 28, 2026
f4c43f2
fix ffi build.
cloudwebrtc Jul 28, 2026
b216c99
fix h264 compile.
cloudwebrtc Jul 28, 2026
2ebb2bc
fix: use libyuv directly in yuv_helper.h to fix win-arm64 linker errors
Copilot Jul 28, 2026
7bc323e
fix: revert use_custom_libcxx=false in build_linux.sh to fix Linux li…
Copilot Jul 28, 2026
ffd1d5a
fix build issue on linux.
cloudwebrtc Jul 28, 2026
1b652e9
chore: update changeset to cover all affected packages
Copilot Jul 28, 2026
27a5748
Update WEBRTC_TAG constant to new version
cloudwebrtc Jul 28, 2026
d1b7fdb
Fix Android build: provide weak NDK r28 compat stub for __hash_memory
Copilot Jul 28, 2026
28558ee
Update WEBRTC_TAG constant to new version
cloudwebrtc Aug 3, 2026
bf52ad6
fix tests.
cloudwebrtc Aug 3, 2026
9413ea5
fix e2e tests for linux.
cloudwebrtc Aug 4, 2026
5ec3038
update.
cloudwebrtc Aug 4, 2026
774a9bc
Update Ubuntu version in WebRTC builds workflow
cloudwebrtc Aug 4, 2026
2ce8677
fix.
cloudwebrtc Aug 4, 2026
fc7c1c3
Update webrtc-builds.yml
cloudwebrtc Aug 4, 2026
f1eb9e2
fix
cloudwebrtc Aug 4, 2026
504e46b
add upgrade_sysroot_libdtcxx.sh for linux build.
cloudwebrtc Aug 4, 2026
309c4b3
fix.
cloudwebrtc Aug 4, 2026
6e3c62e
Update Linux dependency installation conditions
cloudwebrtc Aug 5, 2026
09062d7
Clean up build_linux.sh by removing unused patches
cloudwebrtc Aug 5, 2026
6a894c2
update.
cloudwebrtc Aug 5, 2026
b494632
Update Linux dependencies for arm64 architecture
cloudwebrtc Aug 5, 2026
50da6c6
Update webrtc-builds.yml
cloudwebrtc Aug 5, 2026
0c3c326
update.
cloudwebrtc Aug 6, 2026
2bb70b5
fix abseil cpp build error.
cloudwebrtc Aug 6, 2026
c08c998
fix patch.
cloudwebrtc Aug 6, 2026
60a261d
fix.
cloudwebrtc Aug 6, 2026
7454992
revert changes.
cloudwebrtc Aug 6, 2026
9500e32
fix.
cloudwebrtc Aug 6, 2026
6643976
Update webrtc-builds.yml
cloudwebrtc Aug 6, 2026
c410744
Update WEBRTC_TAG constant to new version
cloudwebrtc Aug 6, 2026
cbec2b8
fix jni_prefix.patch.
cloudwebrtc Aug 7, 2026
2da3891
Require clang 21+ for the m150 hermetic libc++
cloudwebrtc Aug 10, 2026
0b5d9be
Add additional link arguments for aarch64 target
cloudwebrtc Aug 10, 2026
b75ae7e
Update config.toml
cloudwebrtc Aug 10, 2026
d40f016
Keep m150's libwebrtc logs inside the Rust log facade
cloudwebrtc Aug 10, 2026
9a57219
fix ffi build.
cloudwebrtc Aug 10, 2026
988c5e5
fix.
cloudwebrtc Aug 10, 2026
db162a7
fix.
cloudwebrtc Aug 10, 2026
6691a78
update clang for node-builds.yml.
cloudwebrtc Aug 10, 2026
f6083e6
fix.
cloudwebrtc Aug 10, 2026
4e9896c
revert changes.
cloudwebrtc Aug 10, 2026
b7e9c5a
update.
cloudwebrtc Aug 10, 2026
75555bc
update.
cloudwebrtc Aug 10, 2026
29ba605
revert changes.
cloudwebrtc Aug 10, 2026
3e01861
fix CI build issue for linux arm64.
cloudwebrtc Aug 10, 2026
9f0c332
Update lib.rs
cloudwebrtc Aug 10, 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
8 changes: 8 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@ rustflags = ["-C", "target-feature=+crt-static"]
[target.aarch64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]

# `-ObjC` must also be passed to rustdoc: doctest binaries are linked by rustdoc
# and do not inherit `rustflags`. Without it the ObjC categories in libwebrtc's
# static lib (e.g. `NSString (StdString)`) are not loaded, and static
# initializers such as RTCH264ProfileLevelId.mm abort at process startup.
[target.x86_64-apple-darwin]
rustflags = ["-C", "link-args=-ObjC"]
rustdocflags = ["-C", "link-args=-ObjC"]

[target.aarch64-apple-darwin]
rustflags = ["-C", "link-args=-ObjC"]
rustdocflags = ["-C", "link-args=-ObjC"]

[target.aarch64-apple-ios]
rustflags = ["-C", "link-args=-ObjC"]
rustdocflags = ["-C", "link-args=-ObjC"]

[target.aarch64-apple-ios-sim]
rustflags = ["-C", "link-args=-ObjC"]
rustdocflags = ["-C", "link-args=-ObjC"]
9 changes: 9 additions & 0 deletions .changeset/feat_upgrade_libwebrtc_to_m150.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
libwebrtc: patch
livekit: patch
livekit-ffi: patch
webrtc-sys: patch
webrtc-sys-build: patch
---

feat: upgrade libwebrtc to m150. - #1284 (@cloudwebrtc)
61 changes: 61 additions & 0 deletions .github/scripts/install-clang.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
#
# Install a clang new enough to build webrtc-sys on Linux.
#
# webrtc-sys compiles against the hermetic libc++ shipped inside the libwebrtc
# artifact (use_custom_libcxx=true). That libc++ tracks LLVM trunk and uses
# builtins that only exist in a recent clang, so the distro clang in our build
# images (AlmaLinux 8: clang 17, Ubuntu 24: clang 18) fails deep inside <limits>
# and <span> instead of saying the compiler is too old. webrtc-sys/build.rs
# checks the version up front and reports the real floor, which it reads from
# the artifact's own __configuration/compiler.h.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to provide information on the clang requirement in our webrtc repo's readme ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clang 21 is only required for compilation on Ubuntu 24 or earlier Linux distributions, so I updated README.md.
https://github.com/livekit/rust-sdks/pull/1284/changes#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R185

#
# The distro package managers have nothing recent enough, so pull the official
# LLVM release tarball instead. If a build image ever rejects it for glibc
# reasons, LLVM_VERSION is the knob to turn.
#
# Prints the bin directory on stdout; everything else goes to stderr. Also
# exports CC/CXX via $GITHUB_ENV when running as a workflow step.
#
# Usage:
# runner: .github/scripts/install-clang.sh # sets CC/CXX for later steps
# docker: export LLVM_ROOT=/opt/llvm
# .github/scripts/install-clang.sh
# export CC=$LLVM_ROOT/bin/clang CXX=$LLVM_ROOT/bin/clang++

set -euo pipefail

LLVM_VERSION="${LLVM_VERSION:-21.1.8}"
LLVM_ROOT="${LLVM_ROOT:-/opt/llvm-$LLVM_VERSION}"

case "$(uname -m)" in
x86_64) llvm_arch=X64 ;;
aarch64 | arm64) llvm_arch=ARM64 ;;
*) echo "install-clang.sh: unsupported architecture $(uname -m)" >&2; exit 1 ;;
esac

if [ "$(id -u)" -eq 0 ]; then
sudo=""
else
sudo="sudo"
fi

if [ ! -x "$LLVM_ROOT/bin/clang++" ]; then
url="https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVM_VERSION/LLVM-$LLVM_VERSION-Linux-$llvm_arch.tar.xz"
echo "install-clang.sh: fetching $url" >&2
$sudo mkdir -p "$LLVM_ROOT"
# --strip-components=1 drops the LLVM-<version>-Linux-<arch>/ prefix.
curl --fail --location --silent --show-error "$url" \
| $sudo tar -xJ --strip-components=1 -C "$LLVM_ROOT"
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
fi
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.

"$LLVM_ROOT/bin/clang++" --version >&2

if [ -n "${GITHUB_ENV:-}" ]; then
{
echo "CC=$LLVM_ROOT/bin/clang"
echo "CXX=$LLVM_ROOT/bin/clang++"
} >> "$GITHUB_ENV"
fi

echo "$LLVM_ROOT/bin"
7 changes: 7 additions & 0 deletions .github/workflows/builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ jobs:
run: |
sudo apt install -y libva-dev libdrm-dev libnvidia-compute-570 libnvidia-decode-570 nvidia-cuda-dev -y

# Ubuntu 24 ships clang 18; webrtc-sys needs 21+ for libwebrtc's hermetic
# libc++. Sets CC/CXX for the steps below. Android targets are excluded:
# cargo-ndk supplies its own NDK clang.
- name: Install clang for webrtc-sys
if: ${{ contains(matrix.target, 'unknown-linux-gnu') }}
run: .github/scripts/install-clang.sh

- name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1.16.1
with:
Expand Down
9 changes: 6 additions & 3 deletions .github/workflows/ffi-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,15 @@ jobs:
docker run --rm -e CARGO_RUST_PROFILE="$CARGO_RUST_PROFILE" -v $PWD:/workspace -w /workspace ${{ matrix.build_image }} bash -c "\
uname -a; \
export PATH=/root/.cargo/bin:\$PATH; \
yum install llvm llvm-libs lld -y; \
yum install clang -y; \
yum install clang clang-devel lld -y; \
yum install protobuf-compiler -y; \
yum groupinstall 'Development Tools' -y; \
clang --version; \
yum install openssl-devel libX11-devel mesa-libGL-devel libXext-devel libva-devel libdrm-devel libgbm-devel libXdamage-devel libXrandr-devel libXfixes-devel libXcomposite-devel -y; \
clang --version; \
clang++ --version; \
export LIBCLANG_PATH=/usr/lib64; \
export CC=clang; \
export CXX=clang++; \
Comment on lines +219 to +227

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Linux release binaries can no longer be built because the build container installs an outdated compiler

The Linux packaging container still installs and uses the distribution's own compiler (yum install clang / export CXX=clang++ at .github/workflows/ffi-builds.yml:218-226), which is far older than the minimum the build now insists on, so the Linux release artifacts stop being produced.
Impact: The published Linux x86_64 and arm64 FFI downloads fail to build, blocking releases for those platforms.

Compiler floor enforced by webrtc-sys/build.rs vs. the manylinux images

webrtc-sys/build.rs now calls configure_hermetic_libcxx() for every linux target, which in turn runs check_clang_version() (webrtc-sys/build.rs:574-605). That function reads the floor out of the artifact's __configuration/compiler.h (defaulting to 21) and panic!s when the active compiler reports a lower __clang_major__.

The FFI Linux job builds inside sameli/manylinux_2_28_x86_64_cuda_12.3 / quay.io/pypa/manylinux_2_28_aarch64 (AlmaLinux 8), whose clang package is version 17/18 — below the floor. builds.yml and tests.yml were updated to run .github/scripts/install-clang.sh (which even documents a docker: usage mode with LLVM_ROOT), but the FFI workflow was not, so the transformation is incomplete.

Prompt for agents
The Linux FFI build in .github/workflows/ffi-builds.yml runs inside manylinux_2_28 images and relies on the distro clang (17/18) via `yum install clang` plus `export CC=clang CXX=clang++`. webrtc-sys/build.rs now enforces a minimum clang major version (read from the libwebrtc artifact's hermetic libc++ `__configuration/compiler.h`, fallback 21) and panics otherwise, so this job will fail. The new .github/scripts/install-clang.sh already documents a docker usage mode (`export LLVM_ROOT=/opt/llvm; .github/scripts/install-clang.sh; export CC=$LLVM_ROOT/bin/clang CXX=$LLVM_ROOT/bin/clang++`). Update the docker command in the Linux build step to install and use that newer clang instead of the distro one (keeping LIBCLANG_PATH working for bindgen), for both the x86_64 and aarch64 matrix entries.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

curl --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y; \
cd livekit-ffi && cargo build --profile \"\$CARGO_RUST_PROFILE\" --target ${{ matrix.target }} ${{ matrix.buildargs }}"

Expand Down
15 changes: 13 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ jobs:
version: "25.2"
repo-token: ${{ secrets.GITHUB_TOKEN }}

# Ubuntu 24 ships clang 18; webrtc-sys needs 21+ for libwebrtc's hermetic
# libc++. Must run before the sccache step, which wraps whatever CC/CXX
# this sets. (The previous default here was the host `cc`/`c++`, i.e. GCC,
# which webrtc-sys/build.rs now rejects outright: GCC silently ignores
# libc++'s trivial_abi annotations and miscompiles unique_ptr returns.)
- name: Install clang for webrtc-sys
if: ${{ runner.os == 'Linux' }}
run: .github/scripts/install-clang.sh

# sccache wraps both rustc and the C/C++ compilers used by `cxx_build`
# in `webrtc-sys`. The Mozilla action installs the binary; the probe
# step below only enables wrapping if the GHA cache backend is reachable
Expand All @@ -94,9 +103,11 @@ jobs:
# All three matrix targets in tests.yml are host targets (no
# cross-compile), so wrapping CC/CXX is safe. Skip on Windows:
# MSVC `cl` setup needs more care.
# On Linux CC/CXX already point at the clang installed above; keep
# that compiler and just prepend the wrapper.
if [ "${{ runner.os }}" != "Windows" ]; then
echo "CC=sccache cc" >> "$GITHUB_ENV"
echo "CXX=sccache c++" >> "$GITHUB_ENV"
echo "CC=sccache ${CC:-cc}" >> "$GITHUB_ENV"
echo "CXX=sccache ${CXX:-c++}" >> "$GITHUB_ENV"
fi
echo "::notice::sccache enabled (RUSTC_WRAPPER=sccache)"
else
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,17 @@ Building on Ubuntu 24 x86_64:
```
# install required libs
sudo apt install -y \
libglib2.0-dev build-essential clang \
libglib2.0-dev build-essential \
libclang-dev libc6-dev pkg-config libjpeg-turbo8-dev

# webrtc-sys compiles against the hermetic libc++ shipped inside the libwebrtc
# artifact, which tracks LLVM trunk and needs clang 21 or later. Ubuntu 24's
# clang is 18, so install a newer one from apt.llvm.org:
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 21
export CC=clang-21 CXX=clang++-21

# install cuda-toolkit if you have an Nvidia GPU and want to use NVENC for video encoding
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
Expand Down
136 changes: 135 additions & 1 deletion webrtc-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ fn main() {
println!("cargo:rustc-link-lib=dylib=pthread");
println!("cargo:rustc-link-lib=dylib=m");

configure_hermetic_libcxx(&mut builder, &webrtc_include);

// In order to avoid any ABI mismatches we use the sysroot's headers.
add_gio_headers(&mut builder);

Expand Down Expand Up @@ -374,7 +376,12 @@ fn main() {
println!("cargo:rustc-link-lib=c++abi");

configure_android_sysroot(&mut builder);
builder.file("src/android.cpp").flag("-std=c++20");
builder
.file("src/android.cpp")
// Provides a weak stub for std::__ndk1::__hash_memory, which
// was removed from libc++_static.a exports in NDK r28.
.file("src/ndk_compat.cpp")
.flag("-std=c++20");
}
_ => {
panic!("Unsupported target, {}", target_os);
Expand Down Expand Up @@ -491,6 +498,133 @@ fn add_lazy_load_so(builder: &mut cc::Build, name: &str, libraries: Vec<String>)
}
}

/// Compile against the same hermetic libc++ that is baked into libwebrtc.a.
///
/// The Linux libwebrtc build sets `use_custom_libcxx=true`, so every std type in
/// its public API lives in the `std::__Cr` ABI namespace with libc++ layouts.
/// Using the host's libstdc++ here instead is not merely a mangling mismatch that
/// the linker would catch: `std::span` is layout-different between the two, so a
/// span handed to libwebrtc silently arrives with its pointer and size swapped.
///
/// Mirrors the flags in the WebRTC checkout's `build/config/c++/BUILD.gn`. The
/// matching `_LIBCPP_*` defines come from webrtc.ninja via `webrtc_defines()`.
fn configure_hermetic_libcxx(builder: &mut cc::Build, webrtc_include: &path::Path) {
let libcxx = webrtc_include.join("third_party/libc++/src/include");
let libcxxabi = webrtc_include.join("third_party/libc++abi/src/include");
if !libcxx.join("span").exists() {
panic!(
"hermetic libc++ headers missing from {}.\n\
This libwebrtc artifact predates use_custom_libcxx=true; rebuild it with \
build_linux.sh or point LK_CUSTOM_WEBRTC at a newer one.",
libcxx.display()
);
}

// Chromium's libc++ is clang-only. At _LIBCPP_ABI_VERSION 2 it marks unique_ptr
// and shared_ptr __attribute__((trivial_abi)), which GCC accepts and silently
// ignores (a -Wattributes warning that cc's `-w` swallows). That attribute
// changes the calling convention, not just layout: libwebrtc.a returns
// std::unique_ptr in a register, while a GCC caller reads it back from an sret
// slot the callee never wrote, yielding a garbage pointer at the first use.
if env::var_os("CXX").is_none() {
if Command::new("clang++").arg("--version").output().is_err() {
panic!(
"clang++ is required to build webrtc-sys on Linux: libwebrtc.a is built \
against Chromium's hermetic libc++, whose trivial_abi annotations GCC \
ignores, which silently breaks the calling convention for std::unique_ptr \
and std::shared_ptr. Install clang, or set CXX to a clang.",
);
}
builder.compiler("clang++");
}
Comment on lines +529 to +539

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Cross-compiler settings are ignored when building for Linux, forcing the host compiler

The Linux build forces the host clang++ whenever the generic compiler environment variable is unset (builder.compiler("clang++") at webrtc-sys/build.rs:538), ignoring the target-specific compiler overrides the build system normally honors, so cross-compiled builds silently use the wrong compiler.
Impact: People cross-compiling for another Linux architecture get their configured toolchain ignored and the build fails or produces wrong output.

cc crate env-var precedence not covered by the CXX check

The cc crate resolves the C++ compiler from CXX_<target>, CXX_<target-with-underscores>, TARGET_CXX and finally CXX; an explicit Build::compiler() call takes precedence over all of them. webrtc-sys/build.rs:529-539 only checks env::var_os("CXX"), so a user who sets CXX_aarch64_unknown_linux_gnu=/path/to/clang++ (the documented per-target form) still gets the hard-coded host clang++, losing their sysroot/target configuration.

Prompt for agents
In webrtc-sys/build.rs, configure_hermetic_libcxx() decides whether to force clang++ by checking only env::var_os("CXX"). The cc crate also honors CXX_<target>, CXX_<target with underscores> and TARGET_CXX, and an explicit Build::compiler() call overrides all of them. Widen the check so that any of the compiler override variables the cc crate consults (including the target-specific ones derived from the TARGET env var) suppresses the hard-coded clang++, otherwise cross-compilation setups silently get the host compiler.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


check_clang_version(builder, &libcxx);

builder
.flag("-nostdinc++")
.flag(format!("-isystem{}", libcxx.display()))
.flag(format!("-isystem{}", libcxxabi.display()))
// Holds __config_site, which pins _LIBCPP_ABI_NAMESPACE=__Cr.
.include(webrtc_include.join("buildtools/third_party/libc++"));

// libc++/libc++abi are already archived into libwebrtc.a, so linking the
// host libstdc++ on top would only add a second, incompatible stdlib.
builder.cpp_link_stdlib(None);

// The cxx crate builds its own runtime (cxx.cc) with the host default stdlib,
// so the rust::String <-> std::string conversions it exports are mangled for
// libstdc++ and cannot satisfy the std::__Cr call sites in the generated
// bridges. Compile a second copy with the flags above to provide those.
// DEP_CXXBRIDGE1_HEADER is `cargo:HEADER` from the cxx crate: <root>/include/cxx.h.
let cxx_h = env::var("DEP_CXXBRIDGE1_HEADER")
.expect("cxx crate did not export HEADER; cannot locate its cxx.cc");
let cxx_root = path::Path::new(&cxx_h)
.parent()
.and_then(path::Path::parent)
.expect("unexpected DEP_CXXBRIDGE1_HEADER layout");
builder.file(cxx_root.join("src/cxx.cc"));
}

/// The hermetic libc++ tracks LLVM trunk, so it freely uses builtins that only
/// exist in a recent clang (`__builtin_popcountg`, `__is_nothrow_convertible`,
/// `__GCC_DESTRUCTIVE_SIZE`, ...). A compiler below its floor does not fail with
/// "your clang is too old" — it fails deep inside <limits> and <span> with
/// hundreds of lines about `dynamic_extent` not being a constant expression, in
/// headers the user never wrote. Catch it up front instead.
fn check_clang_version(builder: &cc::Build, libcxx: &path::Path) {
let min = libcxx_min_clang_major(libcxx);

let compiler = builder.get_compiler();
let defines = compiler
.to_command()
.args(["-dM", "-E", "-x", "c++", "/dev/null"])
.output()
.unwrap_or_else(|e| panic!("failed to run {}: {e}", compiler.path().display()));

let major = String::from_utf8_lossy(&defines.stdout).lines().find_map(|line| {
line.strip_prefix("#define __clang_major__ ").and_then(|v| v.trim().parse::<u32>().ok())
});

match major {
Some(major) if major >= min => {}
Some(major) => panic!(
"{} is clang {major}, but the hermetic libc++ shipped with this libwebrtc \
requires clang {min} or later. Install a newer clang and point CC/CXX at it, \
or use the exact toolchain libwebrtc was built with (see CR_CLANG_REVISION in \
the artifact's webrtc.ninja).",
compiler.path().display(),
),
None => panic!(
"{} does not define __clang_major__, so it is not a clang. libwebrtc.a is built \
against Chromium's hermetic libc++, which requires clang {min} or later; GCC \
additionally ignores its trivial_abi annotations, silently breaking the calling \
convention for std::unique_ptr and std::shared_ptr.",
compiler.path().display(),
),
}
}

/// libc++ states its own floor in `__configuration/compiler.h`, as
/// `#if _LIBCPP_CLANG_VER < 2101` (major * 100 + minor). Read it from the
/// artifact rather than hardcoding, so a libwebrtc bump moves the floor with it.
fn libcxx_min_clang_major(libcxx: &path::Path) -> u32 {
const FALLBACK: u32 = 21;

let header = libcxx.join("__configuration/compiler.h");
let Ok(source) = std::fs::read_to_string(&header) else {
return FALLBACK;
};

source
.lines()
.find_map(|line| {
let (_, rest) = line.split_once("_LIBCPP_CLANG_VER < ")?;
let ver: u32 = rest.trim().parse().ok()?;
Some(ver / 100)
})
.unwrap_or(FALLBACK)
Comment on lines +618 to +625

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Compiler version check accepts a compiler one point release too old

The required compiler version is rounded down to whole numbers when it is read from the bundled library (Some(ver / 100) at webrtc-sys/build.rs:623), so a compiler that is slightly older than required passes the check.
Impact: Users with a marginally old compiler get hundreds of confusing errors from system headers instead of the clear "your compiler is too old" message.

Minor version is discarded from _LIBCPP_CLANG_VER

_LIBCPP_CLANG_VER is __clang_major__ * 100 + __clang_minor__ (as the doc comment at webrtc-sys/build.rs:607-609 states). The artifact's __configuration/compiler.h currently says #if _LIBCPP_CLANG_VER < 2101, i.e. clang 21.1 is the true floor, but ver / 100 yields 21 and check_clang_version only compares major >= min (webrtc-sys/build.rs:588-589). clang 21.0.x therefore passes the guard and then fails deep inside <limits>/<span> — exactly the failure mode this guard was written to prevent.

Prompt for agents
libcxx_min_clang_major() in webrtc-sys/build.rs parses `_LIBCPP_CLANG_VER < 2101` and returns 2101/100 = 21, dropping the minor version, while check_clang_version() only compares __clang_major__. A clang 21.0 passes even though libc++ requires 21.1. Consider keeping the encoded major*100+minor value end-to-end: read __clang_major__ and __clang_minor__ from the compiler's preprocessor defines, compute the same major*100+minor encoding, and compare against the value parsed from __configuration/compiler.h, formatting the floor as major.minor in the panic message.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

}

fn add_gio_headers(builder: &mut cc::Build) {
let webrtc_dir = webrtc_sys_build::webrtc_dir();
let target_arch = webrtc_sys_build::target_arch();
Expand Down
2 changes: 1 addition & 1 deletion webrtc-sys/build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use regex::Regex;
use reqwest::StatusCode;

pub const SCRATH_PATH: &str = "livekit_webrtc";
pub const WEBRTC_TAG: &str = "webrtc-51ef663";
pub const WEBRTC_TAG: &str = "webrtc-f8a0b64-1";
pub const IGNORE_DEFINES: [&str; 2] = ["CR_CLANG_REVISION", "CR_XCODE_VERSION"];

pub fn target_os() -> String {
Expand Down
7 changes: 4 additions & 3 deletions webrtc-sys/include/livekit/packet_trailer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <deque>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include <unordered_map>
#include <vector>
Expand Down Expand Up @@ -102,7 +103,7 @@ struct PacketTrailerMetadata {
///
/// Shared by the codec-agnostic trailer path and the AV1 OBU path.
std::optional<PacketTrailerMetadata> ParseTrailerPayload(
webrtc::ArrayView<const uint8_t> trailer);
std::span<const uint8_t> trailer);

/// Frame transformer that appends/extracts packet trailers.
/// This transformer can be used standalone or in conjunction with e2ee.
Expand Down Expand Up @@ -193,15 +194,15 @@ class PacketTrailerTransformer : public webrtc::FrameTransformerInterface {

/// Append frame metadata trailer to frame data
std::vector<uint8_t> AppendTrailer(
webrtc::ArrayView<const uint8_t> data,
std::span<const uint8_t> data,
uint64_t user_timestamp,
uint32_t frame_id,
const std::vector<uint8_t>& user_data,
bool is_av1);

/// Extract and remove frame metadata trailer from frame data
std::optional<PacketTrailerMetadata> ExtractTrailer(
webrtc::ArrayView<const uint8_t> data,
std::span<const uint8_t> data,
std::vector<uint8_t>& out_data,
bool is_av1);

Expand Down
Loading
Loading