OSX(Macos) 下编译 WebRTC - Android

美景总是好的

介绍

这段时间基于 Mediasoup 的开源又搞了一遍 WebRTC 的客户端的搭建, 需要支持 iOS, Android, Windows各平台的使用, 这次可以基于较新(M99) 的 WebRTC 版本封装 SDK.

WebRTC 的官方编译这不同系统的 SDK, 也是需要几个操作系统(OSX, Linux, Windows)的环境支持, 如果长期需要三个系统支持编译切换起来也麻烦了. 网上有用虚拟机编译的, 但本人对虚拟机的性能一直比较不看好(虚拟机用的也不熟), 所以还是最好能直接在 OSX 上支持.

在猿辅导的时候是通过阉割了 WetRTC 工具链中的所有 Java支持的部分, 只保留了 C++ 的支持, 可以统一在 OSX 上编译 iOS, Mac, Android, 对于开发环的简化和统一确实起到了一些作用.

这次还是想彻底搞一搞(当然 Windows 环境暂时没办法做交叉编译, 还是需要 Windows 环境), 主要针对是 OSX 上编译 WebRTC Android, 因为计划 JNI 的框架也使用 WebRTC 里的 generate jni 的这套流程, 所以需要保留对 Java, Android 的完整支持, 编译的时候直接有检查 JNI 的错误, 对于开发来说能提早暴露出不少问题.

目录

修改内容主要真对下面三个大的分类

  • 环境准备
  • 工具链修改
  • gn gen 命令行参数

环境准备

WebRTC 代码准备

创建两个目录分别执行 fetch webrtc_android, fetch webrtc_ios, 我们下面就直接称为 webrtc_android 和 webrtc_ios.

切换到同一分支后使用 gclient sync 进行工具链的同步, 使用 webrtc_ios 为基础, 毕竟这是标准的 Macos 环境工具链.

根目录 .cipd 目录

webrtc_android 目中 gclient sync 后, third_party 有些内容会软连接到根目录下的 .cipd 里的内容, 把 .cipd 目录直接覆盖到 webrtc_ios 目录中.

ios 的 .cipd 没什么用直接替换就行了.

third_party 合并

webrtc_android/third_party 目录下的 android 开头的一些目录直接 覆盖掉 webrtc_ios/third_party

编译中还会有个别缺失的, 可以根据报错信息再覆盖过去, 例如 libunwindstack.

Android NDK & SDK

webrtc_android/src/third_party/android_ndk, webrtc_android/src/third_party/android_sdk 是 WebRTC 编译 Android 用的 NDK, SDK, 目前NDK版本是 22, 但这是 Linux 版本, 不能在 Macos 上使用.

手动下载 Android NDK, 我们使用自定义的 NDK

目前测试 NDK23,24编译还有问题, 如果有需要可以自行研究下, 或者等 Google 更新工具链.

JDK

  • 手动下载 JDK, 需要11 或者以后的版本, 替换到 third_party/jdk/current 目录下
  • 下载 jdk8, 解压缩后找到里面的 rt.jar, 也 copy 到 third_party/jdk/current 目录下

rt.jar 在 jdk8 版本后已经从 jdk 里删除了

AAPT2

AAPT2(Android Asset Packaging Tool)是Android Studio和Android Gradle Plugin用于编译和打包应用程序资源的构建工具。
https://developer.android.com/studio/command-line/aapt2

手动下载 OSX 的 aapt2 替换到 third_party/android_build_tools/aapt2

好了... 环境这就准备的差不多了...下面开始需要修改一些编译的脚本.

工具链修改

third_party 目录

third_party/ijar/BUILD.gn
if (is_linux || is_chromeos) {
  ...
}

这个环境判断条件, 直接注释掉, 否则当执行到ijar 的时候会报错.

third_party/android_sdk/BUILD.gn
# public_deps = [ "$android_ndk_root:cpu_features" ]
public_deps = [ "//third_party/android_ndk:cpu_features" ]

因为我们用官方下载的 NDK 是没有 cpu_features 的 gn 配置, 我们可以继续用原有 third_party 目录下的配置, 但因为我们后面会修改掉 android_ndk_root 的环境变量, 所以改成直接引用绝对路径.

build 工具链配置

build/android/gyp/util/build_utils.py

根据自己放 rt.jar 位置修改 RT_JAR_PATH.

# RT_JAR_PATH = os.path.join(DIR_SOURCE_ROOT, 
# 'third_party', 'jdk', 'extras', 'java_8', 'jre', 'lib', 'rt.jar')
RT_JAR_PATH = os.path.join(JAVA_HOME, 'rt.jar')
build/android/gyp/util/server_utils.py

