如何在Symbian SDK下使用GCCE4

来源:互联网 发布:seo前期是做什么 编辑:程序博客网 时间:2024/06/05 20:58

 

Contents

 [hide]
  • 1 为什么要用GCCE 4
  • 2 免责声明
  • 3 必要的文件
  • 4 版本
  • 5 工具链的更换
    • 5.1 备份旧的工具链
    • 5.2 拷贝新的工具链
  • 6 给SDK打补丁
    • 6.1 编辑编译脚本
    • 6.2 移除失败断言
    • 6.3 更正va_lists
    • 6.4 从SDK的头文件移除额外的限定符号
    • 6.5 解决libsupc++链接错误。只GCCE4.3.2检测
    • 6.6 提供自己的整数除法例程
  • 7 项目清理
  • 8 已知移植问题
    • 8.1 警告
    • 8.2 static initialization fiasco
  • 9 Links

为什么要用GCCE 4

Symbian OS v.9.1+ SDK依赖于GCCE CSL Arm Toochain来为真实设备编译代码。然而,随SDK发布的GCCE编译器相当老,3.4.3,最初发布于2004年11月。

尽管在大多数情况下GCCE 3.4.3是一个很好的编译器,不过仍含有一些问题。它也相当慢,在较大的应用程序开发中,你会发现更新的工具链(toolchain)会更好,基于以下理由:

  • GCC 4 编译器明显更快,特别是编译C代码时
  • GCC 4 似乎与优化有关的问题变得更少了
  • GCC 4 生成显著更小的二进制文件(例如,在测试用例中, 整个应用程序的SIS从1.4MB缩小到1MB(Release)).
  • GCC 4 似乎误编译更少了
  • GCC 4 在生成错误及警告信息时更严格,因此导致更好的代码质量。

 

免责声明

若你打算在你的SDK中使用GCCE 4,注意在功能或正确性方面没有保证。这是一个“尽力服务”的Howto,提供但没有保证。

按照: CodeSourcery:

"You are attempting to do something that we do not recommend you do with the zero-cost downloads. The Lite toolchains are provided at zero cost without support."

若你想安全一些,在开始前做一个备份。

必要的文件

首先,必须下载新版的CSL Arm工具链(Toolchain):CodeSourcery。下载路径在这里。若直接的链接不好使,可以在'Downloads'菜单找到下载。

CodeSourcery生成了许多不同的包。你需要的包是“Sourcery G++ Lite Edition for ARM”,Symbian OS为目标OS的那个。这个包应可以免费获得。

也有以前发行的归档版本可用。通常每年发行两次。常常推荐选择较老的发行版。

版本

所有的包已在Series 60 3rd Edition, Maintenance Release (Symbian 9.1) SDK下测试过:

Package versionGCC versionResults of tests2006q1 - 64.1.0Even in simple code, a compilation error with "internal compiler error" message. Recommendation: do not attempt to use it.2007q1 - 264.2.0After making necessary changes to the SDK, the compilation runs well. HelloWorldBasic can be built and run on device (both Debug and Release modes).2007q3 - 524.2.1Not tested. Should behave similarly to 4.2.0 and 4.2.3.2008q1 - 1264.2.3After making necessary changes to the SDK, compilation runs well.

HelloWorldBasic can be built and run on device (both Debug and Release modes). This version has been tested on a very large project (over 100,000 lines of code): some changes were necessary, but overall it seemed to work.

2008q3 – 674.3.2After making necessary changes to the SDK, the compilation runs well.

Linker problems with missing "_Unwind_GetTextRelBase". Recommendation: stick to 4.2.3, if possible.

工具链的更换

从CodeSourcery下载想要的包版本之后安装。缺省时将安装到下面的目录:

c:/program files/CodeSourcery/Sourcery G++ Lite/ 

备份旧的工具链

在开始改变工具链前,给老版(3.4.3)做一个备份。万一有问题时,不必重新安装SDK。

随SDK提供的那个版本通常在下面的目录:

C:/Program Files/CSL Arm Toolchain/ 

另创建一个目录,比如C:/Program Files/CSL-Backup/,拷贝旧版目录下的所有内容到备份目录。若发生错误,只需简单删除改变过的C:/Program Files/CSL Arm Toolchain/目录下的内容,把备份的内容拷贝到原来的位置。

拷贝新的工具链

移除C:/Program Files/CSL Arm Toolchain/目录下所有旧的内容,然后从c:/program files/CodeSourcery/Sourcery G++ Lite/拷贝新工具链的内容到旧目录。

