3.3. Building SymbianOS Programs

Building programs for SymbianOS requires you install additional software and follow the SymbianOS build procedure.

You must install the Symbian SDK. For Linux hosts, you must install the SDK on a Windows machine and then make the file system visible on your Linux host. Alternatively, for Linux hosts, the GnuPoc project provides patches. Set the environment variable EPOCROOT to the directory containing the epoc32 directory of your Symbian SDK installation, and also ensure your PATH variable includes the $EPOCROOT/epoc32/tools directory. The following commands also make use of epoclib and epocarch variables for convenience. For instance, if you have installed the SDK at /opt/symbian-sdk, enter the following commands:

> export EPOCROOT=/opt/symbian-sdk/s60
> PATH=$EPOCROOT/epoc32/tools:$PATH
> epocinc=$EPOCROOT/epoc32/include
> epocarch=$EPOCROOT/epoc32/release/armv5

SymbianOS programs do not start at main, but at E32Main. Using an editor (such as notepad on Microsoft Windows or vi on UNIX-like systems), create a file named main.cc containing the following console program:

#include <e32base.h>
#include <e32cons.h>

_LIT (KTxtEPOC32EX, "EXAMPLES");
_LIT (KTxtExampleCode, "Symbian OS Example Code");
_LIT (KTxtOK, "ok [press any key]");

LOCAL_D CConsoleBase* console;

LOCAL_C int factorial(int n) {
  if (n == 0)
    return 1;
  return n * factorial (n - 1);
}


LOCAL_C void callExampleL () {
  console = Console::NewL
    (KTxtExampleCode,
     TSize (KConsFullScreen, KConsFullScreen));
  CleanupStack::PushL (console);
  
  _LIT (KHelloWorldText, "Hello world!\n");
  console->Printf (KHelloWorldText);
  for (int i = 0; i < 10; ++i) {
    int n = factorial (i);
    _LIT (KFactorialText, "factorial(%d) = %d\n");
    console->Printf (KFactorialText, i, n);
  }
  
  console->Printf (KTxtOK);
  console->Getch ();
  CleanupStack::PopAndDestroy ();
}

GLDEF_C TInt E32Main () {
  __UHEAP_MARK;
  CTrapCleanup *cleanup = CTrapCleanup::New ();
  TRAPD (error, callExampleL ());
  __ASSERT_ALWAYS (!error, User::Panic (KTxtEPOC32EX, error));
  delete cleanup;
  __UHEAP_MARKEND;
  return 0;
}

To compile a program in main.c use the following command:

> arm-none-symbianelf-g++ -march=armv5t -mthumb -mapcs -nostdinc \
  -D__MARM__ -D__MARM_ARMV5__ -D__MARM_THUMB__ \
  -D__MARM_INTERWORK__ -D__EABI__ -D__EXE__ \
  -D_DEBUG -D_UNICODE -D__SUPPORT_CPP_EXCEPTIONS__ \
  -D__GCCE__ -D__SYMBIAN32__ -D__EPOC32__ \
  -D__S60_50__ -D__S60_3X__ -D__SERIES60_3X__ \
  -D__PRODUCT_INCLUDE__=\"$epocinc/variant/symbian_os.hrh\" \
  -include $epocinc/gcce/gcce.h \
  -I $epocinc/libc -I $epocinc -I $epocinc/variant \
  -c -g -o main.o main.cc

You may see some warnings. These are from Symbian SDK header files, not Sourcery CodeBench files.

You can link your application with:

> arm-none-symbianelf-g++ -march=armv5t -mthumb -mapcs -nostdlib \
  -Wl,--target1-abs -Wl,--no-undefined \
  -Wl,-Ttext,0x8000 -Wl,-Tdata,0x400000 \
  -Wl,--default-symver -Wl,-soname,"factorial{000a0000}.exe" \
  -Wl,--entry,_E32Startup -Wl,-u,_E32Startup \
  $epocarch/udeb/eexe.lib \
  -shared -g -o factorial.sym main.o \
  -Wl,"-(" -Wl,$epocarch/udeb/usrt2_2.lib \
  -Wl,$epocarch/udeb/ecrt0.lib -Wl,"-)" \
  -Wl,$epocarch/lib/estlib.dso \
  -Wl,$epocarch/lib/euser.dso \
  -Wl,$epocarch/lib/dfpaeabi.dso \
  -Wl,$epocarch/lib/dfprvct2_2.dso \
  -Wl,$epocarch/lib/drtaeabi.dso \
  -Wl,$epocarch/lib/scppnwdl.dso \
  -Wl,$epocarch/lib/drtrvct2_2.dso \
  -lsupc++ -lgcc -lgcc_eh

This produces a factorial.sym file that can be used by arm-none-symbianelf-gdb.

To run the program on SymbianOS, you must convert this file to EPOC32 format using the elf2e32 command. The elf2e32 command is part of the Symbian SDK and not part of Sourcery CodeBench. If you are using a Linux host, and did not install GnuPoc, you must install Wine and invoke elf2e32 as:

> wine $EPOCROOT/epoc32/tools/elf2e32.exe other options

The following command creates factorial.exe:

> elf2e32 --sid=0x00000000 --version=10.0 --uid1=0x1000007a \
  --uid2=0xe8000075 --uid3=0x00000000 --vid=0x70000001 \
  --capability=none --fpu=softvfp --targettype=EXE \
  --output="factorial.exe" --elfinput="factorial.sym" \
  --linkas="factorial{000a0000}.exe" \
  --libpath="$epocarch/lib"