首页 > 解决方案 > 使用 Android NDK r17 构建 C 库 (FFmpeg):未定义对“__mulodi4”的引用

问题描述

我的问题恰好出在 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.builtins*

我在网上发现了一些地方,这表明这是由于 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 的 r17 中模糊地提到了 asan。

在这种情况下,FFmpeg 构建得很好!

但是,当我尝试将 FFmpeg 拉入我的测试项目(一个简单的带有 C++ 支持的 AAR,它只有一个调用 的 jni 方法时av_gettime(),我得到了大量的链接器错误:

错误:错误:未定义引用“__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引用中的任何一个。

这似乎是人们遇到的一个常见问题,但我找不到真正适合我的解决方法。

标签: ffmpegandroid-ndkclangsanitizerlibgcc

解决方案


简短的回答:更新到 NDK r17。

这在少数 NDK 错误中提到:

本质上,Clang 正在生成 libgcc 未实现的调用。我说而不是因为对于这个特定功能的 NDK r17 似乎不再是这种情况。

如果您仍然遇到此问题并且我无法使用任何早期的测试用例,您可以尝试使用-lcompiler_rt-extras. 这包含在 NDK r17 中,并且具有缺失的功能。


推荐阅读