【问题标题】:Android NDK Shared Object Undefined Reference ErrorAndroid NDK 共享对象未定义引用错误
【发布时间】:2017-03-13 17:02:10
【问题描述】:

我在尝试为 Android 编译代码时遇到了一个奇怪的问题。我的代码与两个第三方库(libcurl 和 WebRTC)交互,当它进入链接阶段(链接到编译的共享对象文件)时,它报告 WebRTC 中有未定义的函数引用,但 libcurl 函数很好。我得到的未定义错误的例子是:

WS.cpp:208: error: undefined reference to 'buzz::XmlElement::AddAttr(buzz::QName const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)'

ThirdPartyLibs/WebRTC/src/third_party/android_tools/ndk/sources/cxx-stl/llvm-libc++/libcxx/include/memory:1636: error: undefined reference to 'buzz::QN_MESSAGE'

当我在 WebRTC 库文件上运行 nm -C,然后运行 ​​grep 函数的结果时,函数清楚地显示存在并被定义(在文本部分中)。

nm -C Android/libs/armv7/libWebRTC.so | grep "AddAttr"
000753e5 t buzz::XmlElement::AddAttr(buzz::QName const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
0007541d t buzz::XmlElement::AddAttr(buzz::QName const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)

nm -C kino/Android/libs/armv7/libWebRTC.so | grep "QN_MESSAGE"
000bfd10 d buzz::QN_MESSAGE

当我说我正在链接已编译的 WebRTC 共享库时,我应该注意共享库是使用 ninja 编译的静态库或目标文件编译的。我正在使用以下内容进行编译:

GCC_armv7=$projectDir/ThirdPartyLibs/WebRTC/src/third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc

OBJS_armv7="…list of static libraries or object files…”

LDFLAGS="-lc -ldl -lm -fPIC 
--sysroot=$projectDir/ThirdPartyLibs/WebRTC/src/third_party/android_tools/ndk/platforms/android-16/arch-arm 
-L$projectDir/ThirdPartyLibs/WebRTC/src/third_party/android_tools/ndk/platforms/android-16/arch-arm/usr/lib/"

$GCC_armv7 -v -shared $LDFLAGS -o libWebRTC.so -Wl,-soname=webrtc $OBJS_armv7

当我将我的代码直接链接到 ninja 编译的静态库文件或 ninja 编译的目标文件时,我不会遇到同样的错误。由于它有效,因此最好只链接其中任何一个。然而,Java Android 开发人员告诉我,虽然 Java 接受静态库,但 Android 不接受。而且我无法想象 Java 或 Android 会针对目标文件进行编译。

我还不得不在 Android.mk 文件中强制引用 LOCAL_LDLIBS 参数中的文件,而不是使用 LOCAL_SHARED_LIBRARIES 或 LOCAL_STATIC_LIBRARIES 参数。

当我尝试使用前一种方法时,ndk-build 似乎永远找不到合适的库文件。相反,它似乎使用了系统版本的 libcurl 和 libopenssl 库。

作为健全性检查,我对目标文件和静态库文件运行相同的nm | grep 命令,并将它们与共享目标文件的结果进行比较。下面是静态/目标文件和编译好的so文件的nm –C | grep结果对比。

static / object -
00000001 T buzz::XmlElement::AddAttr(buzz::QName const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)

shared object -
000753e5 t buzz::XmlElement::AddAttr(buzz::QName const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)

根据我在nm 的输出中收集到的信息,“T”和“t”之间没有区别,但我不明白为什么它会在两组之间发生变化。

我应该注意,正在使用的 gcc(或 g++)编译器是 WebRTC 下载 (commit hash: aad6780e5c25b1622904ef83659461706f6a25db) 提供的相应架构的特定 gcc / g++ 二进制文件。对于 ndk-build(ing),我还使用 WebRTC 下载 (src/chromium/src/third_party/android_tools/ndk/ndk-build) 附带的 ndk-build 二进制文件。

我的问题:我做错了什么,以至于链接对象文件将编译 ndk-build Android.mk 文件,但链接共享对象文件将失败,其中一些函数正在定义而另一个未定义?

更新:我刚刚尝试使用 ndk-build 和 Android.mk 文件而不是 gcc / g++ 编译 so 文件,但我遇到了同样的错误。

【问题讨论】:

    标签: android-ndk shared-libraries webrtc


    【解决方案1】:

    我想出了解决这个问题的方法。我没有尝试为 WebRTC 构建单独的共享对象文件,而是返回直接链接到已编译对象文件的路线。这样做会强制 ndk-build 将这些对象包含在我的代码的已编译共享对象文件中。因此,我的最终库 .so 文件比计划的要大得多。但这并不重要,因为它包含我们正在使用的所有 WebRTC 库。对于那些有类似问题的人,请注意./libs/&lt;arch&gt;/ 文件夹中的已编译库文件已去除符号。所以如果你nm | grep他们,你会得到一个错误。如果您需要使用该命令进行任何类型的完整性检查,请改用 ./obj/local/&lt;arch&gt; 中的已编译库。

    我不会接受这个答案,以防其他人出现并且能够在不解决问题的情况下实际解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-11
      • 2011-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多