在尝试为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
当我直接将我的代码链接到忍者编译的静态库文件或忍者编译的目标文件时,我没有得到相同的错误。既然它有效,那么只需链接其中任何一个都会很好。但是,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”之间没有区别,但我不明白为什么它会在两组之间发生变化。 / p>
我应该注意,正在使用的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文件,我得到了相同的错误。
答案 0 :(得分:0)
我想出了解决这个问题的方法。我没有尝试为WebRTC构建单独的共享对象文件,而是直接链接到编译对象文件的路径。这样做迫使ndk-build将这些对象包含在我的代码的编译共享对象文件中。因此,我的最终库.so文件明显大于计划。但这并不重要,因为它占据了我们正在使用的所有WebRTC库。对于那些有类似问题的人,请注意./libs/<arch>/
文件夹中的已编译库文件是从符号中删除的。因此,如果您nm | grep
他们,您将收到错误。如果您需要使用该命令进行任何类型的完整性检查,请改用./obj/local/<arch>
中的已编译库。
我不会接受这个答案,以防其他人出现并且能够在没有解决方法的情况下实际解决问题。