以前在做Symbian的时候,曾经研究过ARM CPU的指令集问题,ARM处理器支持两套指令集,即ARM和Thumb。ARM为32位指令集而Thumb为16位指令集,理论上32位可以提供更快的执行速度但会生成更大的二进制执行文件,而16位的Thumb则恰恰相反,省地儿但慢,这也正是体现出了ARM对于嵌入式设备的专业性。对于我这种牺牲一切换速度的理念来说,当时就留下了ARM就比Thumb快的印象,以致于现在在做Android NDK原生开发时,也是优先用ARM指令集。(这个可以通过在Android.mk中加入LOCAL_ARM_MODE := arm控制,默认情况下NDK使用Thumb指令集)
但是最近在Xcode编译iOS项目时,注意到同为ARM处理器的苹果设备,使用的是Thumb指令集,而且好像还是某种新版本的Thumb指令集,小搜索了一下看到有人说这种armv7引入的叫做Thumb-2的指令集要比arm指令集更好!于是又重新搜索更新了一下大脑知识库…
armv7对于苹果设备来说,意味着iPhone 3GS以上级别的设备的CPU,而目前主流的Android设备几乎全是armv7处理器的了。也许对于早起的armv6处理器来说,ARM指令集还有优势,但是对于新的v7处理器,各种资料都表明Thumb-2要更好一些。
总的来说,ARM指令集会在某些方面有优势,比如手写汇编(额…),而Thumb则能生成更精简的代码,而且还有一点我之前没有太意识到的问题就是:省电!所以仔细斟酌后,我还是决定把NDK编译选项由原来的ARM改回默认的Thumb,遵循默认原则吧还是。
而对于v7和非v7的问题,Android上可以这样处理,以略增大apk为代价,加入单独针对v7和非v7版的so文件,这样apk在安装时会自动根据目标设备的CPU安装合适的so库,从而达到更好的效果,具体做法是在Application.mk中加入”APP_ABI := armeabi armeabi-v7a"
另外,随着项目规模的增大,代码编译生成时间会大大增加,这时候可以考虑更换r8c版NDK新加入的Clang编译器(苹果家的编译器,新版Xcode默认就用它),实测发现Clang比GCC明显快很多,而且对于warning, error的显示也比GCC要人性的多(有人说GCC的提示就像是天书,呵呵),不过据说Clang也有一些不足,比如对于标准的支持不如GCC(这话怎么听着像是说MS的…),不如GCC支持的语言广等,但感觉对于Android原生开发来说都是些无关紧要的事,我只要编译快,运行快就好了!
改用Clang编译器的方法如下:
对于ndk-build方式,可以使用“export NDK_TOOLCHAIN_VERSION=clang3.1”导出环境变量,或者将这个环境变量设置加入到Application.mk中。
对于独立编译方式,在make-standalone-toolchain.sh脚本中加入–llvm-version=3.1 并在makefile中用<tool-path>/bin/clang and <tool-path>/bin/clang++替换 CC 和CXX 参数。
PS:实际编译时发现Clang好像对中文注释支持不是特别好,比如有端代码在if(…)后谢了//中文注释,导致编译器处理至此处时直接报了异常,删除注释后就没事了…
参考文章:
- Producing optimised NDK code for multiple architectures? http://stackoverflow.com/questions/5089783/producing-optimised-ndk-code-for-multiple-architectures
- Is there a way to compile for ARM rather than Thumb in Xcode 4? http://stackoverflow.com/questions/8390606/is-there-a-way-to-compile-for-arm-rather-than-thumb-in-xcode-4
博主友情提示:
如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。
1 Response
[…] 首先是配置Android开发环境,测试用的linux系统为RHEL RedHat Enterprise Linux 5.5,由于我只是想将项目的native部分(/jni)进行分布式编译处理,不考虑Java部分,所以SDK的配置就免了,直接wget最新版本的NDK for linux:http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2解压缩,调用./ndk-build -C /proj/尝试编译项目代码,结果报错提示libstdc++.so.6的GLIBCXX3.4.10(记忆中好像是这个版本号…),搜索了一下发现是由于libstdc++.so.6符号连接的libstdc++库版本过低导致的,于是开始折腾linux的源更新,什么下载源码编译啊,配置yum自动更新啊,折腾了半天也没给libstdc++.so升级成功,最后直接从网上down了一份人家编译好的so:http://download.csdn.net/detail/dqswuyundong/3379734(同样还是没记错的话…切记不要搞错32bit 64bit版本),放到lib位置然后ln -s重新建立libstdc++.so.6的符号连接到新的so,然后再试,发现又提示libz.so.1的错误(依然是没记错的话,貌似是最后运行一个什么strip程序的时候,libz.so.1: no version information available…),看了一下,依旧是版本过低问题,这次直接到:http://www.zlib.net/下载1.2.7版本的源码编译安装,然后重做符号链接,编译,终于这回pass了,然后又换了一下toolchain到clang3.1,加入APP_ABI armeabi armeabi-v7a两份so生成(具体操作可以看之前的这篇:http://blog.k-res.net/%E8%AE%BE%E8%AE%A1%E5%BC%80%E5%8F%91/cc/android-ndk-arm-thumb-toolchain-switch…),这样下来生成一次时间大概是不到30min! […]