我的问题恰好出在 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引用中的任何一个。
这似乎是人们遇到的一个常见问题,但我找不到真正适合我的解决方法。