The Mozilla
Organization
Our Mission
Who We Are
Getting Involved
Community
Editorials
What's New
Development
Roadmap
Module Owners
Blue Sky
Projects
Status
Tools
Products
Source Code
Binaries
Documentation
License Terms
Bug Reports
Search
Feedback


Dependent version checking

This memo is a proposal for a mechanism that allows cooperating components to divulge their own versioning information and compare that to their import requirements. In order for this to be effective, all cooperating component libraries have to include certain capabilities (defined below).

This mechanism's goal is to provide definitive proof that the product environment (made up of one or more shared libraries) is consistent within itself. It does not provide static checking that might cause ungraceful termination of an application. Nor does it provide early detection of inconsistencies such that might be used to drive selective loading of shared libraries.

Version information

Software components can be identified generically by name (regrettably I don't know anything better than ASCII). For simplicity the version of the software component may also be identified by an ASCII string. The string's content is not significant since (as will be described later) only the component presenting the version string need understand its makeup.

Discovering a component's identity and version

A component will advertise it identity and version through use of static defines in a well-know header. Using NSPR as an example, these constants might show up in a header named prvrsion.h and look like:
#define PR_NAME     "NSPR 2.0"
#define PR_VERSION  "199770530"
Note: It would be expected that the name of the component ("NSPR 2.0" in this example) would not change for the lifetime of the product.

Along with these two constants, each component must provide a function capable of returning a boolean answer indicating that available library is compatible with the expectations of the caller. That function has a signature as follows:

typedef PRBool (*version_check)(const char *imported_version);
The importer would literally code this call as (using NSPR as an example):
    if (!PR_VersionCheck(PR_VERSION))
    {
        ...version check fails...
    }
    
At the time a version check routine is called the code should evaluate the string passed in as the argument with the version the library is exporting. This string will contain the literal value that was defined by environment in which the importing component was built. The called function will compare the string to the value known to it, which represents the value captured at its build time. During the execution of the version check function is the opportunity for the called component to verify its dependencies as well. The answer returned will be the logical union of all the responses.

Caution: Circular dependencies could be a problem.

Version Embedding Specification

Introduction

A complicated product or suite of products can require a huge number of shared libraries. Over time, each of these libraries is patched numerous times. One of the most pressing questions when debugging a field escalation is "What versions of the libraries are installed?". Often, problems can be attributed to wrong installed versions, incompatible versions, etc. So, what remains is how to answer the question "What libraries are installed?". This specification proposes a mechanism for answering that question.

Background

Windows NT long ago addressed this issue by the use of standardized version resources embedded in libraries. The NT installer uses these version numbers when making decisions as to whether or not to overwrite libraries. This proposal allows for similar capabilities on a wider variety of platforms.

Mechanism

We define a C structure to contain version information. We then define a well-known function that all libraries should expose. We also define a naming convention for the instances of the structure to aid in locating them in a core file.

Version structure

The structure we use is listed below. The first field is intended to allow future extensions to this specification. Version 2 of the body is listed below. If the version is not 2, no statement is made about the contents of the body at this time. Time is expressed in the format exposed by NSPR's PRTime. Special builds are intended for non-RTM builds. This could be a private patch, a prototyped change, etc. If special is true, the specialString should be set. All strings are optional, and should be set to NULL if not utilized.
    #include <prtypes.h>
    
    typedef struct {
        PRInt32     version; 
      
        PRTime      buildTime;
        char *      buildTimeString;
      
        PRUint8     vMajor;
        PRUint8     vMinor;
        PRUint8     vPatch;
      
        PRBool      beta;
        PRBool      debug;
        PRBool      special;
      
        char *      filename;
        char *      description;
        char *      security;
        char *      copyright;
        char *      comment;
        char *      specialString;
    } PRVersionDescription;

The PRVersionDescription does use NSPR's typing and type semantics, though is not dependent on NSPR 2.0. There are, however, utilities available for accessing the information defined by the structure, and they do utilize features of the runtime. Some caution should be taken regarding this apparent circular dependency.
version The version of this structure. This memo documents Version 2.
buildTime The time the library was built, expressed as a PRTime. PRTime's are 64-bit signed numbers representing the number of microseconds since midnight, January 1, 1970 GMT.
builtTimeString Another representation of the build time, but in human readable form.
vMajor The major version number of the library. Theoretically, this field will change value if and only if there are incompatible changes in the library's API.
vMinor The minor version number of the library. Changes in this field indicate that the library's content has changed in order to correct deficiencies or possibly add new features. Changes to do not affect previous API, but might add new. All changes are backward compatible with libraries of lesser minor versions.
vPatch The patch level of the library. Patches may be applied to correct deficiencies, but the result will be both backward and forward compatible.
beta This library is a beta release. That it is not certified to be product ready.
debug The library has been built with debugging options enabled. This implies that the library contains debugging symbols and may contain an arbitrary amount of other checking code to assist in a development effort.
special The library is a special build for some special purpose. See also specialString.
filename The root filename of the linked library.
description An arbitrary string describing the component library.
security The level of security of this component.
copyright Textual synopsis of the Copyright information.
comment Free form field for miscellaneous usage.
specialString Yet another free form field, but for special usage.

Interface

All components supporting the version protocol must expose a C function named libVersionPoint.
const PRVersionDescription *libVersionPoint(void);
All components should also expose their PRVersionDescription structure using the following naming convention.
Take the filename field from the structure. Convert non-alphanumeric characters to "_". Prepend "PRVersionDescription_". Use this as the name.
So, for libfoo.so, the name would be PRVersionDescription_libfoo_so.

If the filename field is not set, take PR_Now() and print it using PR_snprintf(). Append this to "PRVersionDescription_". The first form is the preferred form.




Last updated: Wed Jul 23 16:28:40 PDT 1998

Copyright © 1998 Netscape Communications Corporation



Copyright © 1998 The Mozilla Organization.