Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 6 additions & 26 deletions .github/workflows/webrtc-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ jobs:

- name: linux
os: ubuntu-latest
cmd: ./build_linux.sh
cmd: ./build_linux.sh --toolchain chromium-llvm
arch: x64

- name: linux
os: ubuntu-latest
cmd: ./build_linux.sh
cmd: ./build_linux.sh --toolchain chromium-llvm
arch: arm64

- name: android
Expand Down Expand Up @@ -112,36 +112,16 @@ jobs:
run: |
pip3 install setuptools # pkg_resources is sometimes not found?

- name: Add GCC PPA and install GCC 14
if: ${{ matrix.target.os == 'ubuntu-latest' }}
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
sudo apt update
sudo apt install gcc-14 g++-14 g++-14-aarch64-linux-gnu -y

- name: Verify GCC 14 installation
if: ${{ matrix.target.os == 'ubuntu-latest' }}
run: |
gcc-14 --version
g++-14 --version
aarch64-linux-gnu-g++-14 --version

- name: Set GCC 14 as default (optional)
if: ${{ matrix.target.os == 'ubuntu-latest' }}
run: |
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 140 --slave /usr/bin/g++ g++ /usr/bin/g++-14
sudo update-alternatives --config gcc
gcc --version
sudo update-alternatives --install /usr/bin/aarch64-linux-gnu-gcc aarch64-linux-gnu-gcc /usr/bin/aarch64-linux-gnu-gcc-14 140 --slave /usr/bin/aarch64-linux-gnu-g++ aarch64-linux-gnu-g++ /usr/bin/aarch64-linux-gnu-g++-14
sudo update-alternatives --config aarch64-linux-gnu-gcc
aarch64-linux-gnu-gcc --version

- name: Install linux dependencies
if: ${{ matrix.target.os == 'ubuntu-latest' }}
run: |
sudo apt update -y
sudo apt install -y ninja-build pkg-config openjdk-11-jdk

- name: Disable __GLIBC_USE_ISOC2X macro
if: ${{ matrix.target.name == 'linux' && matrix.target.arch == 'arm64' }}
run: sudo sed -i 's/__GLIBC_USE_ISOC2X[[:space:]]*1/__GLIBC_USE_ISOC2X\t0/' /usr/include/features.h

- name: Install macos dependencies
if: ${{ matrix.target.os == 'macos-latest' }}
run: brew install ninja
Expand Down
7 changes: 5 additions & 2 deletions webrtc-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ repository = "https://github.com/livekit/client-sdk-rust"
default = []

[dependencies]
cxx = "1.0"
# Copy an updated version of the cxx.cc file from cxx's repository
# into the src directory when updating to a new version of cxx
# and change the include path for cxx.h to "rust/cxx.h"
cxx = "=1.0.186"
log = "0.4"

[build-dependencies]
webrtc-sys-build = { workspace = true }
cxx-build = "1.0"
cxx-build = "=1.0.186"
glob = "0.3"
cc = "1.0"
pkg-config = "0.3.22"
Expand Down
108 changes: 75 additions & 33 deletions webrtc-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,59 @@ fn main() {
"src/desktop_capturer.cpp",
]);

let webrtc_dir = webrtc_sys_build::webrtc_dir();
let mut webrtc_dir = webrtc_sys_build::webrtc_dir();
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();

#[cfg(target_os = "linux")]
println!("cargo:rerun-if-env-changed=LK_LIBWEBRTC_SOURCE");
#[cfg(target_os = "linux")]
if let Ok(source_archive) = env::var("LK_LIBWEBRTC_SOURCE") {
let out_dir = env::var("OUT_DIR").unwrap();
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

fn check_command_output(output: std::process::Output) {
let status = output.status;
if !status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
panic!("Command exited unsuccessfully: {status:?},\nstdout:\n{stdout}\nstderr:\n{stderr}");
}
}

if !std::fs::exists(format!("{out_dir}/src")).unwrap() {
check_command_output(
Command::new("tar")
.args(["-Jxf", &source_archive, "-C", &out_dir])
.output()
.unwrap(),
);
}

let script_arch = match target_arch.as_str() {
"x86_64" => "x64",
"aarch64" => "arm64",
a => a,
};
check_command_output(
Command::new("bash")
.args([
&format!("{manifest_dir}/libwebrtc/build_linux.sh"),
"--sources",
&format!("{out_dir}/src"),
"--toolchain",
"gnu",
"--arch",
script_arch,
"--profile",
"release",
])
.output()
.unwrap(),
);

webrtc_dir = PathBuf::from(format!("{out_dir}/linux-{script_arch}-release"));
}

let webrtc_include = webrtc_dir.join("include");
let webrtc_lib = webrtc_dir.join("lib");

