Compile WebRTC for Android on Mac

The basic process of compiling WebRTC for Android on Mac is roughly the same as compiling WebRTC for any other target platform on any platform. However, compiling WebRTC for Android on Mac is not a construction method of WebRTC officially supported by WebRTC, so it needs to be built specifically for this purpose. method, make some appropriate adjustments to some configurations and tools in the WebRTC build system. This article will describe the process of compiling WebRTC for Android on Mac, the problems you will encounter at each step in the process, a simple explanation of the cause of the problem, and the solution to the problem.

The process for compiling WebRTC for Android on Mac is as follows.

1. Create args.gnfile

args.gnMake some global build configuration switches for the build creation file of WebRTC for Android , such as:

is_component_build = false
rtc_build_tools = false
rtc_include_tests = false
treat_warnings_as_errors = false
use_rtti = false
use_dummy_lastchange = true
is_clang = true
target_cpu = "arm64"
is_debug = true
symbol_level = 2
clang_base_path = "/Users/lisi/Projects/opensource/OpenRTCClient/build_system/llvm-build/mac/mac/Release+Asserts"
android_sdk_build_tools_version = "30.0.1"
target_os = "android"
android_ndk_root = "/Users/lisi/Library/Android/sdk/ndk/23.1.7779620"
android_sdk_root = "/Users/lisi/Library/Android/sdk"
clang_use_chrome_plugins = false
lint_android_sdk_root = "/Users/lisi/Library/Android/sdk"
use_custom_libcxx = false
use_sysroot = false
enable_libaom = false
enable_libaom_decoder = false
rtc_use_h264 = true
rtc_enable_protobuf = true
rtc_include_ilbc = false
rtc_libvpx_build_vp9 = true
ffmpeg_branding = "Chrome"

2. gn genGenerate build configuration file

Generate the configuration files required for the build by gn genbased on the created args.gnfiles, individual BUILD.gnand *.gnibuild configuration files . ninjaAssuming args.gnthe file is located build/android/arm64/debugin the directory, execute the following command:

OpenRTCClient % gn gen build/android/arm64/debug

An error was reported here, and the error message is as follows:

OpenRTCClient % gn gen build/android/arm64/debug
ERROR Unresolved dependencies.
//examples/androidapp/third_party/autobanh:autobanh_java__header(//build/toolchain/android:android_clang_arm64)
  needs //third_party/ijar:ijar(//build/toolchain/mac:clang_x64)
//third_party/accessibility_test_framework:accessibility_test_framework_java__header(//build/toolchain/android:android_clang_arm64)
  needs //third_party/ijar:ijar(//build/toolchain/mac:clang_x64)
//third_party/android_deps:android_arch_core_common_java__header(//build/toolchain/android:android_clang_arm64)
  needs //third_party/ijar:ijar(//build/toolchain/mac:clang_x64)
//third_party/android_deps:android_arch_core_runtime_java__classes__header(//build/toolchain/android:android_clang_arm64)
  needs //third_party/ijar:ijar(//build/toolchain/mac:clang_x64)
//third_party/android_deps:android_arch_lifecycle_common_java8_java__header(//build/toolchain/android:android_clang_arm64)
  needs //third_party/ijar:ijar(//build/toolchain/mac:clang_x64)
//third_party/android_deps:android_arch_lifecycle_common_java__header(//build/toolchain/android:android_clang_arm64)
  needs //third_party/ijar:ijar(//build/toolchain/mac:clang_x64)
. . . . . .

The error message states that a widely relied upon build target cannot be found //third_party/ijar:ijar.

From this error message, we can easily understand that this build target should be defined in webrtc/third_party/ijar/BUILD.gnthe file. Let's open this file and take a look at the definition of this build target:

if (is_linux || is_chromeos) {
  config("ijar_compiler_flags") {
    if (is_clang) {
      cflags = [
        "-Wno-shadow",
        "-Wno-unused-but-set-variable",
      ]
    }
  }

  executable("ijar") {
    sources = [
      "classfile.cc",
      "common.h",
      "ijar.cc",
      "mapped_file.h",
      "mapped_file_unix.cc",
      "platform_utils.cc",
      "platform_utils.h",
      "zip.cc",
      "zip.h",
      "zlib_client.cc",
      "zlib_client.h",
    ]

    deps = [ "//third_party/zlib" ]

    configs += [ ":ijar_compiler_flags" ]

    # Always build release since this is a build tool.
    if (is_debug) {
      configs -= [ "//build/config:debug" ]
      configs += [ "//build/config:release" ]
    }
  }
}

From this file, you can see that the build target is defined only on Linux and ChromeOS //third_party/ijar:ijar. We modify the conditions in the above ifjudgment and also define this build target for Mac. Specifically, the following conditions are judged:

