在很久很久以前,只有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
呢?
请问 -fno-rtti选项能起到什么作用呢? 这个选项具体加在哪个文件中呢?