我的问题恰好与FFmpeg有关,但我怀疑几乎任何C库都会发生这种情况。
问题描述
我的应用程序使用使用 NDK r10e 编译的 FFmpeg。我正在尝试将所有内容更新为 NDK r17,同时也切换到 clang,因为 Google 更喜欢我们使用它而不是 gcc。
我的第一步是构建FFmpeg。
为此,我使用make_standalone_toolchain.py
脚本为 x86 架构创建了一个独立的工具链,如下所示:
make_standalone_toolchain.py --arch x86 --api 21 --install-dir ~/Development/ndk-toolchains/x86
然后,我按如下方式配置 FFmpeg 构建:
TOOLCHAIN_DIR=~/Development/ndk-toolchains/x86
./configure
--prefix=$(pwd)/android/x86
--cross-prefix=$TOOLCHAIN_DIR/bin/i686-linux-android-
--target-os=android
--arch=x86
--enable-cross-compile
--disable-asm
--toolchain=clang-usan
--disable-stripping
--extra-cflags="-m32"
--sysroot=$TOOLCHAIN_DIR/sysroot/
然后我按如下方式构建它:
make clean
make -j4
make install
一切似乎都编译得很好,但我收到了几个链接器错误,它们都说同样的事情:
对"__mulodi4"的未定义引用
我尝试过的解决方案
1. 链接libclang_rt.内置*
我在网上发现了一些地方,表明这是由于libgcc不提供__mulodi4
的事实造成的。一位名叫sitsofe的github用户很好,可以在这里发布一个解决方法。但是,我确定在哪里可以找到这个libclang_rt.builtins-i686.a
库。以下是我能够在我的独立工具链目录中找到的内容:
lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-x86_64.a ./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-i386.a ./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-aarch64-android.a ./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-mips64-android.a ./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-x86_64-android.a ./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-i686-android.a ./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-arm-android.a ./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-mips-android.a
libclang_rt.builtins-i686-android.a
图书馆看起来很近,但(我认为)没有雪茄。当我尝试链接到它时,我收到相同的错误:
对"__mulodi4"的未定义引用
这是我新的 FFmpeg 构建配置命令:
./configure
--prefix=$(pwd)/android/x86
--cross-prefix=$TOOLCHAIN_DIR/bin/i686-linux-android-
--target-os=android
--arch=x86
--enable-cross-compile
--disable-asm
--toolchain=clang-usan
--disable-stripping
--extra-cflags="-m32"
--extra-ldflags="-L${TOOLCHAIN_DIR}/lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-i686-android.a"
--sysroot=$TOOLCHAIN_DIR/sysroot/
我与-v
一起检查以确保此行已添加到链接器标志中,确实如此。但是,我不知道这个库是否应该工作,更不用说我是否正确地将其添加到链接器标志中了。无论如何,我在这里做的事情是行不通的。
2. 改用其他消毒剂
我没有使用未定义的消毒器,而是尝试切换到地址清理器。这(坦率地说)完全是黑暗中的刺伤,基于本周在 Google I/O 上模糊地提到 asan在 r17 中可用。
在这种情况下,FFmpeg 构建得很好!
但是,当我尝试将 FFmpeg 拉入我的测试项目(一个简单的 AAR C++支持,只有一个调用av_gettime()
的 jni 方法时,我收到大量链接器错误:
错误:未定义对"__asan_option_detect_stack_use_after_return"的引用
错误:错误:未定义对"__asan_stack_malloc_0"的
引用错误:错误:对"__asan_report_load4"的未
定义引用错误:错误:对"__asan_report_load4"的未
定义引用错误:错误:对
"__asan_shadow_memory_dynamic_address"的未定义引用错误:错误:对"__asan_option_detect_stack_use_after_return">
的未定义引用错误:错误:未定义对"__asan_stack_malloc_0"的引用
错误:错误:未定义对"__asan_report_load4"的引用错误
:错误:对"__asan_report_load4"的未定义
引用错误:错误:未定义对"__asan_shadow_memory_dynamic_address"的引用
错误
:错误:未定义对"__asan_option_detect_stack_use_after_return"的引用错误:错误:未定义对"__asan_stack_malloc_0"的引用
错误:错误:未定义对"__asan_report_store4">
的引用错误:错误:未定义对"__asan_report_store4">
的引用错误:错误:未定义对"__asan_init">
的引用错误:错误:对"__asan_version_mismatch_check_v9"的未定义引用
所以它似乎找到 FFmpeg 库很好,表明我的 CMake 文件的那部分是正确的,但它找不到任何这些 asan 引用。
这似乎是人们遇到的常见问题,但我看不到找到真正适合我的解决方法。
简短的回答:更新到 NDK r17。
这在少数 NDK 错误中有所提及:
- https://github.com/android-ndk/ndk/issues/184
- https://github.com/android-ndk/ndk/issues/294(根本原因,不是相同的症状)
- https://github.com/android-ndk/ndk/issues/506
本质上,Clang正在生成libgcc没有实现的调用。我说是而不是因为对于这个特定功能的 NDK r17 来说,情况似乎不再是这种情况。
如果您仍然遇到此问题,而我只是无法使用任何早期的测试用例,您可以尝试与-lcompiler_rt-extras
链接。这从 NDK r17 开始包含在内,并且缺少功能。