Skip to content

Commit 6e83d0e

Browse files
committed
webrtc-sys: build libwebrtc from source on Linux
1 parent 4c69fbf commit 6e83d0e

File tree

3 files changed

+223
-52
lines changed

3 files changed

+223
-52
lines changed

webrtc-sys/build.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,54 @@ fn main() {
7979
"src/apm.cpp",
8080
]);
8181

82-
let webrtc_dir = webrtc_sys_build::webrtc_dir();
82+
let mut webrtc_dir = webrtc_sys_build::webrtc_dir();
83+
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
84+
85+
#[cfg(target_os = "linux")]
86+
println!("cargo:rerun-if-env-changed=LK_LIBWEBRTC_SOURCE");
87+
#[cfg(target_os = "linux")]
88+
if let Ok(source_archive) = env::var("LK_LIBWEBRTC_SOURCE") {
89+
let out_dir = env::var("OUT_DIR").unwrap();
90+
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
91+
92+
fn check_command_output(output: std::process::Output) {
93+
let status = output.status;
94+
if !status.success() {
95+
let stderr = String::from_utf8_lossy(&output.stderr);
96+
let stdout = String::from_utf8_lossy(&output.stdout);
97+
panic!("Command exited unsuccessfully: {status:?},\nstdout:\n{stdout}\nstderr:\n{stderr}");
98+
}
99+
}
100+
101+
check_command_output(
102+
Command::new("tar").args(["-Jxf", &source_archive, "-C", &out_dir]).output().unwrap(),
103+
);
104+
105+
let script_arch = match target_arch.as_str() {
106+
"x86_64" => "x64",
107+
"aarch64" => "arm64",
108+
a => a,
109+
};
110+
check_command_output(
111+
Command::new("bash")
112+
.args([
113+
&format!("{manifest_dir}/libwebrtc/build_linux.sh"),
114+
"--sources",
115+
&format!("{out_dir}/src"),
116+
"--toolchain",
117+
"gnu",
118+
"--arch",
119+
script_arch,
120+
"--profile",
121+
"release",
122+
])
123+
.output()
124+
.unwrap(),
125+
);
126+
127+
webrtc_dir = PathBuf::from(format!("{out_dir}/linux-{script_arch}-release"));
128+
}
129+
83130
let webrtc_include = webrtc_dir.join("include");
84131
let webrtc_lib = webrtc_dir.join("lib");
85132

@@ -110,7 +157,6 @@ fn main() {
110157
println!("cargo:rustc-link-lib=static=webrtc");
111158

112159
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
113-
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
114160
match target_os.as_str() {
115161
"windows" => {
116162
println!("cargo:rustc-link-lib=dylib=msdmo");

webrtc-sys/libwebrtc/build_linux.sh

Lines changed: 31 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ toolchain="gnu"
2020

2121
while [ "$#" -gt 0 ]; do
2222
case "$1" in
23+
--sources)
24+
sources="$(realpath $2)"
25+
shift 2
26+
;;
2327
--arch)
2428
arch="$2"
25-
if [ "$arch" != "x64" ] && [ "$arch" != "arm64" ]; then
26-
echo "Error: Invalid value for --arch. Must be 'x64' or 'arm64'."
27-
exit 1
28-
fi
2929
shift 2
3030
;;
3131
--profile)
@@ -56,14 +56,20 @@ if [ -z "$arch" ]; then
5656
exit 1
5757
fi
5858

59+
if [ -z "$sources" ]; then
60+
echo "Error: --sources must be set."
61+
exit 1
62+
fi
63+
5964
echo "Building LiveKit WebRTC - Linux"
6065
echo "Arch: $arch"
6166
echo "Profile: $profile"
6267
echo "Toolchain: $toolchain"
6368

64-
export COMMAND_DIR=$(cd $(dirname $0); pwd)
65-
export OUTPUT_DIR="$(pwd)/build-$arch-$profile"
66-
export ARTIFACTS_DIR="$(pwd)/linux-$arch-$profile"
69+
COMMAND_DIR=$(cd $(dirname $0); pwd)
70+
OUTPUT_DIR="$(dirname "$sources")"
71+
BUILD_DIR="$OUTPUT_DIR/build-$arch-$profile"
72+
ARTIFACTS_DIR="$OUTPUT_DIR/linux-$arch-$profile"
6773

6874
if [ "$toolchain" == "gnu" ]; then
6975
[ -n "$CC" ] || export CC="$(which gcc)"
@@ -93,45 +99,14 @@ elif [ "$toolchain" == "llvm" ]; then
9399
custom_toolchain=\"//build/toolchain/linux/unbundle:default\" \
94100
host_toolchain=\"//build/toolchain/linux/unbundle:default\""
95101
elif [ "$toolchain" == "chromium-llvm" ]; then
96-
AR="$COMMAND_DIR/src/third_party/llvm-build/Release+Asserts/bin/llvm-ar"
97-
OBJCOPY="$COMMAND_DIR/src/third_party/llvm-build/Release+Asserts/bin/llvm-objcopy"
102+
AR="$sources/third_party/llvm-build/Release+Asserts/bin/llvm-ar"
103+
OBJCOPY="$sources/third_party/llvm-build/Release+Asserts/bin/llvm-objcopy"
98104
chromium_libcxx=true
99105
toolchain_gn_args="is_clang=true \
100106
use_custom_libcxx=true \
101107
use_sysroot=true"
102108
fi
103109

