2016-10-31 50 views
4

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

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' 

当我运行nm -C上的WebRTC库文件,然后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共享库,我应该注意的是,共享库正在使用或者忍者编译静态库文件或目标文件编译。我使用如下的编译:

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命令,并将它们与共享目标文件的结果进行比较。下面是静态/对象文件和编译后的文件之间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 ++编译这样的文件,并且我得到相同的错误。

回答

0

我想出了一个解决这个问题的方法。我没有试图为WebRTC构建单独的共享对象文件,而是沿着直接链接到编译对象文件的路线返回。这样做会迫使ndk-build将这些对象包含在我的代码的编译共享对象文件中。因此,我的最终库.so文件显着大于计划。但这并不重要,因为它拥有我们正在使用的所有WebRTC库。对于那些遇到类似问题的用户,请注意./libs/<arch>/文件夹中已编译的库文件被剥离了符号。所以如果你nm | grep他们,你会得到一个错误。如果您需要使用该命令进行任何形式的理智检查,请改用./obj/local/<arch>中的已编译库。

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