It is important for users that the software they buy and use should continue to run on new releases of Symbian OS, and that it should be transferable to new devices containing the latest releases of the operating system.
Ensuring that a current software release does not break existing software is known as maintaining binary compatibility (BC). There is a related compatibility issue for data — ensuring that new software versions remain data compatible with previous versions. Data incompatibilities can be just as galling for software users, making existing documents obsolete, but don't intrinsically affect the software itself.
BC is most obviously a concern for the systems developers responsible for the evolution of the operating system. However, it is relevant for any developer whose software provides services to client software. Developers whose software uses such services should understand a problem that potentially they may encounter.
A related concern is where a program is first developed using a version of some system component or a third part service. Developers may need to know whether their programs will also work with older versions of that system component or third part service. This form of compatibility is an added bonus but, generally, backward compatibility is the overriding requirement.
When a software component is changed, the changes impact all dependent software components — including the ones which have not yet been written. This means that rather than relying on testing, the safety of changes must somehow be guaranteed.
A component which defines an interface through which it may be used should be regarded as making a contract with the rest of the world. Its interface is its contact. Other components which build against its interface must be guaranteed that when they later run against its interface, nothing will have changed. The BC requirement is that guarantee.
Although in principle there are many different mechanisms through which software can offer an interface to clients, in the Symbian software platform, BC is a DLL related problem.
BC is stronger than both link and source compatibility. Maintaining BC also implies that both link and source compatibility are maintained.
Source compatibility describes the situation where an interface we are using has changed between building against it and running against it, in such a way that we can only recover by rebuilding against the changed interface. Our source need not change, but we must rebuild.
Because source level interfaces are defined in the published header
#include
files, it is easy to see whether changes are compatible
— examine the changes to the header file.
Link compatibility describes the situation where to recover from an interface change we must relink our component against a component we originally built against. Our source need not be rebuilt, but we must relink.
Link level interfaces are defined by the published import library. Again it is not too hard to see whether a change is compatible — ensure that all exported functions are unchanged.
Binary compatibility guarantees a constant interface between our building and running against another component.
The BC level interface is not so easy to define and may include quite general behaviour of the changed component. Because it is hard to define it is hard to check for changes which potentially break it. Potential BC breaking changes include:
Virtual member functions are for life — you can't add or remove virtual member functions
or change the virtuality of a function
or change their declaration order
or override an existing function that was previously inherited
You cannot add a UID if was originally omitted from the DLL
Safe changes which preserve backward binary compatibility include:
Any name can be changed but — this requires
clear documentation because dependent components must change source code, and
usually also requires editing the frozen .def
files
Adding services — classes, global functions, static and non-virtual member functions can all be added to a shared library
Changing access specification — any member can be made more widely accessible. The reverse is not allowed. Similarly, friendship can be bestowed but not withdrawn
You can do what you like with private data and non-virtual function members except — when it would change the class size, or when effectively public data would move in the class
Parameters and return values — valid inputs must retain their interpretation and existing output values must retain their meaning
Inputs can be widened: e.g. less derived pointer, extended enum, adding a const qualifier or outputs can be narrowed: e.g. more derived pointer, fewer error code values, removing a const qualifier
Pointer and reference types can be exchanged
To help maintain BC only release what you need to release — you don't have to support what you don't release
Some potentially BC breaking changes are introduced not by developers but by the build system. Symbian OS provides tools which help to control BC by blocking accidental build-time changes.
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. To preserve BC the index of each export must remain constant from one release to another.
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, which is calculated as index + ordinal base.
Symbian OS uses an ordinal base of 1. By the definition of source compatibility
implied by BC, every export defined in an earlier release will be defined in
the new release. Exports introduced in a new release must come after those
defined in earlier releases.
For DLL builds, the build 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
in the project .mmp
file.
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 once again be copied from the build directory and archived with the new release. Only command-line builds should be released.
The creation and translation of .def
files is managed
by the Symbian OS build process, see
How to use the Symbian OS build process.