From 3a4333ef47c69442f2011153315c373aa70e7e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Sat, 24 Jun 2023 22:02:08 +0200 Subject: [PATCH] feat: webrtc builds for ios & android (#93) --- .github/workflows/builds.yml | 1 + .github/workflows/tests.yml | 1 + .github/workflows/webrtc-builds.yml | 106 +++++++++++++++------ webrtc-sys/compile_flags.txt | 6 ++ webrtc-sys/libwebrtc/.gclient | 14 ++- webrtc-sys/libwebrtc/.gitignore | 2 + webrtc-sys/libwebrtc/build_android.sh | 116 +++++++++++++++++++++++ webrtc-sys/libwebrtc/build_ios.sh | 126 +++++++++++++++++++++++++ webrtc-sys/libwebrtc/build_linux.sh | 2 +- webrtc-sys/libwebrtc/build_macos.sh | 4 +- webrtc-sys/libwebrtc/build_windows.cmd | 2 +- webrtc-sys/libwebrtc/configure.py | 26 ----- 12 files changed, 339 insertions(+), 67 deletions(-) create mode 100755 webrtc-sys/libwebrtc/build_android.sh create mode 100755 webrtc-sys/libwebrtc/build_ios.sh delete mode 100644 webrtc-sys/libwebrtc/configure.py diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 4fce1ba..a60ad95 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -12,6 +12,7 @@ env: jobs: build: strategy: + fail-fast: false matrix: include: - os: windows-latest diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 54b8240..e542866 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,6 +13,7 @@ env: jobs: build: strategy: + fail-fast: false matrix: include: # Platform supports is limited for tests (no aarch64) diff --git a/.github/workflows/webrtc-builds.yml b/.github/workflows/webrtc-builds.yml index 44ca3ef..49bcc1f 100644 --- a/.github/workflows/webrtc-builds.yml +++ b/.github/workflows/webrtc-builds.yml @@ -6,35 +6,78 @@ jobs: strategy: fail-fast: false matrix: - os: - - windows-latest - - ubuntu-latest - - macos-latest - arch: - - x64 - - arm64 + target: + - name: win + os: windows-latest + cmd: .\build_windows.cmd + arch: x64 + + - name: win + os: windows-latest + cmd: .\build_windows.cmd + arch: arm64 + + - name: mac + os: macos-latest + cmd: ./build_macos.sh + arch: x64 + + - name: mac + os: macos-latest + cmd: ./build_macos.sh + arch: arm64 + + - name: linux + os: ubuntu-latest + cmd: ./build_linux.sh + arch: x64 + + - name: linux + os: ubuntu-latest + cmd: ./build_linux.sh + arch: arm64 + + - name: android + os: ubuntu-latest + cmd: ./build_android.sh + arch: arm64 + + - name: android + os: ubuntu-latest + cmd: ./build_android.sh + arch: arm + + - name: android + os: ubuntu-latest + cmd: ./build_android.sh + arch: x64 + + - name: ios + out: ios-device-arm64 + os: macos-latest + cmd: ./build_ios.sh + arch: arm64 + + - name: ios + out: ios-simulator-arm64 + os: macos-latest + cmd: ./build_ios.sh + arch: arm64 + buildargs: --environment simulator profile: - release - debug - include: - - os: windows-latest - cmd: .\build_windows.cmd - name: win - - os: ubuntu-latest - cmd: ./build_linux.sh - name: linux - - os: macos-latest - cmd: ./build_macos.sh - name: macos - name: Build webrtc (${{ matrix.name }}-${{ matrix.arch }}-${{ matrix.profile }}) - runs-on: ${{ matrix.os }} + name: Build webrtc (${{ matrix.target.name }}-${{ matrix.target.arch }}-${{ matrix.profile }}) ${{ matrix.target.buildargs }} + runs-on: ${{ matrix.target.os }} steps: - - name: Setup vars + - name: Setup variables id: setup run: | - echo "OUT=${{ matrix.name }}-${{ matrix.arch }}-${{ matrix.profile }}" >> "$GITHUB_OUTPUT" - echo "ZIP=webrtc-${{ matrix.name }}-${{ matrix.arch }}-${{ matrix.profile }}.zip" >> "$GITHUB_OUTPUT" + DEFAULT_OUT=${{ matrix.target.name }}-${{ matrix.target.arch }} + OUT=${{ matrix.target.out == '' && '$DEFAULT_OUT' || matrix.target.out }}-${{ matrix.profile }} + echo OUT=$OUT >> $GITHUB_OUTPUT + echo ZIP=webrtc-$OUT.zip >> $GITHUB_OUTPUT shell: bash # Print some debug infos to be sure everything is ok before doing really long tasks.. @@ -48,16 +91,16 @@ jobs: submodules: true - name: Install linux dependencies - if: ${{ matrix.os == 'ubuntu-latest' }} - run: sudo apt install -y ninja-build pkg-config + if: ${{ matrix.target.os == 'ubuntu-latest' }} + run: sudo apt install -y ninja-build pkg-config openjdk-11-jdk - name: Install macos dependencies - if: ${{ matrix.os == 'macos-latest' }} + if: ${{ matrix.target.os == 'macos-latest' }} run: brew install ninja # It doesn't seem to be used? - name: Install windows dependencies - if: ${{ matrix.os == 'windows-latest' }} + if: ${{ matrix.target.os == 'windows-latest' }} run: | Invoke-WebRequest -Uri "https://github.com/ninja-build/ninja/releases/latest/download/ninja-win.zip" -OutFile ninja.zip Expand-Archive -Path ninja.zip -DestinationPath ninja @@ -66,18 +109,23 @@ jobs: - name: Print ninja version run: ninja --version + - name: Target OS + run: echo -e "\ntarget_os = [\"${{ matrix.target.name }}\"]" >> .gclient + shell: bash + working-directory: webrtc-sys/libwebrtc + - name: Build WebRTC - run: ${{ matrix.cmd }} --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} + run: ${{ matrix.target.cmd }} --arch ${{ matrix.target.arch }} --profile ${{ matrix.profile }} ${{ matrix.target.buildargs }} working-directory: webrtc-sys/libwebrtc - name: Zip artifact (Unix) - if: ${{ matrix.os != 'windows-latest' }} + if: ${{ matrix.target.os != 'windows-latest' }} run: | cd webrtc-sys/libwebrtc/${{ steps.setup.outputs.OUT }} zip ${{ github.workspace }}/${{ steps.setup.outputs.ZIP }} ./* -r - name: Zip artifact (Windows) - if: ${{ matrix.os == 'windows-latest' }} + if: ${{ matrix.target.os == 'windows-latest' }} run: Compress-Archive -Path .\webrtc-sys\libwebrtc\${{ steps.setup.outputs.OUT }}\* -DestinationPath ${{ steps.setup.outputs.ZIP }} # doublezip here but I don't think there is an alternative diff --git a/webrtc-sys/compile_flags.txt b/webrtc-sys/compile_flags.txt index c8ce65a..93be899 100644 --- a/webrtc-sys/compile_flags.txt +++ b/webrtc-sys/compile_flags.txt @@ -1,10 +1,16 @@ -xc++ +-xobjective-c++ -std=c++17 -Iinclude -Ilibwebrtc/src -Ilibwebrtc/src/third_party/abseil-cpp -Ilibwebrtc/src/third_party/libc++ -Ilibwebrtc/src/third_party/libyuv/include +-Ilibwebrtc/src/sdk/objc/base +-Ilibwebrtc/src/sdk/objc -I../target/cxxbridge -DWEBRTC_MAC -DWEBRTC_POSIX +-DNDEBUG +-DWEBRTC_ENABLE_SYMBOL_EXPORT +-DWEBRTC_LIBRARY_IMPL \ No newline at end of file diff --git a/webrtc-sys/libwebrtc/.gclient b/webrtc-sys/libwebrtc/.gclient index b58c202..2d83068 100644 --- a/webrtc-sys/libwebrtc/.gclient +++ b/webrtc-sys/libwebrtc/.gclient @@ -1,11 +1,9 @@ solutions = [ - { - "name" : 'src', - "url" : 'https://github.com/webrtc-sdk/webrtc.git', - "deps_file" : 'DEPS', - "managed" : False, - "custom_deps" : { - }, - "custom_vars": {}, + { + "name": 'src', + "url": 'https://github.com/webrtc-sdk/webrtc.git', + "custom_deps": {}, + "deps_file": "DEPS", + "managed": False, }, ] diff --git a/webrtc-sys/libwebrtc/.gitignore b/webrtc-sys/libwebrtc/.gitignore index 0ad769f..069beab 100644 --- a/webrtc-sys/libwebrtc/.gitignore +++ b/webrtc-sys/libwebrtc/.gitignore @@ -8,3 +8,5 @@ ninja win* macos* linux* +android* +ios* diff --git a/webrtc-sys/libwebrtc/build_android.sh b/webrtc-sys/libwebrtc/build_android.sh new file mode 100755 index 0000000..c4264ab --- /dev/null +++ b/webrtc-sys/libwebrtc/build_android.sh @@ -0,0 +1,116 @@ +#!/bin/bash + +arch="" +profile="release" + +while [ "$#" -gt 0 ]; do + case "$1" in + --arch) + arch="$2" + if [ "$arch" != "arm" ] && [ "$arch" != "x64" ] && [ "$arch" != "arm64" ]; then + echo "Error: Invalid value for --arch. Must be 'arm', 'x64' or 'arm64'." + exit 1 + fi + shift 2 + ;; + --profile) + profile="$2" + if [ "$profile" != "debug" ] && [ "$profile" != "release" ]; then + echo "Error: Invalid value for --profile. Must be 'debug' or 'release'." + exit 1 + fi + shift 2 + ;; + *) + echo "Error: Unknown argument '$1'" + exit 1 + ;; + esac +done + +if [ -z "$arch" ]; then + echo "Error: --arch must be set." + exit 1 +fi + +echo "Building LiveKit WebRTC - Android" +echo "Arch: $arch" +echo "Profile: $profile" + +if [ ! -e "$(pwd)/depot_tools" ] +then + git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git +fi + +export COMMAND_DIR=$(cd $(dirname $0); pwd) +export PATH="$(pwd)/depot_tools:$PATH" +export OUTPUT_DIR="$(pwd)/src/out-$arch-$profile" +export ARTIFACTS_DIR="$(pwd)/android-$arch-$profile" + +if [ ! -e "$(pwd)/src" ] +then + gclient sync -D --no-history +fi + +cd src +git apply "$COMMAND_DIR/patches/add_license_dav1d.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn +git apply "$COMMAND_DIR/patches/ssl_verify_callback_with_native_handle.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn +git apply "$COMMAND_DIR/patches/fix_mocks.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn +cd .. + +mkdir -p "$ARTIFACTS_DIR/lib" + +debug="false" +if [ "$profile" = "debug" ]; then + debug="true" +fi + +args="is_debug=$debug \ + is_java_debug=$debug \ + target_os=\"android\" \ + target_cpu=\"$arch\" \ + rtc_enable_protobuf=false \ + treat_warnings_as_errors=false \ + use_custom_libcxx=false \ + rtc_include_tests=false \ + rtc_build_tools=false \ + rtc_build_examples=false \ + rtc_libvpx_build_vp9=true \ + is_component_build=false \ + enable_stripping=true \ + use_goma=false \ + rtc_use_h264=false \ + rtc_use_pipewire=false \ + symbol_level=0 \ + enable_iterator_debugging=false \ + use_rtti=true" + +if [ "$debug" = "true" ]; then + args="${args} is_asan=true is_lsan=true"; +fi + +# generate ninja files +gn gen "$OUTPUT_DIR" --root="src" --args="${args}" + +# build static library +ninja -C "$OUTPUT_DIR" :default \ + sdk/android:native_api \ + sdk/android:libwebrtc \ + sdk/android:libjingle_peerconnection_so + + +# make libwebrtc.a +# don't include nasm +ar -rc "$ARTIFACTS_DIR/lib/libwebrtc.a" `find "$OUTPUT_DIR/obj" -name '*.o' -not -path "*/third_party/nasm/*"` + +python3 "./src/tools_webrtc/libs/generate_licenses.py" \ + --target :default "$OUTPUT_DIR" "$OUTPUT_DIR" + +cp "$OUTPUT_DIR/obj/webrtc.ninja" "$ARTIFACTS_DIR" +cp "$OUTPUT_DIR/libjingle_peerconnection_so.so" "$ARTIFACTS_DIR/lib" +cp "$OUTPUT_DIR/args.gn" "$ARTIFACTS_DIR" +cp "$OUTPUT_DIR/LICENSE.md" "$ARTIFACTS_DIR" + +cd src +find . -name "*.h" -print | cpio -pd "$ARTIFACTS_DIR/include" + diff --git a/webrtc-sys/libwebrtc/build_ios.sh b/webrtc-sys/libwebrtc/build_ios.sh new file mode 100755 index 0000000..53a87d3 --- /dev/null +++ b/webrtc-sys/libwebrtc/build_ios.sh @@ -0,0 +1,126 @@ +#!/bin/bash + +arch="" +profile="release" +environment="device" + +while [ "$#" -gt 0 ]; do + case "$1" in + --arch) + arch="$2" + if [ "$arch" != "arm64" ]; then + echo "Error: Invalid value for --arch. Must 'arm64'." + exit 1 + fi + shift 2 + ;; + --environment) + environment="$2" + if [ "$environment" != "device" ] && [ "$environment" != "simulator" ]; then + echo "Error: Invalid value for --environment. Must be 'device' or 'simulator'." + exit 1 + fi + shift 2 + ;; + --profile) + profile="$2" + if [ "$profile" != "debug" ] && [ "$profile" != "release" ]; then + echo "Error: Invalid value for --profile. Must be 'debug' or 'release'." + exit 1 + fi + shift 2 + ;; + *) + echo "Error: Unknown argument '$1'" + exit 1 + ;; + esac +done + +if [ -z "$arch" ]; then + echo "Error: --arch must be set." + exit 1 +fi + +echo "Building LiveKit WebRTC - iOS" +echo "Arch: $arch" +echo "Profile: $profile" +echo "Environment: $environment" + +if [ ! -e "$(pwd)/depot_tools" ] +then + git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git +fi + +export COMMAND_DIR=$(cd $(dirname $0); pwd) +export PATH="$(pwd)/depot_tools:$PATH" + +export OUTPUT_DIR="$(pwd)/src/out-$arch-$profile" +export ARTIFACTS_DIR="$(pwd)/ios-$environment-$arch-$profile" + +if [ ! -e "$(pwd)/src" ] +then + gclient sync -D --no-history +fi + +cd src +git apply "$COMMAND_DIR/patches/add_license_dav1d.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn +git apply "$COMMAND_DIR/patches/ssl_verify_callback_with_native_handle.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn +git apply "$COMMAND_DIR/patches/fix_mocks.patch" -v --ignore-space-change --ignore-whitespace --whitespace=nowarn +cd .. + +mkdir -p "$ARTIFACTS_DIR/lib" + +debug="false" +if [ "$profile" = "debug" ]; then + debug="true" +fi + +# generate ninja files +gn gen "$OUTPUT_DIR" --root="src" \ + --args="is_debug=$debug \ + enable_dsyms=$debug \ + target_os=\"ios\" \ + target_cpu=\"$arch\" \ + target_environment=\"$environment\" \ + treat_warnings_as_errors=false \ + ios_enable_code_signing=false \ + rtc_enable_protobuf=false \ + rtc_include_tests=false \ + rtc_build_examples=false \ + rtc_build_tools=false \ + rtc_libvpx_build_vp9=true \ + is_component_build=false \ + enable_stripping=true \ + rtc_enable_symbol_export=true \ + rtc_enable_objc_symbol_export=false \ + rtc_use_h264=false \ + use_custom_libcxx=false \ + clang_use_chrome_plugins=false \ + use_rtti=true \ + use_lld=false" + +# build static library +ninja -C "$OUTPUT_DIR" :default \ + api/audio_codecs:builtin_audio_decoder_factory \ + api/task_queue:default_task_queue_factory \ + sdk:native_api \ + sdk:default_codec_factory_objc \ + pc:peerconnection \ + sdk:videocapture_objc \ + sdk:framework_objc + +# make libwebrtc.a +# don't include nasm +ar -rc "$ARTIFACTS_DIR/lib/libwebrtc.a" `find "$OUTPUT_DIR/obj" -name '*.o' -not -path "*/third_party/nasm/*"` + +python3 "./src/tools_webrtc/libs/generate_licenses.py" \ + --target :webrtc "$OUTPUT_DIR" "$OUTPUT_DIR" + +cp "$OUTPUT_DIR/obj/webrtc.ninja" "$ARTIFACTS_DIR" +cp "$OUTPUT_DIR/args.gn" "$ARTIFACTS_DIR" +cp "$OUTPUT_DIR/LICENSE.md" "$ARTIFACTS_DIR" + +cd src +find . -name "*.h" -print | cpio -pd "$ARTIFACTS_DIR/include" + diff --git a/webrtc-sys/libwebrtc/build_linux.sh b/webrtc-sys/libwebrtc/build_linux.sh index 896ac21..0a25a23 100755 --- a/webrtc-sys/libwebrtc/build_linux.sh +++ b/webrtc-sys/libwebrtc/build_linux.sh @@ -33,7 +33,7 @@ if [ -z "$arch" ]; then exit 1 fi -echo "Building LiveKit WebRTC" +echo "Building LiveKit WebRTC - Linux" echo "Arch: $arch" echo "Profile: $profile" diff --git a/webrtc-sys/libwebrtc/build_macos.sh b/webrtc-sys/libwebrtc/build_macos.sh index d8c027f..dea40f1 100755 --- a/webrtc-sys/libwebrtc/build_macos.sh +++ b/webrtc-sys/libwebrtc/build_macos.sh @@ -33,7 +33,7 @@ if [ -z "$arch" ]; then exit 1 fi -echo "Building LiveKit WebRTC" +echo "Building LiveKit WebRTC - MacOS" echo "Arch: $arch" echo "Profile: $profile" @@ -45,7 +45,7 @@ fi export COMMAND_DIR=$(cd $(dirname $0); pwd) export PATH="$(pwd)/depot_tools:$PATH" export OUTPUT_DIR="$(pwd)/src/out-$arch-$profile" -export ARTIFACTS_DIR="$(pwd)/macos-$arch-$profile" +export ARTIFACTS_DIR="$(pwd)/mac-$arch-$profile" if [ ! -e "$(pwd)/src" ] then diff --git a/webrtc-sys/libwebrtc/build_windows.cmd b/webrtc-sys/libwebrtc/build_windows.cmd index 7bb57b1..83dd54c 100644 --- a/webrtc-sys/libwebrtc/build_windows.cmd +++ b/webrtc-sys/libwebrtc/build_windows.cmd @@ -28,7 +28,7 @@ if not "!profile!" == "debug" if not "!profile!" == "release" ( exit /b 1 ) -echo "Building LiveKit WebRTC" +echo "Building LiveKit WebRTC - Windows" echo "Arch: !arch!" echo "Profile: !profile!" diff --git a/webrtc-sys/libwebrtc/configure.py b/webrtc-sys/libwebrtc/configure.py deleted file mode 100644 index c335ff9..0000000 --- a/webrtc-sys/libwebrtc/configure.py +++ /dev/null @@ -1,26 +0,0 @@ -# Ignore this file if you have no intention of using a custom libwebrtc build. - -import platform -import subprocess - -# Edit the target_os/target_cpu to match your platform. -GN_ARGS = [ - "is_debug=true", - "treat_warnings_as_errors=false", - 'target_os="mac"', - 'target_cpu="arm64"', - "rtc_include_tests=false", - "rtc_use_h264=false", - "is_component_build=false", - "rtc_build_examples=false", - "use_rtti=true", - "rtc_build_tools=false", - "use_custom_libcxx=false", -] - -cmd = ["gn", "gen", "out/Dev", "--args=" + ' '.join(GN_ARGS)] -print("Executing:", cmd) -subprocess.call(cmd, shell=platform.system() == "Windows") - -# Use this command when developing on libwebrtc: -# ninja -C out/Dev sdk:default_codec_factory_objc api api/task_queue:default_task_queue_factory api/audio_codecs:builtin_audio_decoder_factory sdk:videocapture_objc pc:peerconnection sdk:native_api callback_logger_objc default