最近公司因为版权原因,不能继续使用ADS编译器,而是换成了免费的gcc编译器。
经过一段时间的试用磨合,现在公司里大部分应用在生成mod时都使用gcc编译器。小部分因为容量限制,使用的是公司购买的RealView编译器。gcc 编译器使用thumb模式生成的mod在手机上跑有问题,尚未解决,因此mod体积要比可以使用thumb模式的RealView大一些。但是购买的RealView版本,一套只能装一个机器。一套RealView几万块钱,每台机器装又不现实。即使使用telnet远程编译,也不如本机上装的gcc方便。
使用gcc的过程中还是颇费了一番周折的,下面记录一下遇到的困难,希望能给大家提供一些帮助。
1.GCC版本
在BREW Forum上了解到BREW圈子里,GNUDE和WINARM是两个用的比较多的windows下的arm-gcc编译环境(还有一个更新的YAGARTO)。GNUDE的gcc编译器是3.x版本,WINARM的是4.x版本。GNUDE在win7上生成源文件依赖文件列表时编译器会死掉,因此顺势就用了版本较新的WINARM。
2.搭配工具
项目要有一个针对GCC的Makefile。这个Makefile可以自己写,也可以使用BREW SDK Tools 1.1.1 SP06带的VC插件自动生成。如果是自动生成的话,注意要配好GCC的环境变量。例如我的WinARM装在D盘根目录下,环境变量就要设为
GCCHOME=D:/WinARM
GCCLIBPATH=D:/WinARM/lib/gcc/arm-elf/4.1.1
Path里也要加入D:/WinARM/bin
3.链接脚本问题
需要给GCC链接器提供一个链接脚本,如果使用BREW SDK Tools 1.1.1 SP06的话,有一个默认的链接脚本elf2mod.x。如果多文件工程,使用-O2或-Os编译选项的话,这个链接脚本会有问题,它不能保证AEEMod_Load放在mod的0地址处,而对于BREW程序而言,这又是必须的。我稍微修改了下elf2mod.x文件,这样定义.text段,就可以使用优化编译选项了。
.text : AT(0)
{
"AEEMod*.o"(.text.AEEMod_Load) /*add by zp,10.06.08*/
*(.text .stub .text.* .gnu.linkonce.t* .glue_7t .glue_7)
} :ER_RO =0
4.链接错误
刚开始使用WinARM时,链接器总报告这样的错误
undefined reference to `abort'
undefined reference to `_sbrk_r'
开始我以为是没有链接正确的gcc库,后来发现WinARM使用了一个叫做NewLib的库,这个库里有些与硬件相关的底层函数是需要用户自己定义的。而程序里使用这些底层功能的地方是一个叫做__cxa_pure_virtual的系统函数(纯虚函数调用的错误处理函数)。我们只要将这个函数定义成空就可以绕过这个问题了。
void __cxa_pure_virtual (void) {}
5.宽字符串
使用AECHAR的话,GCC默认是4个字节,与BREW标准不符。需要使用一个编译选项-fshort-wchar,否则使用宽字符串的地方会出错。
6.浮点数问题
GCC的double格式可以称为middle endian(即DWORD内部是little endian,DWORD之间是big endian),这与手机上的BREW实现是不一致的。因此如果调用BREW的浮点数接口,例如FADD / WSTRTOFLOA等,得到结果是不正确的。其实一般的加减乘除,直接使用运算符就可以了(GCC的这个解决方案支持全局变量,进而支持浮点数运算)。如果要使用FSQT等函数,可以在运行时动态判断浮点数格式,在与BREW接口交互时进行必要的转换。
7.参考资料
a.
HOWTO Compile BREW applets with WinARM 4.1.0
(and other applet startup topics)
——————http://brew.wardco.com/
目前发现的最好的参考资料,有编译选项的详细说明,各种编译器的对比数据,对链接脚本也有细致的讲解
b.
使用GNU GCC创建BREW应用
——————http://blog.vckbase.com/knight/archive/2009/06/29/16801.html
中文的,还附带一份Makefile模板