Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 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
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)
74 changes: 73 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,71 @@ 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.


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"));
}

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";
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
8 changes: 4 additions & 4 deletions webrtc-sys/include/livekit/packet_trailer_av1.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

#include <cstdint>
#include <optional>
#include <span>
#include <vector>

#include "api/array_view.h"
#include "api/frame_transformer_interface.h"
#include "livekit/packet_trailer.h"

Expand All @@ -36,8 +36,8 @@ bool IsAv1Frame(const webrtc::TransformableFrameInterface& frame);
/// [`PacketTrailerTransformer`]). The OBU is placed after any temporal
/// delimiter and sequence header OBUs so it is not mistaken for frame data.
std::vector<uint8_t> InsertTrailerObu(
webrtc::ArrayView<const uint8_t> data,
webrtc::ArrayView<const uint8_t> trailer);
std::span<const uint8_t> data,
std::span<const uint8_t> trailer);

/// Extracts and removes a LiveKit packet-trailer metadata OBU from an AV1
/// temporal unit.
Expand All @@ -46,7 +46,7 @@ std::vector<uint8_t> InsertTrailerObu(
/// frame data with the metadata OBU removed. Otherwise `out_data` receives
/// an unchanged copy of `data` and `std::nullopt` is returned.
std::optional<PacketTrailerMetadata> ExtractTrailer(
webrtc::ArrayView<const uint8_t> data,
std::span<const uint8_t> data,
std::vector<uint8_t>& out_data);

} // namespace av1
Expand Down
Loading
Loading