http://www.bizlink.co.jp /trash

BREWコンパイル調査 by gnude

GCCを用いてBREW用のmodファイルをコンパイルするまでの調査。実機で動作するのかどうかまでは未検証である。

  1. 手順
    1. 用意するもの
    2. 環境設定
      1. 環境変数
      2. path
      3. Visual Studio
    3. コンパイル及びMake
      1. C言語
      2. C++言語
      3. 注意
  2. 工夫
  3. C++機能の検証
    1. 使用するソース
      1. gccex1.cpp
      2. gccexImpl.cpp
    2. 結果

手順

このサイトを基にして行った。

用意するもの

以下をインストールする。

参考サイトではQualcomm BREW Utilities and Support for GNUを使用すると書かれているが不要ではないかと思う。

環境設定
環境変数

環境変数を設定する。

  • GCCHOMEをgnudeのインストールパス(例 C:\gnude)に設定する。
  • GCCLIBPATHをlibgcc.aの存在するパス(例 C:\gnude\lib\gcc-lib\arm-elf\3.3.1)に設定する。
path

pathに以下のように追加する。

  • $(GNUHOME)\bin(例 C:\gnude\bin)
  • $(GNUHOME)\arm-elf\bin(例 C:\gnude\arm-elf\bin)
  • $(GNUHOME)\lib\gcc-lib\arm-elf\[GNUのバージョン](例 C:\gnude\lib\gcc-lib\arm-elf\3.3.1)
  • nmakeのパス(例 C:\Program Files\Microsoft Visual Studio\VC98\Bin)
Visual Studio

アドインのツールバーを表示する。

  1. メニューから「ツール」→「カスタマイズ」を選択
  2. 「カスタマイズダイアログ」から「アドイン及びマクロファイル」タブを選択
  3. いくつかあるBREW関係のチェックボックスにチェックを入れる
コンパイル及びMake
C言語
  1. ソースファイル作成後、Visual Studioのツールバーから「GenerateGCCMakeFile」のボタンを押す。
  2. Visual Studioのプロジェクト名と同名の.cファイルをコンパイルするMakeFileが作成される。
  3. コンソールからnmake -f [MakeFile名]でMakeする。
C++言語

Addinのツール自体は未対応の模様。C言語と同様の方法ではC++でコンパイルできるようなMakeFileは生成できなかった。

注意

自動生成されるgcc用のMakeFileは[Visual Studioのプロジェクト名].cに対応したC言語用のMakeFileのようだ。尚、それが存在しない場合には強制的にARM用のMakeFile生成が行われるらしい。

工夫

手順の章でC++用のMakeFileが生成できないと示したが、工夫することによってMakeFileの手動作成を軽減することができる。

ARM用のMakeFileはC++用として生成されるので、両者の良いとこ取りをすることでC++用に仕立て上げることが可能。一度作成してしまえば、ヘッダファイルの依存関係と、どのオブジェクトファイルを作成するかの設定を操作するだけで各プロジェクトに対応できると考えられる。

サンプルをここに示しておく。

C++機能の検証

gnudeでのコンパイルによってC++の機能がどこまで使用できるかを検証する。

使用するソース

以下に示す二つのファイルをコンパイルした。尚、機能はHelloWorldとほぼ同等である。

gccex1.cpp
#include "AEEModGen.h" // Module interface definitions
#include "AEEAppGen.h" // Applet interface definitions
#include "AEEShell.h" // Shell interface definitions
#include "gccexImpl.cpp"
#include "gccex.bid"

extern "C" {
    int AEEClsCreateInstance(AEECLSID ClsId,IShell * pIShell,IModule * pMod,void ** ppObj)
    {
     *ppObj = NULL;
            
     if(AEEApplet_New( sizeof(AEEApplet), // Size of our private class
                         ClsId, // Our class ID
                         pIShell, // Shell interface
                         pMod, // Module instance
                         (IApplet**)ppObj, // Return object
                         (AEEHANDLER)HelloWorld_HandleEvent, // Our event handler
                         NULL)) // No special "cleanup" function
         return(AEE_SUCCESS);

        return (EFAILED);
    }
}

gccexImpl.cpp
#include "AEEAppGen.h" // Applet interface definitions
#include "AEEShell.h" // Shell interface definitions
#include "AEEStdLib.h"

/**
* namespace test
*/

namespace test
{
    class TestClass
    {
        int value;

    public:
        TestClass(int v) : value(v){}
        int getValue(){return value;}
    };
};

static void showText(AEEApplet * pMe, const AECHAR* szText)
{
IDISPLAY_DrawText(pMe->m_pIDisplay, // Display instance
AEE_FONT_BOLD, // Use BOLD font
szText, // Text - Normally comes from resource
-1, // -1 = Use full string length
0, // Ignored - IDF_ALIGN_CENTER
0, // Ignored - IDF_ALIGN_MIDDLE
NULL, // No clipping
IDF_ALIGN_CENTER | IDF_ALIGN_MIDDLE);
IDISPLAY_Update (pMe->m_pIDisplay);
}


static boolean HelloWorld_HandleEvent(AEEApplet * pMe, AEEEvent eCode, uint16 wParam, uint32 dwParam)
{
AECHAR szText[] = {'H','e','l','l','o',' ','W','o', 'r', 'l', 'd', '\0'};
AECHAR szThrowText[] = {'T','H','R','O','W',' ','W','o', 'r', 'l', 'd', '\0'};

switch (eCode){
case EVT_APP_START:
         {
        
            try
            {
//                throw szThrowText;
                showText(pMe, szText);

                test::TestClass cls(3);
                DBGPRINTF("namespace test: %d", cls.getValue());

            }
            catch(const AECHAR* sz)
            {
                showText(pMe, sz);
            }

            return(TRUE);
         }

case EVT_APP_STOP:
return(TRUE);


default:
break;
}
return(FALSE);
}
結果

