【发布时间】: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