231 lines
11 KiB
Bash
231 lines
11 KiB
Bash
#!/bin/bash
|
||
#
|
||
# Этот скрипт автоматизирует подготовку окружения и сборку WebRTC libjingle_peerconnection_so с поддержкой H.265
|
||
# и сборкой libstream-webrtc-1.3.9.aar от getstream под Android с собранными .so
|
||
# Что делает:
|
||
# 1) Ставит пакеты apt, которые нужны для сборки (git, curl, python, ninja, cmake, JDK и т.д.).
|
||
# 2) Качает набор инструментов depot_tools (fetch/gclient/gn) и добавляет его в PATH.
|
||
# 3) Загружает исходники WebRTC, переписывает .gclient так, чтобы сборка была под Android (target_os = ["android"]).
|
||
# 4) Подключает удалённый репозиторий GetStream, переходит на тег m137.0 (это версия, на которой собран их AAR 1.3.9), синхронизирует зависимости и запускает runhooks.
|
||
# 5) Создаёт вспомогательный Python‑скрипт build_multiabi_aar.py, который поочерёдно собирает AAR для каждой архитектуры и потом объединяет .so в один libstream-webrtc-1.3.9.aar.
|
||
# 6) Запускает сборку для arm64‑v8a, armeabi‑v7a, x86 и x86_64 с выключенным режимом отладки и включённым H.265.
|
||
#
|
||
# Итог: готовый libstream-webrtc-1.3.9.aar лежит в каталоге src, а промежуточные AAR‑файлы по ABI находятся в out/aar/_abi_aars и out/aar/<abi>/.
|
||
#
|
||
# Запуск: запустите этот файл на Ubuntu (понадобятся sudo‑права для apt install).
|
||
# Скрипт пропустит шаги, если каталоги или удалённый уже существуют.
|
||
#
|
||
set -e
|
||
|
||
echo "=== Шаг 1: Обновляем список пакетов и ставим зависимости ==="
|
||
sudo apt update
|
||
sudo apt install -y git curl python3 python3-venv python3-pip ninja-build \
|
||
cmake default-jdk pkg-config
|
||
|
||
echo "=== Шаг 2: Клонируем depot_tools и добавляем в PATH ==="
|
||
mkdir -p WEBRTC
|
||
cd WEBRTC
|
||
|
||
if [ ! -d depot_tools ]; then
|
||
echo "Клонируем depot_tools..."
|
||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||
else
|
||
echo "Каталог depot_tools уже существует; пропускаем клонирование."
|
||
fi
|
||
|
||
# Добавляем depot_tools в PATH только для этого скрипта. Это позволит пользоваться
|
||
# `fetch`, `gclient` и `gn`, не изменяя постоянные настройки пользователя.
|
||
export PATH="$PWD/depot_tools:$PATH"
|
||
|
||
echo "=== Шаг 3: Качаем исходники WebRTC ==="
|
||
if [ ! -d src ]; then
|
||
# `fetch` создаст каталог `src` и файл .gclient.
|
||
fetch --nohooks webrtc
|
||
else
|
||
echo "Каталог src уже есть; пропускаем fetch."
|
||
fi
|
||
|
||
echo "=== Шаг 4: Правим .gclient под Android ==="
|
||
# Перезаписываем .gclient и прописываем target_os = [ \"android\" ].
|
||
cat > .gclient <<'EOF'
|
||
solutions = [
|
||
{
|
||
"name": "src",
|
||
"url": "https://webrtc.googlesource.com/src.git",
|
||
"deps_file": "DEPS",
|
||
"managed": False,
|
||
"custom_deps": {},
|
||
},
|
||
]
|
||
target_os = [ "android" ]
|
||
EOF
|
||
|
||
echo "=== Шаг 5: Checkout тега m137.0 и синхронизация зависимостей ==="
|
||
cd src
|
||
|
||
# Добавляем удалённый репозиторий GetStream, если он ещё не добавлен.
|
||
if ! git remote | grep -q '^stream$'; then
|
||
echo "Добавляем удалённый репозиторий GetStream..."
|
||
git remote add stream https://github.com/GetStream/webrtc.git
|
||
else
|
||
echo "Удалённый GetStream уже есть; пропускаем добавление."
|
||
fi
|
||
|
||
git fetch stream --tags # стягиваем теги, чтобы появился m137.0
|
||
|
||
git checkout tags/m137.0 # переключаемся на нужный тег
|
||
|
||
echo "Запускаем gclient sync и gclient runhooks..."
|
||
gclient sync --jobs 1 -D
|
||
gclient runhooks
|
||
|
||
echo "=== Шаг 6: Создаём обёрточный build_multiabi_aar.py ==="
|
||
# Записываем вспомогательный скрипт в tools_webrtc/android/build_multiabi_aar.py. Он собирает AAR для каждой архитектуры, а потом склеивает их JNI‑библиотеки в единый libstream-webrtc-1.3.9.aar.
|
||
cat > tools_webrtc/android/build_multiabi_aar.py <<'PY'
|
||
#!/usr/bin/env python3
|
||
"""
|
||
Обёртка для сборки libwebrtc.aar сразу под несколько ABI.
|
||
|
||
Оригинальный скрипт tools_webrtc/android/build_aar.py за один запуск собирает только одну архитектуру,
|
||
а итоговый libwebrtc.aar иногда содержит только последнюю собранную архитектуру. Этот скрипт решает
|
||
проблему: он собирает AAR для каждого ABI по отдельности, потом извлекает из каждого файл
|
||
jni/<abi>/libjingle_peerconnection_so.so и собирает их в один архив.
|
||
|
||
Аргумент --arch может повторяться для перечисления нужных ABI (arm64-v8a, armeabi-v7a, x86, x86_64).
|
||
Дополнительные параметры GN передаются через --extra-gn-args, например чтобы включить H.265.
|
||
|
||
Пример запуска:
|
||
python3 build_multiabi_aar.py \
|
||
--build-dir=out/aar \
|
||
--arch=arm64-v8a --arch=armeabi-v7a --arch=x86 --arch=x86_64 \
|
||
--extra-gn-args='is_debug=false rtc_include_tests=false rtc_build_examples=false rtc_use_h265=true' \
|
||
--final-out=./libwebrtc.aar
|
||
|
||
Итоговый AAR будет записан в файл, указанный параметром --final-out.
|
||
"""
|
||
import argparse
|
||
import os
|
||
import shutil
|
||
import subprocess
|
||
import zipfile
|
||
import tempfile
|
||
import sys
|
||
|
||
# Compute the absolute repository root from this script's location.
|
||
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||
|
||
def run(cmd):
|
||
"""Выполняет команду в корне репозитория и выводит её в терминал."""
|
||
print(">>", " ".join(cmd))
|
||
subprocess.check_call(cmd, cwd=ROOT)
|
||
|
||
def find_built_aar(build_dir):
|
||
"""Возвращает путь к AAR, собранному build_aar.py, если он существует."""
|
||
cand1 = os.path.join(build_dir, "libwebrtc.aar")
|
||
cand2 = os.path.join(ROOT, "libwebrtc.aar")
|
||
for c in (cand1, cand2):
|
||
if os.path.exists(c):
|
||
return c
|
||
return None
|
||
|
||
def unzip_member(zpath, member, dest_dir):
|
||
"""Извлекает один файл из ZIP‑архива в указанную директорию."""
|
||
with zipfile.ZipFile(zpath, "r") as zf:
|
||
zf.extract(member, dest_dir)
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(description="Собрать libwebrtc.aar под несколько ABI")
|
||
parser.add_argument("--build-dir", default="out/aar", help="Каталог, который использует build_aar.py")
|
||
parser.add_argument("--arch", action="append", required=True, help="ABI для сборки; повторяйте для нескольких")
|
||
parser.add_argument("--extra-gn-args", dest="extra_gn_args", default="", help="Дополнительные параметры GN, передаваемые build_aar.py")
|
||
parser.add_argument("--final-out", default=os.path.join(ROOT, "libwebrtc.aar"), help="Путь к итоговому AAR")
|
||
args = parser.parse_args()
|
||
|
||
build_dir = os.path.join(ROOT, args.build_dir)
|
||
os.makedirs(build_dir, exist_ok=True)
|
||
|
||
# A directory to store per‑ABI AARs
|
||
stash_dir = os.path.join(build_dir, "_abi_aars")
|
||
os.makedirs(stash_dir, exist_ok=True)
|
||
|
||
built = []
|
||
for abi in args.arch:
|
||
# Construct the command to build the AAR for this ABI
|
||
cmd = [sys.executable,
|
||
os.path.join(ROOT, "tools_webrtc", "android", "build_aar.py"),
|
||
"--build-dir=" + args.build_dir,
|
||
"--arch=" + abi]
|
||
if args.extra_gn_args:
|
||
cmd.append("--extra-gn-args=" + args.extra_gn_args)
|
||
run(cmd)
|
||
|
||
produced = find_built_aar(build_dir)
|
||
if not produced:
|
||
raise RuntimeError(f"libwebrtc.aar not found after building {abi}")
|
||
abi_aar = os.path.join(stash_dir, f"{abi}.aar")
|
||
shutil.copy2(produced, abi_aar)
|
||
print(f"[OK] Stored {abi} AAR -> {abi_aar}")
|
||
built.append((abi, abi_aar))
|
||
|
||
# Use first ABI AAR as the base for non‑JNI files
|
||
base_abi, base_aar = built[0]
|
||
stage = tempfile.mkdtemp(prefix="webrtc_aar_")
|
||
with zipfile.ZipFile(base_aar, "r") as zf:
|
||
zf.extractall(stage)
|
||
|
||
# Replace or create the jni directory with combined libs
|
||
jni_dir = os.path.join(stage, "jni")
|
||
shutil.rmtree(jni_dir, ignore_errors=True)
|
||
os.makedirs(jni_dir, exist_ok=True)
|
||
|
||
for abi, abi_aar in built:
|
||
tmp = tempfile.mkdtemp(prefix="webrtc_abi_")
|
||
try:
|
||
member = f"jni/{abi}/libjingle_peerconnection_so.so"
|
||
unzip_member(abi_aar, member, tmp)
|
||
abi_dir = os.path.join(jni_dir, abi)
|
||
os.makedirs(abi_dir, exist_ok=True)
|
||
shutil.move(os.path.join(tmp, member), os.path.join(abi_dir, "libjingle_peerconnection_so.so"))
|
||
finally:
|
||
shutil.rmtree(tmp, ignore_errors=True)
|
||
|
||
# Write final AAR
|
||
final_aar = args.final_out
|
||
if os.path.exists(final_aar):
|
||
os.remove(final_aar)
|
||
with zipfile.ZipFile(final_aar, "w", zipfile.ZIP_DEFLATED) as zf:
|
||
for root, dirs, files in os.walk(stage):
|
||
for f in files:
|
||
full = os.path.join(root, f)
|
||
rel = os.path.relpath(full, stage)
|
||
zf.write(full, rel)
|
||
|
||
print("\n[OK] Создан многоплатформенный AAR:", final_aar)
|
||
with zipfile.ZipFile(final_aar, "r") as zf:
|
||
for n in zf.namelist():
|
||
if n.startswith("jni/") and n.endswith(".so"):
|
||
print(" ", n)
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
PY
|
||
|
||
# Make the helper script executable
|
||
chmod +x tools_webrtc/android/build_multiabi_aar.py
|
||
|
||
echo "=== Шаг 7: Сборка libstream-webrtc-1.3.9.aar для нескольких ABI c H.265 ==="
|
||
# Запускаем вспомогательный скрипт, передавая необходимые архитектуры и параметры GN.
|
||
# Итоговый AAR будет записан в <src>/libstream-webrtc-1.3.9.aar.
|
||
python3 tools_webrtc/android/build_multiabi_aar.py \
|
||
--build-dir=out/aar \
|
||
--arch=arm64-v8a \
|
||
--arch=armeabi-v7a \
|
||
--arch=x86 \
|
||
--arch=x86_64 \
|
||
--extra-gn-args='is_debug=false rtc_include_tests=false rtc_build_examples=false rtc_use_h265=true' \
|
||
--final-out="$(pwd)/libstream-webrtc-1.3.9.aar"
|
||
|
||
echo "Всё готово!"
|
||
echo "Готовый libstream-webrtc-1.3.9.aar находится в: $(pwd)/libstream-webrtc-1.3.9.aar"
|
||
echo "Промежуточные AAR‑файлы по архитектурам лежат в директории out/aar/_abi_aars"
|