前言
最近,多位同事在 Mac 端编译 Android 平台的 WebRTC(m84版本)的时遇到了编译错误:
FAILED: clang_x64/obj/third_party/ijar/ijar/ijar.o
../../third_party/llvm-build/Release+Asserts/bin/clang++ -MMD -MF clang_x64/obj/third_party/ijar/ijar/ijar.o.d -D_LIBCPP_HAS_NO_ALIGNED_ALLOCATION -DCR_XCODE_VERSION=1250 -DCR_CLANG_REVISION=\"n353803-99ac9ce7-1\" -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FORTIFY_SOURCE=2 -D__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0 -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -I../.. -Iclang_x64/gen -I../../third_party/zlib -fno-strict-aliasing -fstack-protector -fcolor-diagnostics -fmerge-all-constants -fcrash-diagnostics-dir=../../tools/clang/crashreports -Xclang -mllvm -Xclang -instcombine-lower-dbg-declare=0 -arch x86_64 -Wno-builtin-macro-redefined -D__DATE__= -D__TIME__= -D__TIMESTAMP__= -Xclang -fdebug-compilation-dir -Xclang . -no-canonical-prefixes -Wall -Werror -Wextra -Wimplicit-fallthrough -Wunreachable-code -Wthread-safety -Wunguarded-availability -Wno-missing-field-initializers -Wno-unused-parameter -Wno-c++11-narrowing -Wno-unneeded-internal-declaration -Wno-unused-private-field -Wno-unused-variable -Wno-undefined-var-template -Wno-ignored-pragma-optimize -Wno-implicit-int-float-conversion -Wno-final-dtor-non-final-class -Wno-builtin-assume-aligned-alignment -Wno-deprecated-copy -Wno-non-c-typedef-for-linkage -O2 -fno-omit-frame-pointer -gdwarf-4 -g2 -Xclang -debug-info-kind=constructor -isysroot ../../../../../../../../../../../Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -mmacosx-version-min=10.10.0 -ftrivial-auto-var-init=pattern -fvisibility=hidden -Xclang -add-plugin -Xclang find-bad-constructs -Wheader-hygiene -Wstring-conversion -Wtautological-overlap-compare -std=c++14 -stdlib=libc++ -fno-exceptions -fvisibility-inlines-hidden -c ../../third_party/ijar/ijar.cc -o clang_x64/obj/third_party/ijar/ijar/ijar.o
In file included from ../../third_party/ijar/ijar.cc:21:
../../third_party/llvm-build/Release+Asserts/bin/../include/c++/v1/stdlib.h:142:34: error: unknown type name 'ldiv_t'
inline _LIBCPP_INLINE_VISIBILITY ldiv_t div(long __x, long __y) _NOEXCEPT {
^
../../third_party/llvm-build/Release+Asserts/bin/../include/c++/v1/stdlib.h:143:12: error: no member named 'ldiv' in the global namespace
return ::ldiv(__x, __y);
~~^
../../third_party/llvm-build/Release+Asserts/bin/../include/c++/v1/stdlib.h:146:34: error: unknown type name 'lldiv_t'
inline _LIBCPP_INLINE_VISIBILITY lldiv_t div(long long __x,
...
../../third_party/llvm-build/Release+Asserts/bin/../include/c++/v1/wchar.h:157:93: error: cannot initialize a parameter of type 'wchar_t *' with an lvalue of type 'const wchar_t *'
wchar_t* __libcpp_wcsstr(const wchar_t* __s1, const wchar_t* __s2) {return (wchar_t*)wcsstr(__s1, __s2);}
^~~~
../../third_party/llvm-build/Release+Asserts/bin/../include/c++/v1/wchar.h:140:38: note: passing argument to parameter '__s' here
wchar_t* wcschr( wchar_t* __s, wchar_t __c) {return __libcpp_wcschr(__s, __c);}
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
ninja: build stopped: subcommand failed.
WebRTC的Android平台编译需要用 mac 工具链编译 ijar 可执行文件,用于将java文件打包成 jar或将jar库进行拆解。经过对比判断,同事升级了Xcode 12.5(clang-1205.0.22.9),而我本机仍是 Xcode 12.4(clang-1200.0.32.29),WebRTC m84的工具链llvm-build(clang 11.0.0)。在同事把头文件目录 third_party/llvm-build/Release+Asserts/bin/…/include 重命名 include_bk后,编译通过,可以基本确定是工具链问题导致,毕竟众所周知,苹果的Xcode升级经常会有各种兼容问题。但该方法经验证,在 Xcode 12.4 环境会编译失败,即该解决方法并不能通用,需要查找新的解决方法。
所以,便有了以下两个预案:
-
- 弃用 llvm-build 工具链,改用 macos 系统的工具链;
-
- 升级 WebRTC 的llvm-build工具链。
接下来,我们一一尝试。
1 更改工具链
经过对编译脚本的分析,修改了以下几个文件,将 WebRTC m84的工具链从 llvm-build 切换到系统的 clang 工具链:
diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn
old mode 100644
new mode 100755
index 960726e1e5..30df135499
--- a/build/config/clang/BUILD.gn
+++ b/build/config/clang/BUILD.gn
@@ -10,12 +10,12 @@ config("find_bad_constructs") {
# The plugin is built directly into clang, so there's no need to load it
# dynamically.
- cflags += [
- "-Xclang",
- "-add-plugin",
- "-Xclang",
- "find-bad-constructs",
- ]
+ # cflags += [
+ # "-Xclang",
+ # "-add-plugin",
+ # "-Xclang",
+ # "find-bad-constructs",
+ # ]
if (is_linux || is_android || is_fuchsia) {
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
old mode 100644
new mode 100755
index d166b82928..4c2cc7443d
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1114,22 +1114,22 @@ config("compiler_deterministic") {
config("clang_revision") {
if (is_clang && clang_base_path == default_clang_base_path) {
- update_args = [
- "--print-revision",
- "--verify-version=$clang_version",
- ]
- if (llvm_force_head_revision) {
- update_args += [ "--llvm-force-head-revision" ]
- }
- clang_revision = exec_script("//tools/clang/scripts/update.py",
- update_args,
- "trim string")
+ # update_args = [
+ # "--print-revision",
+ # "--verify-version=$clang_version",
+ # ]
+ # if (llvm_force_head_revision) {
+ # update_args += [ "--llvm-force-head-revision" ]
+ # }
+ # clang_revision = exec_script("//tools/clang/scripts/update.py",
+ # update_args,
+ # "trim string")
# This is here so that all files get recompiled after a clang roll and
# when turning clang on or off. (defines are passed via the command line,
# and build system rebuild things when their commandline changes). Nothing
# should ever read this define.
- defines = [ "CR_CLANG_REVISION=\"$clang_revision\"" ]
+ # defines = [ "CR_CLANG_REVISION=\"$clang_revision\"" ]
}
}
@@ -1441,6 +1441,7 @@ config("default_warnings") {
cflags += [
# TODO(thakis): Consider -Wloop-analysis (turns on
# -Wrange-loop-analysis too).
+ "-Wno-range-loop-analysis",
# This warns on using ints as initializers for floats in
# initializer lists (e.g. |int a = f(); CGSize s = { a, a };|),
@@ -1456,6 +1457,7 @@ config("default_warnings") {
# add by vinton.liu on 20210226
"-Wno-unused-private-field",
"-Wno-unused-variable",
+ "-Wno-unknown-warning-option",
]
# use_xcode_clang only refers to the iOS toolchain, host binaries use
@@ -2287,10 +2289,10 @@ config("symbols") {
}
if (is_clang && !is_nacl && !use_xcode_clang) {
- cflags += [
- "-Xclang",
- "-debug-info-kind=constructor",
- ]
+ # cflags += [
+ # "-Xclang",
+ # "-debug-info-kind=constructor",
+ # ]
}
if (use_debug_fission && !is_nacl && !is_android) {
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
old mode 100644
new mode 100755
index add57c71bb..46c82968bf
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -92,6 +92,7 @@ template("mac_toolchain") {
prefix = rebase_path("$clang_base_path/bin/", root_build_dir)
}
+ prefix = ""
_cc = "${prefix}clang"
_cxx = "${prefix}clang++"
经修改后编译验证,android 及 mac 平台代码都可以正常编译通过。
2 更新工具链
WebRTC 提供了一个可以自行下载并编译llvm-build的脚本(tools/clang/scripts/build.py),但这个脚本是会随WebRTC的版本不断更新的,这个脚本所在目录 tools 是在下载WebRTC代码执行 gclient runhooks的时候才下载的,它不在 WebRTC 的源码中,而是在 Chromium 项目内,源码目录在 https://chromium.googlesource.com/chromium/src/+/refs/heads/man/tools,我们将这个路径的源码打包下载解压:
unzip src-refs_heads_main-tools.tar.gz
在此方案中,我们又可以通过两种方式来更新工具链:
- 本地编译 llvm 工程;
- 直接下载预编译的 llvm 工具链文件。
2.1 本地编译 llvm
本地下载并编译llvm的方式耗时会比较长,因为要将llvm的代码全部clone到本地,然后再编译。
- 首先,将 src-refs_heads_main-tools/clang 目录替换到现有 WebRTC 的 tools/clang:
rm -rf src/tools/clang
cp -rf src-refs_heads_main-tools/clang src/tools/
- 执行 build.py 脚本,下载llvm并编译:
cd src
python tools/clang/scripts/build.py --without-fuchsia --use-system-cmake
编译完成后,可以将llvm-build内多余的临时文件删除,仅保留必要的include,libs和bin内必要的命令即可。
- 最后,修改 toolchain.gni 内 clang的版本号:
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index 552ceb67e6..06c8958fb9 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -38,7 +38,7 @@ if (generate_linker_map) {
declare_args() {
if (is_clang) {
# Clang compiler version. Clang files are placed at version-dependent paths.
- clang_version = "11.0.0"
+ clang_version = "13.0.0"
}
}
具体版本号,可能每次都不一样,可以通过命令 clang --version 查看:
cd src/third_party/llvm-build/Release+Asserts/bin
./clang --version
输出版本号类似如下:
clang version 13.0.0 (https://github.com/llvm/llvm-project/ 5dad3d1ba9ad01152be21e94cfbbfb31659ea3e1)
Target: x86_64-apple-darwin20.4.0
Thread model: posix
InstalledDir: <webrtc path>/third_party/llvm-build/Release+Asserts/bin/.
2.2 下载预编译 llvm
预编译的llvm 在google仓库内,所以你懂的。
在此方式中,最主要的是对比新旧 update.py 的下载方法,然后修改到本地 update.py或尝试替换。
在此以当前下载的 tools (2021-05-13) 文件为例。
- 首先,修改本地 update.py 如下:
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 83e0ede51f..970703da61 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -37,13 +37,12 @@ import zipfile
# Do NOT CHANGE this if you don't know what you're doing -- see
# https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md
# Reverting problematic clang rolls is safe, though.
-CLANG_REVISION = '99ac9ce7016d701b43b8f0c308dc3463da57d983'
+CLANG_REVISION = 'llvmorg-13-init-9881-g5dad3d1b'
CLANG_SVN_REVISION = 'n353803'
CLANG_SUB_REVISION = 1
-PACKAGE_VERSION = '%s-%s-%s' % (CLANG_SVN_REVISION, CLANG_REVISION[:8],
- CLANG_SUB_REVISION)
-RELEASE_VERSION = '11.0.0'
+PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION)
+RELEASE_VERSION = '13.0.0'
CDS_URL = os.environ.get('CDS_CLANG_BUCKET_OVERRIDE',
- 执行 update.py 脚本,下载相关工具:
python tools/clang/scripts/update.py --host-os=mac
python tools/clang/scripts/update.py --host-os=mac --package=lld_mac
python tools/clang/scripts/update.py --host-os=mac --package=objdump
- 最后,修改 toolchain.gni 内 clang的版本号:
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index 552ceb67e6..06c8958fb9 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -38,7 +38,7 @@ if (generate_linker_map) {
declare_args() {
if (is_clang) {
# Clang compiler version. Clang files are placed at version-dependent paths.
- clang_version = "11.0.0"
+ clang_version = "13.0.0"
}
}
3 总结
经验证,以上两个预案三种方式都可以解决上述编译错误,并完整编过。但经过对比,个人感觉最优的应该是最后一个方式解决,毕竟这个相对来说最简单也是最贴近 WebRTC 的原生编译的方法。
在Mac上编译WebRTC m84时遇到编译错误,原因是Xcode 12.5的工具链不兼容。解决方案包括更改工具链为macos系统工具链,或者升级WebRTC的llvm-build工具链。通过本地编译llvm或下载预编译版本,可以成功解决编译问题。
2256

被折叠的 条评论
为什么被折叠?