Expand All @@ -103,7 +155,7 @@ fn main() {

println!("cargo:rustc-link-search=native={}", webrtc_lib.to_str().unwrap());

for (key, value) in webrtc_sys_build::webrtc_defines() {
for (key, value) in webrtc_sys_build::webrtc_defines(&webrtc_dir) {
let value = value.as_deref();
builder.define(key.as_str(), value);
}
Expand All @@ -112,7 +164,6 @@ fn main() {
println!("cargo:rustc-link-lib=static=webrtc");

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
match target_os.as_str() {
"windows" => {
println!("cargo:rustc-link-lib=dylib=msdmo");
Expand Down Expand Up @@ -150,14 +201,28 @@ fn main() {
.flag("/EHsc");
}
"linux" => {
// If libwebrtc was built with Chromium's libc++, the C++ in this crate needs to be built with it too.
let buildtools = webrtc_include.join("buildtools/third_party/libc++");
if buildtools.exists() {
// Chromium's libc++ doesn't build with GCC
if env::var("CC").is_err() {
builder.compiler("clang++");
}
builder.include(buildtools);
builder.flag("-nostdinc++");
let webrtc_include = webrtc_include.to_string_lossy();
builder.flag(format!("-isystem{webrtc_include}/third_party/libc++/src/include"));
builder.flag(format!("-isystem{webrtc_include}/third_party/libc++abi/src/include"));
// The cxx crate builds this C++ file. However, this crate needs to rebuild it when using a
// different C++ standard library or linking will fail with unresolved symbol errors.
builder.file("src/cxx.cc");
}

println!("cargo:rustc-link-lib=dylib=rt");
println!("cargo:rustc-link-lib=dylib=dl");
println!("cargo:rustc-link-lib=dylib=pthread");
println!("cargo:rustc-link-lib=dylib=m");

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

#[cfg(target_os = "linux")]
{
for lib_name in [
Expand All @@ -173,7 +238,10 @@ fn main() {
"gobject-2.0",
"gio-2.0",
] {
pkg_config::probe_library(lib_name).unwrap();
let lib = pkg_config::probe_library(lib_name).unwrap();
if lib_name == "gio-2.0" {
builder.includes(lib.include_paths);
}
}
}

Expand Down Expand Up @@ -386,29 +454,3 @@ fn configure_android_sysroot(builder: &mut cc::Build) {
let sysroot = toolchain.join("sysroot").canonicalize().unwrap();
builder.flag(format!("-isysroot{}", sysroot.display()).as_str());
}

fn add_gio_headers(builder: &mut cc::Build) {
let webrtc_dir = webrtc_sys_build::webrtc_dir();
let target_arch = webrtc_sys_build::target_arch();
let target_arch_sysroot = match target_arch.as_str() {
"arm64" => "arm64",
"x64" => "amd64",
_ => panic!("unsupported arch"),
};
let sysroot_path = format!("include/build/linux/debian_bullseye_{target_arch_sysroot}-sysroot");
let sysroot = webrtc_dir.join(sysroot_path);
let glib_path = sysroot.join("usr/include/glib-2.0");
println!("cargo:info=add_gio_headers {}", glib_path.display());

builder.include(&glib_path);
let arch_specific_path = match target_arch.as_str() {
"x64" => "x86_64-linux-gnu",
"arm64" => "aarch64-linux-gnu",
_ => panic!("unsupported target"),
};

let glib_path_config = sysroot.join("usr/lib");
let glib_path_config = glib_path_config.join(arch_specific_path);
let glib_path_config = glib_path_config.join("glib-2.0/include");
builder.include(&glib_path_config);
}
9 changes: 5 additions & 4 deletions webrtc-sys/build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::{
env,
fs::{self, File},
io::{self, BufRead, Write},
path,
path::{self, Path},
process::Command,
};

Expand Down Expand Up @@ -115,14 +115,15 @@ pub fn webrtc_dir() -> path::PathBuf {
prebuilt_dir()
}

pub fn webrtc_defines() -> Vec<(String, Option<String>)> {
pub fn webrtc_defines(path: impl AsRef<Path>) -> Vec<(String, Option<String>)> {
let path = path.as_ref();
// read preprocessor definitions from webrtc.ninja
let defines_re = Regex::new(r"-D(\w+)(?:=([^\s]+))?").unwrap();
let mut files = vec![webrtc_dir().join("webrtc.ninja")];
let mut files = vec![path.join("webrtc.ninja")];
// include desktop_capture.ninja to avoid ABI mismatch for DesktopCaptureOptions due to WEBRTC_USE_X11 missing
// libwebrtc does not implement desktop capture on Android
if env::var("CARGO_CFG_TARGET_OS").unwrap() != "android" {
files.push(webrtc_dir().join("desktop_capture.ninja"));
files.push(path.join("desktop_capture.ninja"));
}

let mut seen = HashSet::new();
Expand Down
Loading
Loading