104-
set -x
105-
106-
if [ ! -e "$(pwd)/depot_tools" ]
107-
then
108-
git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
109-
fi
110-
111-
# must be done after runing `which` to find toolchain's executables above
112-
export PATH="$(pwd)/depot_tools:$PATH"
113-
114-
if [ ! -e "$(pwd)/src" ]; then
115-
# use --nohooks to avoid the download_from_google_storage hook that takes > 6 minutes
116-
# then manually run the other hooks
117-
gclient sync -D --no-history --nohooks
118-
python3 src/tools/rust/update_rust.py
119-
if [ "$toolchain" == "chromium-llvm" ] || [ "$toolchain" == "llvm" ]; then
120-
python3 src/tools/clang/scripts/update.py
121-
fi
122-
if [ "$toolchain" == "chromium-llvm" ]; then
123-
python3 src/build/linux/sysroot_scripts/install-sysroot.py --arch=x64
124-
python3 src/build/linux/sysroot_scripts/install-sysroot.py --arch=arm64
125-
fi
126-
fi
127-
128-
cd src
129-
git apply "$COMMAND_DIR/patches/add_licenses.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn
130-
git apply "$COMMAND_DIR/patches/ssl_verify_callback_with_native_handle.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn
131-
git apply "$COMMAND_DIR/patches/add_deps.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn
132-
git apply "$COMMAND_DIR/patches/david_disable_gun_source_macro.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn
133-
cd ..
134-
135110
debug="false"
136111
if [ "$profile" = "debug" ]; then
137112
debug="true"
@@ -163,29 +138,35 @@ args="is_debug=$debug \
163138
rtc_use_x11=false \
164139
$toolchain_gn_args"
165140

166-
set -e
141+
set -xe
142+
143+
if [ "$toolchain" == "chromium-llvm" ]; then
144+
python3 "$sources/build/linux/sysroot_scripts/install-sysroot.py" --arch=x64
145+
python3 "$sources/build/linux/sysroot_scripts/install-sysroot.py" --arch=arm64
146+
fi
167147

168148
# generate ninja files
169-
gn gen "$OUTPUT_DIR" --root="src" --args="${args}"
149+
export PATH="$sources/depot_tools:$PATH"
150+
gn gen "$BUILD_DIR" --root="$sources" --args="${args}"
170151

171152
# build static library
172-
ninja -C "$OUTPUT_DIR" :default
153+
ninja -C "$BUILD_DIR" :default
173154

174155
mkdir -p "$ARTIFACTS_DIR/lib"
175156

176157
# make libwebrtc.a
177158
# don't include nasm
178-
"$AR" -rc "$ARTIFACTS_DIR/lib/libwebrtc.a" `find "$OUTPUT_DIR/obj" -name '*.o' -not -path "*/third_party/nasm/*"`
159+
"$AR" -rc "$ARTIFACTS_DIR/lib/libwebrtc.a" `find "$BUILD_DIR/obj" -name '*.o' -not -path "*/third_party/nasm/*"`
179160
"$OBJCOPY" --redefine-syms="$COMMAND_DIR/boringssl_prefix_symbols.txt" "$ARTIFACTS_DIR/lib/libwebrtc.a"
180161

181-
python3 "./src/tools_webrtc/libs/generate_licenses.py" \
182-
--target :default "$OUTPUT_DIR" "$OUTPUT_DIR"
162+
python3 "$sources/tools_webrtc/libs/generate_licenses.py" \
163+
--target :default "$BUILD_DIR" "$BUILD_DIR"
183164

184-
cp "$OUTPUT_DIR/obj/webrtc.ninja" "$ARTIFACTS_DIR"
185-
cp "$OUTPUT_DIR/args.gn" "$ARTIFACTS_DIR"
186-
cp "$OUTPUT_DIR/LICENSE.md" "$ARTIFACTS_DIR"
165+
cp "$BUILD_DIR/obj/webrtc.ninja" "$ARTIFACTS_DIR"
166+
cp "$BUILD_DIR/args.gn" "$ARTIFACTS_DIR"
167+
cp "$BUILD_DIR/LICENSE.md" "$ARTIFACTS_DIR"
187168