上記のソースコードにより、namespace及び例外を使用したプログラムをコンパイルすることを試したが、例外に関しては下記のようなリンカエラーが発生してしまった。

C:\ms2\brew\gccex>nmake -f gccex.gcc.mak

Microsoft (R) Program Maintenance Utility Version 6.00.8168.0
Copyright (C) Microsoft Corp 1988-1998. All rights reserved.

---------------------------------------------------------------
OBJECT gccex1.o
C:\brew\gnude\bin\arm-elf-g++ -c -DDYNAMIC_APP -mcpu=arm7tdmi -mapcs-fra
me -mthumb-interwork -mlittle-endian -fshort-enums -fno-builtin -g -IC:\PROGRA~
1\BREWSD~1.1JA\inc -IC:\brew\gnude\lib\gcc-lib\arm-elf\3.3.1\include -IC:\brew\g
nude\arm-elf\include -O2 -IC:\PROGRA~1\BREWSD~1.1JA\inc -IC:\brew\gnude\lib\gcc-
lib\arm-elf\3.3.1\include -IC:\brew\gnude\arm-elf\include -o gccex1.o gccex1.cpp

---------------------------------------------------------------
---------------------------------------------------------------
OBJECT gccexImpl.o
C:\brew\gnude\bin\arm-elf-g++ -c -DDYNAMIC_APP -mcpu=arm7tdmi -mapcs-fra
me -mthumb-interwork -mlittle-endian -fshort-enums -fno-builtin -g -IC:\PROGRA~
1\BREWSD~1.1JA\inc -IC:\brew\gnude\lib\gcc-lib\arm-elf\3.3.1\include -IC:\brew\g
nude\arm-elf\include -O2 -IC:\PROGRA~1\BREWSD~1.1JA\inc -IC:\brew\gnude\lib\gcc-
lib\arm-elf\3.3.1\include -IC:\brew\gnude\arm-elf\include -o gccexImpl.o gccexIm
pl.cpp
---------------------------------------------------------------
C:\brew\gnude\bin\arm-elf-ld -Ttext 0 --emit-relocs -entry AEEMod_Load
--gc-sections -o C:\ms2\brew\gccex\gccex.elf -LC:\brew\gnude\lib\gcc-lib\arm-el
f\3.3.1 AEEModGen.o AEEAppGen.o gccex1.o gccexImpl.o GCCResolver.o -lgcc
/cygdrive/c/brew/gnude/bin/arm-elf-ld: Warning: C:\brew\gnude\lib\gcc-lib\arm-el
f\3.3.1/libgcc.a(unwind-sjlj.o) does not support interworking, whereas C:\ms2\br
ew\gccex\gccex.elf does
gccex1.o(.text+0x170): In function `HelloWorld_HandleEvent':
/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:127: undefined reference to `__cxa_begi
n_catch'
gccex1.o(.text+0x188):/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:129: undefined re
ference to `__cxa_end_catch'
gccex1.o(.text+0x1ac):/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:129: undefined re
ference to `__cxa_end_catch'
gccex1.o(.text+0x1b4):/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:129: undefined re
ference to `__gxx_personality_sj0'
gccex1.o(.gcc_except_table+0xc): In function `showText':
/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:96: undefined reference to `typeinfo fo
r unsigned short const*'
gccexImpl.o(.text+0x170): In function `HelloWorld_HandleEvent':
/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:127: undefined reference to `__cxa_begi
n_catch'
gccexImpl.o(.text+0x188):/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:129: undefined
reference to `__cxa_end_catch'
gccexImpl.o(.text+0x1ac):/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:129: undefined
reference to `__cxa_end_catch'
gccexImpl.o(.text+0x1b4):/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:129: undefined
reference to `__gxx_personality_sj0'
gccexImpl.o(.gcc_except_table+0xc): In function `showText':
/cygdrive/c/ms2/brew/gccex/gccexImpl.cpp:96: undefined reference to `typeinfo fo
r unsigned short const*'
C:\brew\gnude\lib\gcc-lib\arm-elf\3.3.1/libgcc.a(unwind-sjlj.o)(.text+0x140): In
function `_Unwind_RaiseException_Phase2':
../../gcc-3.3.1/gcc/unwind.inc:67: undefined reference to `abort'
C:\brew\gnude\lib\gcc-lib\arm-elf\3.3.1/libgcc.a(unwind-sjlj.o)(.text+0x3d8): In
function `_Unwind_SjLj_Resume':
../../gcc-3.3.1/gcc/unwind.inc:230: undefined reference to `abort'
C:\brew\gnude\lib\gcc-lib\arm-elf\3.3.1/libgcc.a(unwind-sjlj.o)(.text+0x444): In
function `_Unwind_SjLj_Resume_or_Rethrow':
../../gcc-3.3.1/gcc/unwind.inc:256: undefined reference to `abort'
NMAKE : fatal error U1077: 'C:\brew\gnude\bin\arm-elf-ld' : リターン コード '0x1'
Stop.

例外は使用できないようだ。

namespaceは簡単な使用に関しては問題なさそうだ。