undefined reference

在很久很久以前,只有GNU ld,后来Google贡献了一个gold,就有了两个linker。

Android 2.3里面的gcc 4.4.3默认搭配的是gold。

$ cd prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/arm-eabi/bin
$ ls -l ld*
-rwxr-xr-x 1 liang liang 32272032 2010-12-20 02:44 ld
-rwxr-xr-x 1 liang liang  3248778 2010-12-20 02:44 ld.bfd
-rwxr-xr-x 1 liang liang 32272032 2010-12-20 02:44 ld.gold

使用gold没有任何问题,但是如果把上面的ld换成ld.bfd,那么在链接system/media/opensles/tests下面的程序时,就会报如下错误:

out/target/product/generic/obj/lib/libOpenSLES.so: undefined reference to `typeinfo for android::SortedVectorImpl'
out/target/product/generic/obj/lib/libOpenSLES.so: undefined reference to `vtable for __cxxabiv1::__vmi_class_type_info'

这说明gold和GNU ld的行为不完全一致。使用linker选项--allow-shlib-undefined可以忽略这个错误。ld手册上说:这个选项会使ld忽略so库内的未定义符号,但是对于命令行上其它.o文件内的未定义符号仍然报错。

因此,可以在相应的Android.mk文件里添加

LOCAL_LDFLAGS := -Wl,--allow-shlib-undefined

来解决这个问题。

尽管使用这个解决方法可以把影响减少到最小,但是因为要修改的地方较多,比较麻烦。最省事的方式是全局使用-fno-rtti选项,或者像某些帖子上建议的那样,把IAndroidEffect.c改名为IAndroidEffect.cpp,并在Android.mk里做相应修改。

说实话,我感觉opensles里面的东西有点怪,明明是C++程序,非要使用后缀名.c,然后编译的时候使用-x c++来当作C++程序编译。问题是这样编译就没有使用-fno-rtti,因此输出了rtti信息。当然Android的构建系统也不尽如人意,为啥要根据文件后缀名是.c还是.cpp来选择是否使用-fno-rtti呢?

One thought on “undefined reference

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据