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.gn
file
args.gn
Make 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 gen
Generate build configuration file
Generate the configuration files required for the build by gn gen
based on the created args.gn
files, individual BUILD.gn
and *.gni
build configuration files . ninja
Assuming args.gn
the file is located build/android/arm64/debug
in 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.gn
the 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 if
judgment 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.gn
The 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 ninja
the command to build WebRTC
(1). -ffile-compilation-dir=.
Compilation errors caused by
Execute ninja
the 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 clang
a 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 clang
newer versions. However , the version used for local compilation is not new enough, so the compilation tool appears. Unable to recognize compilation options.clang
clang
This compilation option is webrtc/build/config/compiler/BUILD.gn
added 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 gen
and ninja
commands.
(2). jni_generator.py
Errors 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.py
encountered 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 JNIFromJavaP
constructor.
When we print the parameters JNIFromJavaP
received 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 javap
what 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
-c
The parameters are used to disassemble the code and -s
the 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. javap
The command accepts methods for specifying classes as described at the bottom of the help output above. The way the Mac platform javap
command accepts specified classes javap
is different from the way the Linux platform command accepts it.
WebRTC's build system webrtc/base/android/jni_generator/jni_generator.py
generates JNI header files for several standard library classes, and the class files for these classes are packaged in rt.jar
files. We rt.jar
extract all the class files from the file and execute javap
the 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, javap
the execution fails. When 类名.class
the 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 .class
suffix name javap
can 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.Integer
can be the complete file path of the class file, such as /var/folders/1x/5vtfxt410vbf9xhk8vvfz8l40000gn/T/tmp2gbxloem/java/lang/Integer.class
the file name of the class file Integer.class
, but it cannot be Integer
.
From this, we can get our solution to this problem.
javap
Option 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 javap
the 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 ninja
and 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.Merger
in sdk/cmdline-tools/latest/lib/build-system/manifest-merger.jar
this 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.0
version is installed.
From this, there are many solutions to solve this problem.
Option one, create a symbolic link sdk/cmdline-tools/latest
pointing 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-tools
and still cannot find the main class com.android.manifmerger.Merger
, you can check to see cmdline-tools
if there is ~/Library/Android/sdk/cmdline-tools/latest/lib/build-system/manifest-merger.jar
this 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.jar
or 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.gni
the 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-tools
to 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 ninja
and 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 ninja
and 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-nm
tools:
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 ninja
and 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.py
the file we can see SOCKET_ADDRESS
the 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 ninja
and 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.py
this file, set the in the file DISABLE_ASYNC
to True
, or export environment variables export DISABLE_ASYNC=1
.
(7). Aapt executable file format error causes compilation failure
Execute it again ninja
and 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/aapt2
the file is actually an executable file for the Linux platform.
The template for compiling resources is webrtc/build/config/android/internal_rules.gni
defined 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.py
and 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_aapt2
is 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.gn
customizing android_sdk_tools_bundle_aapt2_dir
this 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.