188-
cd src
169+
cd $sources
189170
if [ $chromium_libcxx == "true" ]; then
190171
mkdir -p "$ARTIFACTS_DIR/include/buildtools/third_party"
191172
cp -R buildtools/third_party/libc++ "$ARTIFACTS_DIR/include/buildtools/third_party"
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#!/bin/bash
2+
3+
COMMAND_DIR="$(cd $(dirname $0); pwd)"
4+
SOURCE_DIR="$COMMAND_DIR/src"
5+
ARCHIVE_PATH="$COMMAND_DIR/libwebrtc-source.tar.xz"
6+
7+
set -x
8+
9+
# for debugging this script
10+
reset() {
11+
rm -rf "$SOURCE_DIR" "$COMMAND_DIR/depot_tools" "$ARCHIVE_PATH"
12+
}
13+
14+
download() {
15+
cd "$COMMAND_DIR"
16+
git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
17+
# use --nohooks to avoid the download_from_google_storage hook that takes > 6 minutes
18+
# then manually run the other hooks
19+
export PATH="$COMMAND_DIR/depot_tools:$PATH"
20+
gclient sync -D --no-history --nohooks
21+
python3 "$SOURCE_DIR/tools/rust/update_rust.py"
22+
python3 "$SOURCE_DIR/tools/clang/scripts/update.py"
23+
mv depot_tools src
24+
}
25+
26+
patch() {
27+
cd $SOURCE_DIR
28+
git apply "$COMMAND_DIR/patches/add_licenses.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn
29+
git apply "$COMMAND_DIR/patches/ssl_verify_callback_with_native_handle.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn
30+
git apply "$COMMAND_DIR/patches/add_deps.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn
31+
cd third_party
32+
git apply "$COMMAND_DIR/patches/david_disable_gun_source_macro.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn
33+
}
34+
35+
clean() {
36+
required_files_and_dirs=(
37+
abseil-cpp
38+
boringssl
39+
catapult
40+
closure_compiler
41+
dav1d
42+
ffmpeg
43+
freetype
44+
googletest
45+
harfbuzz-ng
46+
icu
47+
jsoncpp
48+
libaom
49+
libjpeg_turbo
50+
libjpeg.gni
51+
BUILD.gn
52+
libpng
53+
libsrtp
54+
libvpx
55+
libyuv
56+
nasm
57+
openh264
58+
opus
59+
perfetto
60+
protobuf
61+
protobuf-javascript
62+
rust
63+
rust-toolchain
64+
zlib
65+
fuzztest
66+
crc32c
67+
pffft
68+
re2
69+
google_benchmark
70+
rnnoise
71+
)
72+
for filename in $(ls -1 "$SOURCE_DIR/third_party"); do
73+
if ! [[ ${required_files_and_dirs[@]} =~ $filename ]]; then
74+
rm -rf "$SOURCE_DIR/third_party/$filename"
75+
fi
76+
done
77+
78+
third_party_dirs=(
79+
rust-toolchain/bin
80+
rust-toolchain/lib
81+
catapult/tracing/test_data
82+
catapult/third_party/vinn/third_party/v8
83+
catapult/third_party/gsutil
84+
rust/chromium_crates_io
85+
boringssl/src/third_party/wycheproof_testvectors
86+
openh264/src/res
87+
ffmpeg/tests
88+
harfbuzz-ng/src/test
89+
harfbuzz-ng/src/perf
90+
perfetto/src/traced/probes/ftrace/test
91+
perfetto/src/trace_processor
92+
perfetto/docs
93+
perfetto/test
94+
perfetto/ui
95+
icu/source/data
96+
icu/source/test
97+
icu/source
98+
boringssl/src/crypto/cipher/test
99+
boringssl/src/fuzz
100+
opus/src/dnn/torch/osce/resources
101+
nasm/travis
102+
nasm/test
103+
closure_compiler/compiler
104+
)
105+
for dir in "${third_party_dirs[@]}"; do
106+
rm -rf "$SOURCE_DIR/third_party/$dir"
107+
done
108+
109+
src_dirs=(
110+
depot_tools/.cipd_bin
111+
depot_tools/.cipd_client
112+
buildtools/reclient
113+
tools/perf/testdata
114+
tools/luci-go
115+
tools/metrics
116+
tools/resultdb
117+
tools/perf/page_sets
118+
tools/perf/core/shard_maps/timing_data
119+
tools/disable_tests/tests
120+
data
121+
base/test
122+
)
123+
for dir in "${src_dirs[@]}"; do
124+
rm -rf "$SOURCE_DIR/$dir"
125+
done
126+
127+
dir_names=(testdata test_data doc docs \.git)
128+
for dir_name in "${dir_names[@]}"; do
129+
for dir in $(find "$SOURCE_DIR" -name $dir_name); do
130+
rm -rf "$dir"
131+
done
132+
done
133+
}
134+
135+
package() {
136+
tar -Jcf "$ARCHIVE_PATH" -C "$COMMAND_DIR" src
137+
}
138+
139+
reset
140+
set -e
141+
download
142+
patch
143+
clean
144+
package

0 commit comments

Comments
 (0)