这个完成后,新的工具链就装上了。然而要使用新工具链,还需给SDK打补丁。

给SDK打补丁

编辑编译脚本

就目前所致,所有SDK都需要这个补丁。

在SDK的子目录epoc32/tools下有一些文件,指向工具链的准备版本,因此需要打补丁。即:

cl_bpabi.pmcl_gcce.pm ide_cw.pm compilation_config/gcce.mk

备份上面的文件到不同的目录(比如,"original_343")。然后编辑所有文件,移除"3.4.3"字符串,用在新工具链使用的那个GCC版本替换它们(例如:"4.2.3")。

备份这些文件到不同的目录——不要备份在同一个目录。IDE中处理这些文件的脚本可能误将备份作为真实的文件。更多信息参看这里的讨论。

移除失败断言

这个修补与Series 60 3rd Edition, MR SDK有关。你的SDK或许不同,可能根本不需要这个修补。

在你的SDK的include目录找到文件d32locd.h。备份一下这个文件。然后找到并注释掉下面的行:

__ASSERT_COMPILE(_FOFF(TLocalDriveCaps,iSize)%8 == 0);__ASSERT_COMPILE(_FOFF(TLocalDriveCapsV3,iFormatInfo.iCapacity) % 8 == 0);

这些行在GCC4下会触发一个编译错误("not a constant", 等)。

 

更正va_lists

这个修补与Series 60 3rd Edition, MR SDK有关。你的SDK或许不同,可能根本不需要这个修补。

类型
va_list
和相关类型用在处理可变参数长度的函数中(例如,LIBC库中的
printf
函数)。 在新工具链安装后,将有这些必需类型的多个定义,使编译器困惑,每次你用
va_list
和相关类型时都将打出错误信息。 要避免这个,在SDK的include目录找到
gcce/gcce.h
文件。备份一下这个文件。在这个文件中,找到并注释掉这些行:
typedef struct __va_list { void *__ap; } va_list;#define va_start(ap, parmN) __builtin_va_start(ap.__ap, parmN)#define va_arg(ap, type) __builtin_va_arg(ap.__ap, type)#define va_end(ap) __builtin_va_end(ap.__ap)

然后添加下面的行,就在被注释掉的第一行之前:

#include <libc/stdarg.h>

注意由于这个修补,现在事实上你的每个项目都需从标准C库中包含stdarg.h头文件。为克服这个问题,必需在每个你要用新工具链编译的项目的MMP文件中有下面这一行:

SYSTEMINCLUDE     /epoc32/include/libc
因为
stdarg.h
文件从这个目录包含了更多的文件。

从SDK的头文件移除额外的限定符号

这个修补与Series 60 3rd Edition, MR SDK有关。你的SDK或许不同,可能根本不需要这个修补。

若你在用AVKON Query Dialog,在SDK的include目录找到aknquerydialog.h,备份一下这个文件,然后找到下面的行:

CCoeControl* CAknQueryDialog::FindControlOnAnyPageWithControlType(TInt aControlType, TInt* aLineIndex=0, TInt* aPageIndex=0) const;

然后去掉前面的限定符号:

CAknQueryDialog::

结果如下:

CCoeControl* FindControlOnAnyPageWithControlType(TInt aControlType, TInt* aLineIndex=0, TInt* aPageIndex=0) const;

这阻止了一个"extra qualification"编译错误。在GCC 3.4.3不产生这个错误,而GCC 4会检测到。

若使用ImageConversion.h,将碰到一个类似的问题。有问题的行为:

IMPORT_C static CIclRecognizerUtil* CIclRecognizerUtil::NewL();

再次,移除额外的限定符号:

你会在Symbian SDK include文件中发现更多的"extra qualification"错误。这似乎是一个常见问题。下一个这样的错误在mmf/mmfcontrollerpluginresolver.h, 以及coecntrl.h,等等。它们都需要修补一下。应该不会超过4-5个错误。

同样也适用于你自己的代码——不允许额外的限定符号。

解决libsupc++链接错误。只GCCE4.3.2检测

在链接阶段,GCCE 4.3.2工具链会抱怨找不到对<pr>_Unwind_GetTextRelBase</PR>的引用。

这是由于在下面的文件中缺少二进制代码引起的:

CSL Arm Toolchain/lib/libsupc++.a

在4.3.2发行中,这个文件大约7kB。

