Developing Series 60 Applications: A Guide for Symbian OS C++ Developers: A Guide for Symbian OS C++ Developers
A miscellaneous set of more advanced build and deployment guidelines is provided here. Some are relevant to working with the emulator, some are for target devices (including some crucial differences between emulator and target hardware). Some information is more relevant to software installation and distribution.
Platform UIDs
Platform UIDs are an essential part of the definition of a Symbian Installation System ( .sis ) package file ( .pkg ) ”they must be included before a Series 60 application is readied for external distribution. Table 2-5 provides a list of current Platform UIDs you can use in your .pkg file to specify the target Series 60 Platforms that are compatible with your application:
Table 2-5. Platform UIDs for Series 60 Platform Versions and Devices
Platform or Product | Platform UID |
---|---|
Series 60 0.9 | 0x101F6F88 |
Series 60 1.0 | 0x101F795F |
Series 60 1.2 | 0x101F8202 |
Series 60 2.0 | 0x101F7960 |
Nokia 7650 | 0x101F6F87 |
Nokia 3650 | 0x101F7962 |
Nokia N-Gage | 0x101F8A64 |
Nokia 6600 | 0x101F7963 |
Siemens SX1 | 0x101F9071 |
It is generally preferable to use the Series 60 Platform UIDs (rather than target device-specific ones) unless your application is only targeted at a very specific phone.
Multiple Series 60 Platform UIDs can be defined in a .pkg file to signify all platforms and devices that an application is able to run on. Use the widest possible number of Platform UIDs for maximum compatibility, but use discretion. Do not use the Series 60 2.x Platform UID unless you have built with the Series 60 2.x SDK.
For a fuller explanation of this requirement, and for up-to-the-minute implementation details, see http://www.forum.nokia.com ”the relevant document is entitled Series 60 Platform Identification Code .
Device Identification UIDs
All Series 60 devices can return a unique identifier UID assigned by the manufacturer. Note that this is not the same as the Platform UID.
Occasionally it may be useful to determine the exact identity of the device your application is being installed on during the process, or at runtime. Both requirements are possible and are described in the next two sections.
A partial list of device UIDs is provided in Table 2-6; however, you may need to refer to the licensee for the UID of a specific device.
Table 2-6. Machine UIDs
Product | Machine UID |
---|---|
Nokia 7650 | 0x101F4FC3 |
Nokia 3650 | 0x101F466A |
Nokia N-Gage | 0x101F8C19 |
Nokia 6600 | 0x101FB3DD |
Siemens SX1 | 0x101F9071 |
Sendo X | 0x101FA031 |
Series 60 1.2 emulator | 0x10005F62 |
Device Identification at Install Time
Determining the exact identity of the device your application is being installed on during the process has a number of potential benefits. For example, it allows decisions about which variants of particular components or files are needed for the specific device. Here is an example section from a fictitious installation package script ( .pkg ) file that shows how you could achieve this conditional installation processing.
IF MachineUID=0x101F4FC3; install Nokia 7650 specific files "\Epoc32\release\armi\urel\N7650.dat" - "!:\system\apps\ExampleApp\N7650.dat" ELSEIF MachineUID=0x101F466A ; install Nokia 3650 specific files "\Epoc32\release\armi\urel\N3650.dat" - "!:\system\apps\ExampleApp\N3650.dat" ELSEIF MachineUID=0x101FB3DD ; install Nokia 6600 specific files "\Epoc32\release\armi\urel\N6600.dat" - "!:\system\apps\ExampleApp\N6600.dat" ELSE ; install option for all other devices "\Epoc32\release\armi\urel\Default.dat" - "!:\system\apps\ExampleApp\Default.dat" ENDIF
Device Identification During Execution
It may be useful to get the exact identity of the device an application is executing on at runtime ”typically you might want to do this early on during the application's initialization. This is possible, and a Symbian OS utility API can provide the device UID ”see Chapter 12 and the section titled Hardware Abstraction Layer for some example code.
Resource File Versions and Compression
Symbian OS 7.0s introduced a resource file compression algorithm that was not present in generic Symbian OS 6.1. However, Series 60 versions prior to version 2.0 implemented its own resource file compression scheme ”a different scheme from that in Symbian OS 7.0s.
Series 60 2.x compressed resource files are not backward compatible with Series 60 1.x.
However, to maintain a degree of forward compatibility, Series 60 1.x resource, .aif , .sis , and bitmap ( .mbm ) files can be used with devices based on Series 60 2.x.
Building for ARM Targets
Building for ARM will in general be more difficult than building for the emulator ( WINS ), and it is normal to find additional compiler errors and warnings from gcc on the first attempt. This is because gcc is, in general, stricter than, say the Microsoft compiler, and also it has some subtle differences that will come out the first time an ARM build is attempted. The following covers a few of the most common pitfalls.
Function Exports
The gcc tool-chain is stricter than WINS builds when it comes to specifying exported functions. The correct way to export a function from a DLL is as follows :
In the header ( .h ) file:
class CMyClass : public CBase { IMPORT_C void Function(); }
and then in the source ( .cpp ) file:
EXPORT_C void CMyClass::Function() { }
The WINS tool chain does not mind if the EXPORT_C is excluded from the CPP file; it exports the function anyway. However, the gcc tool chain requires the IMPORT_C and EXPORT_C to be perfectly matched. If they are not, the function will not be exported from the DLL, which will eventually lead to errors such as " Cannot Find Function " when attempting to link to this DLL.
Writable Static Data in DLLs
Other compilation differences include errors such as the " The MyDll.DLL has (un) initialized data " error arising from the build tool petran . The petran tool strips a PE format file (Win32 Portable Executable file format) of its irrelevant symbol information for an ARM target; thus making DLLs much smaller. As a consequence, ARM targets only support linking by ordinal. Petran is also responsible for adding UID information into the headers of executable files.
The Symbian OS architecture does not allow DLLs to have a data segment (static data, either initialized or uninitialized ). There are fundamental problems in deciding whether a data segment should be used:
-
Do all users of the DLL share it?
-
Should it be copied for each process that attaches to the DLL?
-
There are significant runtime overheads in implementing any of the possible answers.
However, as the WINS emulator uses the underlying Windows DLL mechanisms, it can provide per-process DLL data using " copy-on-write " semantics. This is why the problem goes undetected until the code is built for an ARM-based Symbian OS device.
The associated .map file generated during the build process contains information that helps to track down the source file involved. Look in ..\epoc32\release\armi\urel\dllname.map and search for " .data " or " .bss ". See "Coding Idioms for Series 60" on the Series 60 section of Forum Nokia for more detailed coverage of this topic.
Building and Freezing DLLs
When a DLL is loaded, it supplies a table of addresses, one for each exported symbol and one for the entry point of each exported function. This is the DLL's public interface, and DLLs should freeze their exports before release, so as to ensure the backward compatibility of new releases of a library. This is termed maintaining binary compatibility ( BC ), and the index of each export must remain constant from one release to another.
While you are developing a DLL, you can use the EXPORTUNFROZEN keyword in the .mmp file for the project to tell the build process that exports are not yet frozen. When you are ready to freeze, you must remove the EXPORTUNFROZEN keyword from the .mmp and supply a .def file listing the exports.
Symbian OS uses export definitions ( .def ) files to manage this requirement. Each exported symbol is listed in the exports section of the file with its ordinal number ”ordinals start at 1.
The first time a build is done, a warning may be generated to say that the frozen .def file does not yet exist. Once the project has been completed, and has been built in its release form, you can freeze it with abld by using:
abld freeze
This method will create the frozen .def file containing the project's exported functions. Then, to build an application against the newly frozen interface, enter the following command:
abld build wins udeb | ”for Visual C++ |
abld build winsb udeb | ”for Borland C++ |
abld build winscw udeb | ”for CodeWarrior |
To maintain BC, every export defined in an earlier release must be defined in the new release. Any ordinals for new exports introduced in a new release must come after those defined in earlier releases.
For DLL builds, the command-line tools automatically create the .def file within the build tree for the specified target. Once these have been generated for a build, they can be archived with the project source and used in future builds to freeze the exports against change. This is done by copying the .def files into a default location and including the directive:
DEFFILE projectname.def
into the project .mmp file.
Normally only command-line builds should be released ”note that some of the IDEs now support freezing of exports. In any subsequent command-line build of the project the exports will be guaranteed compatible with the current version.
If new exports are added, the new .def files should be copied from the build directory and archived with the new release.
Note that all ARM platforms share a common .def file, but WINS/WINSCW/WINSB have different .def files.