注释掉这一段.

-  if BUILD_SERVER_ENV_VARIABLE in os.environ:
-    return False
-  with contextlib.closing(socket.socket(socket.AF_UNIX)) as sock:
-    try:
-      sock.connect(SOCKET_ADDRESS)
-      sock.sendall(
-          json.dumps({
-              'name': name,
-              'cmd': argv,
-              'cwd': os.getcwd(),
-              'stamp_file': stamp_file,
-          }).encode('utf8'))
-    except socket.error as e:
-      # [Errno 111] Connection refused. Either the server has not been started
-      #             or the server is not currently accepting new connections.
-      if e.errno == 111:
-        return False
-      raise e
build/config/c++/BUILD.gn

不使用 buildtools 下的 c++ 标准库实现, 统一使用自己下载的 NDK.

+  if (!(is_android && host_os == "mac")) {
     include_dirs += [ "//buildtools/third_party/libc++" ]
+  }
+  if (!(is_android && host_os == "mac")) {
      cflags_cc += [
        "-nostdinc++",
        "-isystem" + rebase_path("$libcxx_prefix/include", root_build_dir),
        "-isystem" + rebase_path("$libcxxabi_prefix/include", root_build_dir),
      ]
+  }
build/compiler/BUILD.gn

NDK22 的 clang version 是11, 有些选项是不支持.

...
-  cflags += [ "-mno-outline-atomics" ]   // clang 12.0.0 支持
... 

-  cflags += [ "-ffile-compilation-dir=." ] // clang 13.0.0 支持

...

-  cflags += [
-    "-Xclang",
-    "-fuse-ctor-homing", // clang 13.0.0 支持
-  ] 

个别不支持警告也可以适当关闭.
"-Wno-unused-but-set-variable",

gn gen 命令行参数

clang_use_chrome_plugins

使用官方下载的 NDK, 内部的 clang 是没有 google 添加的 plugin, 这里要禁用

clang_use_chrome_plugins=false
use_lld

NDK 22 LLD 现在是默认链接器, 不需要显式设置 use_lld

use_lld=false
use_custom_libcxx

使用 NDK 带的 c++ 标准库, 禁用 buildtools 下的.

use_custom_libcxx=false
Android SDK

使用自定义的 SDK, 根据自己使用的路径和 buildtools 版本设置

android_sdk_root="${ANDROID_SDK_ROOT}"
android_sdk_version="32"
android_sdk_build_tools_version="32.0.0"
Android NDK

使用自定义的 NDK, 根据自己使用的路径和版本设置

clang_base_path="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/darwin-x86_64"
target_sysroot="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/darwin-x86_64/sysroot"
android_ndk_root="${ANDROID_NDK_ROOT}"
android_ndk_major_version=22
gn gen 例子

到这里基本配置已经修改的差不多了, 可以在 OSX 上也像 Linux 上一样的对 Android 进行支持了. 下面是 gn gen 生成 Android 工程的一个例子(debug 版本), 包含了上面的一些设置, 和和其他平台共用的一些设置, 作为参考:

gn gen out/android/debug/arm64 --args="target_cpu="arm64" target_os="android" rtc_include_ilbc=false rtc_build_examples=false rtc_build_tools=false rtc_enable_protobuf=false rtc_enable_sctp=false rtc_include_tests=false libyuv_include_tests=false rtc_disable_trace_events=true enable_dsyms=true rtc_use_h264=true rtc_build_x264=true ffmpeg_branding="Chrome" treat_warnings_as_errors=false clang_use_chrome_plugins=false use_lld=false use_custom_libcxx=false clang_base_path="/Users/edy/Library/Android/sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/darwin-x86_64" target_sysroot="/Users/edy/Library/Android/sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/darwin-x86_64/sysroot" android_ndk_root="/Users/edy/Library/Android/sdk/ndk/22.1.7171670" android_ndk_major_version=22 android_sdk_root="/Users/edy/Library/Android/sdk" android_sdk_version="32" android_sdk_build_tools_version="32.0.0" symbol_level=2 is_debug=true"

结束语

这些流程是通过事后的一些修改记录整理出来的, 如果有什么遗漏或者不同 arch 的问题, 各位看官们可以评论, 后面也会进行补充和修改.
需要替换和修改的东西并不多, 不清楚为什么 Google 不从官方直接支持, 可以省去大家不少事.

你可能感兴趣的:(OSX(Macos) 下编译 WebRTC - Android)