这个问题有两个可行的解决方案。

简单的方法是用从一些更老的工具链(甚至3.4.3)的原来文件替换这个文件。老文件将有15kB。只需用较旧的文件替换这个较新的文件。

更复杂的办法是自己写丢失的函数,然后把它们添加到你的项目的源代码中。函数实现可以为空。这里这个办法没有测试。

GCCE 4.2.0或4.2.3不检测这个问题。

提供自己的整数除法例程

一些S60第三版SDK遇到下面的问题:系统库不含编译器辅助函数__aeabi_uidiv和__aeabi_idiv的定义。这是一个Symbian的疏忽,它不仅限于SDK,设备也受到影响。

若你从不打算在项目中使用使用整数除法,可完全跳过这个部分。

要找出你的SDK是否含有这个错误,在你的代码的某个地方输入下面的代码片段(不要在不可到达的地方),然后尝试用GCCE DEBUG编译代码:

#include <e32debug.h>
 
...
void tryDivision ()
{
TInt a, b, c;
a = 10;
b = 5;
c = a / b;
RDebug::Printf("Result of division is %d",c);
}

下一步,在你的代码的某处调用tryDivision()函数,例如在AppUi类的ConstructL方法中。

(这里Printf行是必要的因为否则的话编译器抛出无用的除法代码,而不能检测到可能的错误。)

这段代码在WINSCW下总是可编译的,在GCCE DEBUG下,编译过程可能终止,给出提示信息:"missing reference to __aeabi_idiv"

这种情形下,你使用的SDK有些问题,需执行下面的修改:

在你的项目的src/目录下创建一个新文件,命名为division.c。文件内容如下:

// This code was suggested by Julian Brown from CodeSourcery. It is in public domain.
// Many thanks!
 
#if __GCCE__
#if __SERIES60_30__
extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator);
int __aeabi_idiv(int numerator, int denominator)
{
int neg_result = (numerator ^ denominator) & 0x80000000;
int result = __aeabi_uidivmod ((numerator < 0) ? -numerator : numerator, (denominator < 0) ? -denominator : denominator);
return neg_result ? -result : result;
}
unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator)
{
return __aeabi_uidivmod (numerator, denominator);
}
#endif // __SERIES60_30__
#endif // __GCCE__

这个文件将被自动加到MMP文件中。按照需要调整预处理块(#if __SERIES60_30__)

项目清理

在命令行(你的项目的group目录)下执行下面的命令:

bldmake clean bldmake bldfilesabld build gcce udeb

这应该清除并重建了你的GCCE makefiles文件(含有旧工具链路径)。

已知移植问题

警告

GCCE4给出比GCCE3更多的警告信息,因此,你会在以前没有警告的代码发现许多警告。然后,这是一个功能而不是bug,大多数警告是有用的。

static initialization fiasco

GCCE4对"static initialization fiasco"比GCCE3更敏感。

"Static initialization fiasco"意味着这样的情形:用另一个静态变量(或常量)初始化某个静态变量(或常量)。应为编译器或系统不保证静态初始化的正确顺序,若你试图用一个尚未初始化的值去初始化某些东西你将碰到错误。

要阅读更多关于"static initialization fiasco"的资料,访问: C++ Faq Lite.

若在你的Symbian代码中有"static initialization fiascos",机会是GCCE 3.4.3不触发任何错误,而GCCE 4.x会。那是因为编译器产生了不同的代码,因此,静态初始化顺序也改变了。

这是一个十分让人沮丧的状态,因为它导致你的应用程序的过早退出。然而static initialization fiasco是一个严重问题,退回使用旧GCCE它也不会消失。机会是,将来你需要用新的工具链编译你的代码,不管怎样你将被迫做些修理。

典型的例子是static const描述符从另一个static const描述符初始化,或者是一个使用静态常量描述符的static const结构,或者是使用资源id的static const结构。解决办法:这个种情形下,有问题的结构只局部使用,在单个类或单个函数中。因此,值得考虑从全局头文件移到那里(单个类或单个函数)。

检测"static initialization fiascos"的方法是用GCCE Debug编译,运行on/device debugging,然后观察错误。panic栈会导航到引起问题的那个结构(点击"static initialization and destruction"行)。

Links

  • [How to use GCCE 4 with Symbian SDKs]
  • [GCC 4.2.3 provides some space optimisation..]

Related Wiki Articles

No related wiki articles found

原创粉丝点击