if (is_linux || is_chromeos) {

change into:

if (is_linux || is_chromeos || is_mac) {

webrtc/third_party/ijar/BUILD.gnThe other contents of this file remain unchanged.

This way we can successfully execute gn gen:

OpenRTCClient % gn gen build/android/arm64/debug
Done. Made 5530 targets from 318 files in 2743ms

3. Execute ninjathe command to build WebRTC

(1). -ffile-compilation-dir=.Compilation errors caused by

Execute ninjathe command to build WebRTC:

OpenRTCClient % ninja -C build/android/arm64/debug

Before compiling a few lines of code, a compilation error was reported:

OpenRTCClient % ninja -C build/android/arm64/debug
ninja: Entering directory `/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug'
[1/5234] CC obj/base/third_party/libevent/libevent/event_tagging.o
FAILED: obj/base/third_party/libevent/libevent/event_tagging.o 
../../../../../../../Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -MMD -MF obj/base/third_party/libevent/libevent/event_tagging.o.d -DHAVE_CONFIG_H -D_GNU_SOURCE -DANDROID -DHAVE_SYS_UIO_H -DANDROID_NDK_VERSION_ROLL=r22_1 -D_DEBUG -DDYNAMIC_ANNOTATIONS_ENABLED=1 -I../../../../webrtc/base/third_party/libevent/android -I../../../../webrtc -Igen -fno-delete-null-pointer-checks -fno-ident -fno-strict-aliasing --param=ssp-buffer-size=4 -fstack-protector -funwind-tables -fPIC -fcolor-diagnostics -fmerge-all-constants -fcrash-diagnostics-dir=../../../../webrtc/tools/clang/crashreports -mllvm -instcombine-lower-dbg-declare=0 -ffp-contract=off -ffunction-sections -fno-short-enums --target=aarch64-linux-android21 -mno-outline-atomics -mno-outline -Wno-builtin-macro-redefined -D__DATE__= -D__TIME__= -D__TIMESTAMP__= -ffile-compilation-dir=. -no-canonical-prefixes -Oz -fdata-sections -ffunction-sections -fno-unique-section-names -fno-omit-frame-pointer -g2 -gdwarf-aranges -ggnu-pubnames -Xclang -fuse-ctor-homing -fvisibility=hidden -Wheader-hygiene -Wstring-conversion -Wtautological-overlap-compare -Wall -Wno-unused-variable -Wno-c++11-narrowing -Wno-unused-but-set-variable -Wno-misleading-indentation -Wno-missing-field-initializers -Wno-unused-parameter -Wloop-analysis -Wno-unneeded-internal-declaration -Wenum-compare-conditional -Wno-psabi -Wno-ignored-pragma-optimize -Wmax-tokens -std=c11 --sysroot=../../../../../../../Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -c ../../../../webrtc/base/third_party/libevent/event_tagging.c -o obj/base/third_party/libevent/libevent/event_tagging.o
clang: error: unknown argument: '-ffile-compilation-dir=.'
[2/5234] CC obj/base/third_party/libevent/libevent/signal.o
. . . . . .

This error message means that clanga compilation option cannot be recognized -ffile-compilation-dir=.. There is a post on stack overflow discussing this issue, Can't build Webrtc with Bitcode enabled . This problem occurs because the version used to compile WebRTC is generally relatively new. The WebRTC build system sets a compilation option for compilation that is only supported by clangnewer versions. However , the version used for local compilation is not new enough, so the compilation tool appears. Unable to recognize compilation options.clangclang

This compilation option is webrtc/build/config/compiler/BUILD.gnadded in the file:

  if (is_clang && strip_absolute_paths_from_debug_symbols) {
    # If debug option is given, clang includes $cwd in debug info by default.
    # For such build, this flag generates reproducible obj files even we use
    # different build directory like "out/feature_a" and "out/feature_b" if
    # we build same files with same compile flag.
    # Other paths are already given in relative, no need to normalize them.
    if (is_nacl) {
      # TODO(https://crbug.com/1231236): Use -ffile-compilation-dir= here.
      cflags += [
        "-Xclang",
        "-fdebug-compilation-dir",
        "-Xclang",
        ".",
      ]
    } else {
      # -ffile-compilation-dir is an alias for both -fdebug-compilation-dir=
      # and -fcoverage-compilation-dir=.
      cflags += [ "-ffile-compilation-dir=." ]
    }
    if (!is_win) {
      # We don't use clang -cc1as on Windows (yet? https://crbug.com/762167)
      asmflags = [ "-Wa,-fdebug-compilation-dir,." ]
    }

Here we replace this compilation option to solve this problem. Specifically, the following line of code:

      cflags += [ "-ffile-compilation-dir=." ]

Replace with:

      cflags += [ "-fdebug-compilation-dir" ]

After the modification is completed, re-execute the gn genand ninjacommands.

(2). jni_generator.pyErrors caused by execution failure

Then I encountered the following compilation error:

[1109/5146] ACTION //sdk/android:generated_external_classes_jni(//build/toolchain/android:android_clang_arm64)
FAILED: gen/sdk/android/generated_external_classes_jni/Integer_jni.h gen/sdk/android/generated_external_classes_jni/Double_jni.h gen/sdk/android/generated_external_classes_jni/Long_jni.h gen/sdk/android/generated_external_classes_jni/Iterable_jni.h gen/sdk/android/generated_external_classes_jni/Iterator_jni.h gen/sdk/android/generated_external_classes_jni/Boolean_jni.h gen/sdk/android/generated_external_classes_jni/BigInteger_jni.h gen/sdk/android/generated_external_classes_jni/Map_jni.h gen/sdk/android/generated_external_classes_jni/LinkedHashMap_jni.h gen/sdk/android/generated_external_classes_jni/ArrayList_jni.h gen/sdk/android/generated_external_classes_jni/Enum_jni.h 
python3 ../../../../webrtc/base/android/jni_generator/jni_generator.py --ptr_type=long --includes ../../../../../../../../webrtc/sdk/android/src/jni/jni_generator_helper.h --jar_file ../../../../../../../Library/Android/sdk/platforms/android-31/android.jar --output_file gen/sdk/android/generated_external_classes_jni/Integer_jni.h --output_file gen/sdk/android/generated_external_classes_jni/Double_jni.h --output_file gen/sdk/android/generated_external_classes_jni/Long_jni.h --output_file gen/sdk/android/generated_external_classes_jni/Iterable_jni.h --output_file gen/sdk/android/generated_external_classes_jni/Iterator_jni.h --output_file gen/sdk/android/generated_external_classes_jni/Boolean_jni.h --output_file gen/sdk/android/generated_external_classes_jni/BigInteger_jni.h --output_file gen/sdk/android/generated_external_classes_jni/Map_jni.h --output_file gen/sdk/android/generated_external_classes_jni/LinkedHashMap_jni.h --output_file gen/sdk/android/generated_external_classes_jni/ArrayList_jni.h --output_file gen/sdk/android/generated_external_classes_jni/Enum_jni.h --input_file=java/lang/Integer.class --input_file=java/lang/Double.class --input_file=java/lang/Long.class --input_file=java/lang/Iterable.class --input_file=java/util/Iterator.class --input_file=java/lang/Boolean.class --input_file=java/math/BigInteger.class --input_file=java/util/Map.class --input_file=java/util/LinkedHashMap.class --input_file=java/util/ArrayList.class --input_file=java/lang/Enum.class
Traceback (most recent call last):
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/base/android/jni_generator/jni_generator.py", line 1630, in <module>
    sys.exit(main())
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/base/android/jni_generator/jni_generator.py", line 1624, in main
    GenerateJNIHeader(java_path, header_path, args)
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/base/android/jni_generator/jni_generator.py", line 1485, in GenerateJNIHeader
    jni_from_javap = JNIFromJavaP.CreateFromClass(input_file, options)
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/base/android/jni_generator/jni_generator.py", line 847, in CreateFromClass
    jni_from_javap = JNIFromJavaP(stdout.split('\n'), options)
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/base/android/jni_generator/jni_generator.py", line 767, in __init__
    self.fully_qualified_class = self.fully_qualified_class.replace('.', '/')
AttributeError: 'JNIFromJavaP' object has no attribute 'fully_qualified_class'
[1110/5146] CXX obj/third_party/abseil-cpp/absl/base/spinlock_wait/spinlock_wait.o
warning: unknown warning option '-Wno-unused-but-set-variable'; did you mean '-Wno-unused-const-variable'? [-Wunknown-warning-option]

This time the build system webrtc/base/android/jni_generator/jni_generator.pyencountered an error when executing the script file to generate the JNI header file. According to the error call stack information, the main relevant codes are fished out as follows:

class JNIFromJavaP(object):
  """Uses 'javap' to parse a .class file and generate the JNI header file."""

  def __init__(self, contents, options):
    self.contents = contents
    self.namespace = options.namespace
    for line in contents:
      class_name = re.match(
          '.*?(public).*?(class|interface) (?P<class_name>\S+?)( |\Z)', line)
      if class_name:
        self.fully_qualified_class = class_name.group('class_name')
        break
    self.fully_qualified_class = self.fully_qualified_class.replace('.', '/')
    # Java 7's javap includes type parameters in output, like HashSet<T>. Strip
    # away the <...> and use the raw class name that Java 6 would've given us.
. . . . . .
  @staticmethod
  def CreateFromClass(class_file, options):
    class_name = os.path.splitext(os.path.basename(class_file))[0]
    javap_path = os.path.abspath(options.javap)
    p = subprocess.Popen(
        args=[javap_path, '-c', '-verbose', '-s', class_name],
        cwd=os.path.dirname(class_file),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True)
    stdout, _ = p.communicate()
    jni_from_javap = JNIFromJavaP(stdout.split('\n'), options)
    return jni_from_javap
. . . . . .
def GenerateJNIHeader(input_file, output_file, options):
  try:
    if os.path.splitext(input_file)[1] == '.class':
      jni_from_javap = JNIFromJavaP.CreateFromClass(input_file, options)
      content = jni_from_javap.GetContent()
    else:
      jni_from_java_source = JNIFromJavaSource.CreateFromFile(
          input_file, options)
      content = jni_from_java_source.GetContent()
  except ParseError as e:
    print(e)
    sys.exit(1)
  if output_file:
    with build_utils.AtomicOutput(output_file, mode='w') as f:
      f.write(content)
  else:
    print(content)

The general meaning of the relevant code is that the method GenerateJNIHeader()is called in the function JNIFromJavaP.CreateFromClass(input_file, options); the command JNIFromJavaP.CreateFromClass(input_file, options)is executed in the method javap, the content of the standard output of the command execution is obtained, and the content is created as a parameter JNIFromJavaP, and an error occurs in the class JNIFromJavaPconstructor.

When we print the parameters JNIFromJavaPreceived by the constructor contents, we can see that this parameter is an empty string, which obviously does not meet expectations. We extract the command JNIFromJavaP.CreateFromClass(input_file, options)executed in the method javap. This command probably looks like this:

/Library/Java/JavaVirtualMachines/jdk-11.0.13.jdk/Contents/Home/bin/javap  -c  -verbose  -s  Integer 

We execute this command in the terminal command line, and an error will be reported when executing this command:

OpenRTCClient % /Library/Java/JavaVirtualMachines/jdk-11.0.13.jdk/Contents/Home/bin/javap  -c  -verbose  -s  Integer  
错误: 找不到类: Integer

Let’s take a look at javapwhat the two parameters passed to are used for:

OpenRTCClient % javap --help                                                                                                  
用法: javap <options> <classes>
其中, 可能的选项包括:
  -? -h --help -help               输出此帮助消息
  -version                         版本信息
  -v  -verbose                     输出附加信息
  -l                               输出行号和本地变量表
  -public                          仅显示公共类和成员
  -protected                       显示受保护的/公共类和成员
  -package                         显示程序包/受保护的/公共类
                                   和成员 (默认)
  -p  -private                     显示所有类和成员
  -c                               对代码进行反汇编
  -s                               输出内部类型签名
  -sysinfo                         显示正在处理的类的
                                   系统信息 (路径, 大小, 日期, MD5 散列)
  -constants                       显示最终常量
  --module <模块>, -m <模块>       指定包含要反汇编的类的模块
  --module-path <路径>             指定查找应用程序模块的位置
  --system <jdk>                   指定查找系统模块的位置
  --class-path <路径>              指定查找用户类文件的位置
  -classpath <路径>                指定查找用户类文件的位置
  -cp <路径>                       指定查找用户类文件的位置
  -bootclasspath <路径>            覆盖引导类文件的位置

GNU 样式的选项可使用 = (而非空白) 来分隔选项名称
及其值。

每个类可由其文件名, URL 或其
全限定类名指定。示例:
   path/to/MyClass.class
   jar:file:///path/to/MyJar.jar!/mypkg/MyClass.class
   java.lang.Object

-cThe parameters are used to disassemble the code and -sthe parameters are used to output the internal type signature. But the key to the error here is not the parameters, but the way the class is specified. javapThe command accepts methods for specifying classes as described at the bottom of the help output above. The way the Mac platform javapcommand accepts specified classes javapis different from the way the Linux platform command accepts it.

WebRTC's build system webrtc/base/android/jni_generator/jni_generator.pygenerates JNI header files for several standard library classes, and the class files for these classes are packaged in rt.jarfiles. We rt.jarextract all the class files from the file and execute javapthe command on the class files:

opensource % mkdir jar_classes
opensource % cd jar_classes
jar_classes % jar xf /Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home/jre/lib/rt.jar
jar_classes % cd java/lang
lang % javap -c -s Integer
错误: 找不到类: Integer
lang % javap -c -s Integer.class
Compiled from "Integer.java"
public final class java.lang.Integer extends java.lang.Number implements java.lang.Comparable<java.lang.Integer> {
  public static final int MIN_VALUE;
    descriptor: I

  public static final int MAX_VALUE;

In the directory where the class file is located, when we only specify the class by passing in the class name, javapthe execution fails. When 类名.classthe class is specified in the form, it can be executed successfully. On the Linux platform, if it is located in the directory where the class file is located, specifying the class only by passing in the class name without the .classsuffix name javapcan also be executed successfully.

For the above example Integer, when executing on the Mac platform javap, there are many correct parameter formats. It java.lang.Integercan be the complete file path of the class file, such as /var/folders/1x/5vtfxt410vbf9xhk8vvfz8l40000gn/T/tmp2gbxloem/java/lang/Integer.classthe file name of the class file Integer.class, but it cannot be Integer.

From this, we can get our solution to this problem.

javapOption 1, specify the class through the complete file path of the class file , and modify JNIFromJavaP.CreateFromClass(input_file, options)the implementation of the method as:

  @staticmethod
  def CreateFromClass(class_file, options):
    if sys.platform == "darwin":
      class_name = class_file
    else:
      class_name = os.path.splitext(os.path.basename(class_file))[0]

    javap_path = os.path.abspath(options.javap)
    p = subprocess.Popen(
        args=[javap_path, '-c', '-verbose', '-s', class_name],
        cwd=os.path.dirname(class_file),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True)
    stdout, _ = p.communicate()
    jni_from_javap = JNIFromJavaP(stdout.split('\n'), options)
    return jni_from_javap

Option two, since the working directory is set when the process is created to execute the command, we can also specify javapthe class through the file name of the class file. The implementation of this modified JNIFromJavaP.CreateFromClass(input_file, options)method is:

  @staticmethod
  def CreateFromClass(class_file, options):
    if sys.platform == "darwin":
      class_name = os.path.basename(class_file)
    else:
      class_name = os.path.splitext(os.path.basename(class_file))[0]

    javap_path = os.path.abspath(options.javap)
    p = subprocess.Popen(
        args=[javap_path, '-c', '-verbose', '-s', class_name],
        cwd=os.path.dirname(class_file),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True)
    stdout, _ = p.communicate()
    jni_from_javap = JNIFromJavaP(stdout.split('\n'), options)
    return jni_from_javap

Option three is to specify a class through the class path javap. The implementation of this modified JNIFromJavaP.CreateFromClass(input_file, options)method is:

  @staticmethod
  def CreateFromClass(class_file, options):
    if sys.platform == "darwin":
      path_items = class_file.split("/")
      i = len(path_items) - 2
      while i >= 0:
        class_name = path_items[i] + "." + class_name
        if path_items[i] == "java":
          break
        i = i -1
    else:
      class_name = os.path.splitext(os.path.basename(class_file))[0]

    javap_path = os.path.abspath(options.javap)
    p = subprocess.Popen(
        args=[javap_path, '-c', '-verbose', '-s', class_name],
        cwd=os.path.dirname(class_file),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True)
    stdout, _ = p.communicate()
    jni_from_javap = JNIFromJavaP(stdout.split('\n'), options)
    return jni_from_javap

This implementation of Option 3 has certain restrictions on the classes to be generated JNI.

Relatively speaking, all things considered, option 2 is undoubtedly the best.

(3). Compilation errors caused by missing Android SDK tools or version issues

Execute it again ninjaand encounter the following compilation error:

OpenRTCClient % mv  ~/Library/Android/sdk/cmdline-tools/latest  ~/Library/Android/sdk/cmdline-tools/latest_bak
OpenRTCClient % webrtc_build build android arm64 debug                                                        
/Users/lisi/Projects/opensource/OpenRTCClient/build_system/tools/bin/mac/ninja -C /Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug   
ninja: Entering directory `/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug'
[355/4574] ACTION //examples:AppRTCMobile_test_apk__test_apk__merge_manifests(//build/toolchain/android:android_clang_arm64)
FAILED: gen/examples/AppRTCMobile_test_apk__test_apk_manifest/AndroidManifest.xml 
python3 ../../../../webrtc/build/android/gyp/merge_manifest.py --depfile gen/examples/AppRTCMobile_test_apk__test_apk__merge_manifests.d --android-sdk-cmdline-tools ../../../../../../../Library/Android/sdk/cmdline-tools/latest --root-manifest ../../../../webrtc/examples/androidtests/AndroidManifest.xml --output gen/examples/AppRTCMobile_test_apk__test_apk_manifest/AndroidManifest.xml --extras @FileArg\(gen/examples/AppRTCMobile_test_apk__test_apk.build_config.json:extra_android_manifests\) --min-sdk-version=21 --target-sdk-version=21
Traceback (most recent call last):
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/android/gyp/merge_manifest.py", line 149, in <module>
    main(sys.argv[1:])
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/android/gyp/merge_manifest.py", line 129, in main
    build_utils.CheckOutput(
  File "/Users/lisi/Projects/opensource/OpenRTCClient/webrtc/build/android/gyp/util/build_utils.py", line 276, in CheckOutput
    raise CalledProcessError(cwd, args, stdout + stderr)
util.build_utils.CalledProcessError: Command failed: ( cd /Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug; /Library/Java/JavaVirtualMachines/jdk-11.0.13.jdk/Contents/Home/bin/java -Xmx1G -noverify -cp ../../../../../../../Library/Android/sdk/cmdline-tools/latest/lib/build-system/manifest-merger.jar:../../../../../../../Library/Android/sdk/cmdline-tools/latest/lib/common/common.jar:../../../../../../../Library/Android/sdk/cmdline-tools/latest/lib/sdk-common/sdk-common.jar:../../../../../../../Library/Android/sdk/cmdline-tools/latest/lib/sdklib/sdklib.jar:../../../../../../../Library/Android/sdk/cmdline-tools/latest/lib/external/com/google/guava/guava/30.1-jre/guava-30.1-jre.jar:../../../../../../../Library/Android/sdk/cmdline-tools/latest/lib/external/kotlin-plugin-ij/Kotlin/kotlinc/lib/kotlin-stdlib.jar:../../../../../../../Library/Android/sdk/cmdline-tools/latest/lib/external/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar com.android.manifmerger.Merger --out /Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/gen/examples/AppRTCMobile_test_apk__test_apk_manifest/tmpvg3qg_k3AndroidManifest.xml --property MIN_SDK_VERSION=21 --property TARGET_SDK_VERSION=21 --libs gen/third_party/android_sdk/android_test_base_java/AndroidManifest.xml:gen/third_party/android_sdk/android_test_runner_java/AndroidManifest.xml --main /var/folders/1x/5vtfxt410vbf9xhk8vvfz8l40000gn/T/AndroidManifest.xmlwu610lv1 --property PACKAGE=org.appspot.apprtc.test --remove-tools-declarations )
错误: 找不到或无法加载主类 com.android.manifmerger.Merger
原因: java.lang.ClassNotFoundException: com.android.manifmerger.Merger

This error is reported because compiling Android needs to generate some test APK files. At this time, some Java tools in the Android SDK need to be executed. Here it is prompted that the main class cannot be found, which is defined com.android.manifmerger.Mergerin sdk/cmdline-tools/latest/lib/build-system/manifest-merger.jarthis jar file, but in our SDK, There is no sdk/cmdline-tools/latest/such directory.

It is not difficult to see sdk/cmdline-tools/latest/that the latest version should be quoted cmdline-tools, but in our SDK package, only 3.0version is installed.

From this, there are many solutions to solve this problem.

Option one, create a symbolic link sdk/cmdline-tools/latestpointing to sdk/cmdline-tools/3.0, such as:

tmp % ln -s ~/Library/Android/sdk/cmdline-tools/3.0  ~/Library/Android/sdk/cmdline-tools/lastest

Option two, install the latest version cmdline-tools, which can be done through Android Studio or through the command line tools provided by the Android SDK, such as:

~/Library/Android/sdk/tools/bin/sdkmanager --install "cmdline-tools;latest"

If you find that you have installed the latest version cmdline-toolsand still cannot find the main class com.android.manifmerger.Merger, you can check to see cmdline-toolsif there is ~/Library/Android/sdk/cmdline-tools/latest/lib/build-system/manifest-merger.jarthis jar file in:

OpenRTCClient % ls -l ~/Library/Android/sdk/cmdline-tools/latest/lib/build-system/ 
total 424
drwxr-xr-x  3 lisi  staff      96  4 11 14:21 builder-model
drwxr-xr-x  3 lisi  staff      96  4 11 14:21 builder-test-api
-rwxr-xr-x  1 lisi  staff  213592  4 11 14:21 tools.manifest-merger.jar

If this is the case, you can copy it tools.manifest-merger.jaror create a symbolic link to it, such as:

OpenRTCClient % cp ~/Library/Android/sdk/cmdline-tools/latest/lib/build-system/tools.manifest-merger.jar ~/Library/Android/sdk/cmdline-tools/latest/lib/build-system/manifest-merger.jar

In the error message above, we can see that multiple jar files are referenced. For each jar file, we need to ensure their existence in a similar way.

Option three is to modify the build configuration of WebRTC.
The error reported here is reported when executing webrtc/build/config/android/internal_rules.gnithe defined in , and the path is defined here, such as:template("merge_manifests")cmdline-tools

  template("merge_manifests") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ])
      script = "//build/android/gyp/merge_manifest.py"
      depfile = "$target_gen_dir/$target_name.d"

      inputs = [
        invoker.build_config,
        invoker.input_manifest,
      ]

      outputs = [ invoker.output_manifest ]
      _rebased_build_config = rebase_path(invoker.build_config, root_build_dir)

      args = [
        "--depfile",
        rebase_path(depfile, root_build_dir),
        "--android-sdk-cmdline-tools",
        rebase_path("${android_sdk_root}/cmdline-tools/latest",
                    root_build_dir),
        "--root-manifest",
        rebase_path(invoker.input_manifest, root_build_dir),
        "--output",
        rebase_path(invoker.output_manifest, root_build_dir),
        "--extras",
        "@FileArg($_rebased_build_config:extra_android_manifests)",
        "--min-sdk-version=${invoker.min_sdk_version}",
        "--target-sdk-version=${invoker.target_sdk_version}",
      ]

You can change the path here cmdline-toolsto the path of the version we have installed locally.

(4). Clang lacks the libraries or tools of the Android NDK package, causing compilation to fail.

Execute it again ninjaand encounter the following compilation error:

OpenRTCClient % webrtc_build build android arm64 debug
/Users/lisi/Projects/opensource/OpenRTCClient/build_system/tools/bin/mac/ninja -C /Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug   
ninja: Entering directory `/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug'
[14/1093] LINK ./stun_prober
FAILED: stun_prober exe.unstripped/stun_prober 
python3 "../../../../webrtc/build/toolchain/gcc_link_wrapper.py" --output="./stun_prober" --strip="../../../../build_system/llvm-build/mac/mac/Release+Asserts/bin/llvm-strip" --unstripped-file="./exe.unstripped/stun_prober" -- ../../../../build_system/llvm-build/mac/mac/Release+Asserts/bin/clang++ -fuse-ld=lld -Wl,--fatal-warnings -Wl,--build-id -fPIC -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,-z,max-page-size=4096 -Wl,--color-diagnostics -Wl,--no-rosegment -Wl,--no-call-graph-profile-sort -Wl,--exclude-libs=libvpx_assembly_arm.a --unwindlib=none --target=aarch64-linux-android21 -Wl,-mllvm,-enable-machine-outliner=never -no-canonical-prefixes -Wl,--gc-sections -Wl,--gdb-index --sysroot=../../../../../../../Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -Wl,--warn-shared-textrel -Wl,-z,defs -Wl,--as-needed -pie -Bdynamic -Wl,-z,nocopyreloc -Wl,--dynamic-linker,/system/bin/linker64 -o "./exe.unstripped/stun_prober" -Wl,--start-group @"./stun_prober.rsp"  -Wl,--end-group  -ldl -lm -llog -lGLESv2 -lOpenSLES
ld.lld: error: cannot open ../../../../build_system/llvm-build/mac/mac/Release+Asserts/lib/clang/14.0.0/lib/linux/libclang_rt.builtins-aarch64-android.a: No such file or directory
ld.lld: error: cannot open ../../../../build_system/llvm-build/mac/mac/Release+Asserts/lib/clang/14.0.0/lib/linux/libclang_rt.builtins-aarch64-android.a: No such file or directory
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

This is due to the lack of some library files required to compile and link Android binaries in the LLVM toolchain in webrtc. This can be solved by copying the library files in the NDK to the corresponding directory of the LLVM tool chain, such as:

android-ndk-r23b-darwin % cp -r  toolchains/llvm/prebuilt/darwin-x86_64//lib64/clang/12.0.8/lib/linux  ~/Projects/opensource/OpenRTCClient/build_system/llvm-build/mac/mac/Release+Asserts/lib/clang/14.0.0/lib/

Execute it again ninjaand encounter the following compilation error:

OpenRTCClient % webrtc_build build android arm64 debug
/Users/lisi/Projects/opensource/OpenRTCClient/build_system/tools/bin/mac/ninja -C /Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug   
ninja: Entering directory `/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug'
[33/880] LINK ./stun_prober
FAILED: stun_prober exe.unstripped/stun_prober 
python3 "../../../../webrtc/build/toolchain/gcc_link_wrapper.py" --output="./stun_prober" --strip="../../../../build_system/llvm-build/mac/mac/Release+Asserts/bin/llvm-strip" --unstripped-file="./exe.unstripped/stun_prober" -- ../../../../build_system/llvm-build/mac/mac/Release+Asserts/bin/clang++ -fuse-ld=lld -Wl,--fatal-warnings -Wl,--build-id -fPIC -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,-z,max-page-size=4096 -Wl,--color-diagnostics -Wl,--no-rosegment -Wl,--no-call-graph-profile-sort -Wl,--exclude-libs=libvpx_assembly_arm.a --unwindlib=none --target=aarch64-linux-android21 -Wl,-mllvm,-enable-machine-outliner=never -no-canonical-prefixes -Wl,--gc-sections -Wl,--gdb-index --sysroot=../../../../../../../Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -Wl,--warn-shared-textrel -Wl,-z,defs -Wl,--as-needed -pie -Bdynamic -Wl,-z,nocopyreloc -Wl,--dynamic-linker,/system/bin/linker64 -o "./exe.unstripped/stun_prober" -Wl,--start-group @"./stun_prober.rsp"  -Wl,--end-group  -ldl -lm -llog -lGLESv2 -lOpenSLES
Traceback (most recent call last):
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/toolchain/gcc_link_wrapper.py", line 91, in <module>
    sys.exit(main())
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/toolchain/gcc_link_wrapper.py", line 78, in main
    result = subprocess.call(
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/subprocess.py", line 349, in call
    with Popen(*popenargs, **kwargs) as p:
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/subprocess.py", line 951, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/subprocess.py", line 1821, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: '../../../../build_system/llvm-build/mac/mac/Release+Asserts/bin/llvm-strip'

This error means that when linking, the LLVM tool chain cannot be found llvm-strip.

Similarly, we copy the tools under the NDK and also copy the dependent libraries:

android-ndk-r23b-darwin % cp toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip /Users/lisi/Projects/opensource/OpenRTCClient/build_system/llvm-build/mac/mac/Release+Asserts/bin/
android-ndk-r23b-darwin % cp -r toolchains/llvm/prebuilt/darwin-x86_64/lib64 /Users/lisi/Projects/opensource/OpenRTCClient/build_system/llvm-build/mac/mac/Release+Asserts/

To do the same thing there are llvm-nmtools:

android-ndk-r23b-darwin % cp toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm /Users/lisi/Projects/opensource/OpenRTCClient/build_system/llvm-build/mac/mac/Release+Asserts/bin/
(5). Compilation failure caused by incorrect Unix domain Socket address

Execute it again ninjaand encounter the following compilation error:

OpenRTCClient % webrtc_build build android arm64 debug                              
/Users/lisi/Projects/opensource/OpenRTCClient/build_system/tools/bin/mac/ninja -C /Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug   
ninja: Entering directory `/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug'
[7/744] ACTION //sdk/android:base_java__errorprone(//build/toolchain/android:android_clang_arm64)
FAILED: obj/sdk/android/base_java__errorprone.errorprone.stamp 
python3 ../../../../webrtc/build/android/gyp/compile_java.py --depfile=gen/sdk/android/base_java__errorprone.d --generated-dir=gen/sdk/android/base_java/generated_java --jar-path=obj/sdk/android/base_java__errorprone.errorprone.stamp --java-srcjars=\[\"gen/sdk/android/base_java.generated.srcjar\"\] --target-name //sdk/android:base_java__errorprone --header-jar obj/sdk/android/base_java.turbine.jar --classpath=\[\"obj/sdk/android/base_java.turbine.jar\"\] --classpath=@FileArg\(gen/sdk/android/base_java.build_config.json:deps_info:javac_full_interface_classpath\) --java-version=1.8 --bootclasspath=@FileArg\(gen/sdk/android/base_java.build_config.json:android:sdk_interface_jars\) --chromium-code=1 --jar-info-exclude-globs=\[\"\*/R.class\",\ \"\*/R\\\$\*.class\",\ \"\*/Manifest.class\",\ \"\*/Manifest\\\$\*.class\",\ \"\*/GEN_JNI.class\"\] --processorpath=@FileArg\(gen/tools/android/errorprone_plugin/errorprone_plugin.build_config.json:deps_info:host_classpath\) --enable-errorprone @gen/sdk/android/base_java.sources --javac-arg=-Werror
Traceback (most recent call last):
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/android/gyp/compile_java.py", line 800, in <module>
    sys.exit(main(sys.argv[1:]))
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/android/gyp/compile_java.py", line 693, in main
    and server_utils.MaybeRunCommand(name=options.target_name,
  File "/Users/lisi/Projects/opensource/OpenRTCClient/webrtc/build/android/gyp/util/server_utils.py", line 40, in MaybeRunCommand
    raise e
  File "/Users/lisi/Projects/opensource/OpenRTCClient/webrtc/build/android/gyp/util/server_utils.py", line 27, in MaybeRunCommand
    sock.connect(SOCKET_ADDRESS)
FileNotFoundError: [Errno 2] No such file or directory

In webrtc/build/android/gyp/util/server_utils.pythe file we can see SOCKET_ADDRESSthe definition of :

SOCKET_ADDRESS = '\0chromium_build_server_socket'

The leading '\0' causes the creation of the unix domain socket on Mac to fail and sets it to a path in the temporary directory, such as:

SOCKET_ADDRESS = '/tmp/chromium_build_server_socket'

At the same time, the server side of the Unix domain socket is also run, such as:

OpenRTCClient % python3 webrtc/build/android/fast_local_dev_server.py
(6). Failed to compile resources

Execute it again ninjaand encounter the following compilation error:

[20/692] ACTION //examples:AppRTCMobile__compile_resources(//build/toolchain/android:android_clang_arm64)
FAILED: gen/examples/AppRTCMobile__compile_resources.srcjar obj/examples/AppRTCMobile.ap_ obj/examples/AppRTCMobile.ap_.info gen/examples/AppRTCMobile__compile_resources_R.txt obj/examples/AppRTCMobile/AppRTCMobile.resources.proguard.txt gen/examples/AppRTCMobile__compile_resources.resource_ids 
python3 ../../../../webrtc/build/android/gyp/compile_resources.py --include-resources=@FileArg\(gen/examples/AppRTCMobile.build_config.json:android:sdk_jars\) --aapt2-path ../../../../webrtc/third_party/android_build_tools/aapt2/aapt2 --dependencies-res-zips=@FileArg\(gen/examples/AppRTCMobile.build_config.json:deps_info:dependency_zips\) --extra-res-packages=@FileArg\(gen/examples/AppRTCMobile.build_config.json:deps_info:extra_package_names\) --extra-main-r-text-files=@FileArg\(gen/examples/AppRTCMobile.build_config.json:deps_info:extra_main_r_text_files\) --min-sdk-version=21 --target-sdk-version=29 --webp-cache-dir=obj/android-webp-cache --android-manifest gen/examples/AppRTCMobile_manifest/AndroidManifest.xml --srcjar-out gen/examples/AppRTCMobile__compile_resources.srcjar --version-code 1 --version-name Developer\ Build --arsc-path obj/examples/AppRTCMobile.ap_ --info-path obj/examples/AppRTCMobile.ap_.info --debuggable --r-text-out gen/examples/AppRTCMobile__compile_resources_R.txt --dependencies-res-zip-overlays=@FileArg\(gen/examples/AppRTCMobile.build_config.json:deps_info:dependency_zips\) --proguard-file obj/examples/AppRTCMobile/AppRTCMobile.resources.proguard.txt --emit-ids-out=gen/examples/AppRTCMobile__compile_resources.resource_ids --depfile gen/examples/AppRTCMobile__compile_resources.d
E 3273   2236 Subprocess raised an exception:
Traceback (most recent call last):
  File "/Users/lisi/Projects/opensource/OpenRTCClient/webrtc/build/android/gyp/util/parallel.py", line 75, in __call__
    return self._func(*_fork_params[index], **_fork_kwargs)
TypeError: 'NoneType' object is not subscriptable

Here we solve this problem by turning off concurrent compilation of resource compilation. Specifically, you can modify webrtc/build/android/gyp/util/parallel.pythis file, set the in the file DISABLE_ASYNCto True, or export environment variables export DISABLE_ASYNC=1.

(7). Aapt executable file format error causes compilation failure

Execute it again ninjaand encounter the following compilation error:

[36/579] ACTION //examples:AppRTCMobile__compile_resources(//build/toolchain/android:android_clang_arm64)
FAILED: gen/examples/AppRTCMobile__compile_resources.srcjar obj/examples/AppRTCMobile.ap_ obj/examples/AppRTCMobile.ap_.info gen/examples/AppRTCMobile__compile_resources_R.txt obj/examples/AppRTCMobile/AppRTCMobile.resources.proguard.txt gen/examples/AppRTCMobile__compile_resources.resource_ids 
python3 ../../../../webrtc/build/android/gyp/compile_resources.py --include-resources=@FileArg\(gen/examples/AppRTCMobile.build_config.json:android:sdk_jars\) --aapt2-path ../../../../webrtc/third_party/android_build_tools/aapt2/aapt2 --dependencies-res-zips=@FileArg\(gen/examples/AppRTCMobile.build_config.json:deps_info:dependency_zips\) --extra-res-packages=@FileArg\(gen/examples/AppRTCMobile.build_config.json:deps_info:extra_package_names\) --extra-main-r-text-files=@FileArg\(gen/examples/AppRTCMobile.build_config.json:deps_info:extra_main_r_text_files\) --min-sdk-version=21 --target-sdk-version=29 --webp-cache-dir=obj/android-webp-cache --android-manifest gen/examples/AppRTCMobile_manifest/AndroidManifest.xml --srcjar-out gen/examples/AppRTCMobile__compile_resources.srcjar --version-code 1 --version-name Developer\ Build --arsc-path obj/examples/AppRTCMobile.ap_ --info-path obj/examples/AppRTCMobile.ap_.info --debuggable --r-text-out gen/examples/AppRTCMobile__compile_resources_R.txt --dependencies-res-zip-overlays=@FileArg\(gen/examples/AppRTCMobile.build_config.json:deps_info:dependency_zips\) --proguard-file obj/examples/AppRTCMobile/AppRTCMobile.resources.proguard.txt --emit-ids-out=gen/examples/AppRTCMobile__compile_resources.resource_ids --depfile gen/examples/AppRTCMobile__compile_resources.d
WARNING:root:Running in synchronous mode.
Traceback (most recent call last):
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/android/gyp/compile_resources.py", line 1039, in <module>
    main(sys.argv[1:])
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/android/gyp/compile_resources.py", line 956, in main
    manifest_package_name = _PackageApk(options, build)
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/android/gyp/compile_resources.py", line 759, in _PackageApk
    partials = _CompileDeps(options.aapt2_path, dep_subdirs,
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/android/gyp/compile_resources.py", line 619, in _CompileDeps
    partials = lisi(
  File "/Users/lisi/Projects/opensource/OpenRTCClient/webrtc/build/android/gyp/util/parallel.py", line 207, in BulkForkAndCall
    yield func(*args, **kwargs)
  File "/Users/lisi/Projects/opensource/OpenRTCClient/build/android/arm64/debug/../../../../webrtc/build/android/gyp/compile_resources.py", line 583, in _CompileSingleDep
    build_utils.CheckOutput(
  File "/Users/lisi/Projects/opensource/OpenRTCClient/webrtc/build/android/gyp/util/build_utils.py", line 260, in CheckOutput
    child = subprocess.Popen(args,
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/subprocess.py", line 951, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/subprocess.py", line 1821, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 8] Exec format error: '../../../../webrtc/third_party/android_build_tools/aapt2/aapt2'

This is because webrtc/third_party/android_build_tools/aapt2/aapt2the file is actually an executable file for the Linux platform.

The template for compiling resources is webrtc/build/config/android/internal_rules.gnidefined in:

  template("compile_resources") {
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

    _deps = [
      invoker.android_sdk_dep,
      invoker.build_config_dep,
    ]
    if (defined(invoker.android_manifest_dep)) {
      _deps += [ invoker.android_manifest_dep ]
    }
    foreach(_dep, invoker.deps) {
      _target_label = get_label_info(_dep, "label_no_toolchain")
      if (filter_exclude([ _target_label ], _java_library_patterns) == [] &&
          filter_exclude([ _target_label ], _java_resource_patterns) != []) {
        # Depend on the java libraries' transitive __assetres target instead.
        _deps += [ "${_target_label}__assetres" ]
      } else {
        _deps += [ _dep ]
      }
    }

    if (defined(invoker.arsc_output)) {
      _arsc_output = invoker.arsc_output
    }
    _final_srcjar_path = "${target_gen_dir}/${target_name}.srcjar"

    _script = "//build/android/gyp/compile_resources.py"

    _inputs = [
      invoker.build_config,
      android_sdk_tools_bundle_aapt2,
    ]

    _rebased_build_config = rebase_path(invoker.build_config, root_build_dir)

    _args = [
      "--include-resources=@FileArg($_rebased_build_config:android:sdk_jars)",
      "--aapt2-path",
      rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir),
      "--dependencies-res-zips=@FileArg($_rebased_build_config:deps_info:dependency_zips)",
      "--extra-res-packages=@FileArg($_rebased_build_config:deps_info:extra_package_names)",
      "--extra-main-r-text-files=@FileArg($_rebased_build_config:deps_info:extra_main_r_text_files)",
      "--min-sdk-version=${invoker.min_sdk_version}",
      "--target-sdk-version=${invoker.target_sdk_version}",
      "--webp-cache-dir=obj/android-webp-cache",
    ]

The script file will be called webrtc/build/android/gyp/compile_resources.pyand the path of aapt2 will be passed in as one of the parameters. You can see that the path of aapt2 referenced here is android_sdk_tools_bundle_aapt2. android_sdk_tools_bundle_aapt2is a compilation configuration item, which is defined in webrtc/build/config/android/config.gni. This configuration item has a default value:

    android_sdk_tools_bundle_aapt2_dir =
        "//third_party/android_build_tools/aapt2"
 . . . . . .
  android_sdk_tools_bundle_aapt2 = "${android_sdk_tools_bundle_aapt2_dir}/aapt2"

We can solve this problem by args.gncustomizing android_sdk_tools_bundle_aapt2_dirthis configuration item in . Specifically, this configuration item needs to be set to the path of the build-tools we selected in the Android SDK, as follows:

android_sdk_tools_bundle_aapt2_dir = "/Users/lisi/Library/Android/sdk/build-tools/30.0.1"

Execute it again ninja, and each required file can be compiled correctly.

The author built a warehouse on GitHub, which contains the complete code and build system of WebRTC, including the source code of WebRTC and the third-party libraries it relies on, various tools required for compilation, etc., mainly for the m98 version of WebRTC. The entire build environment is at OpenRTCClient . Friends in need can refer to it.

Done.

Guess you like

Origin blog.csdn.net/tq08g2z/article/details/124110454
Recommended