RISC OS Packaging Project
Policy Manual
Version 0.5.0.0 (11 March 2016)

Introduction

This is the Policy Manual for the RISC OS Packaging Project. It defines the standards which packages are normally expected to meet if they are to be accepted as part of the project. These include:

Rules can be broken where there is good reason to do so, however a consensus must be reached beforehand if other parts of the project are affected.

These rules do not apply to packages distributed independently of the project.

Aims

The aims of the project are:

  1. to build and distribute a collection of RISC OS software packages;
  2. to provide a convienient mechanism for users to install, update and remove packages on their computers;
  3. to promote consistency and peaceful co-existence among packages in the collection by setting policies to regulate their content and behaviour;
  4. to provide a systematic mechanism for recording, characterising and fixing bugs in the package collection;
  5. to ensure that the legal status of all software in the package collection is understood and respected;
  6. to promote the development of free and open source software for RISC OS.

Notation

Extended Backus-Naur Form (EBNF) is used to specify the syntax of data structures. A formal description may be found in ISO/IEC 14977. Briefly:

The meta-identifer ws indicates whitespace:

ws = ws-character, {ws-character};

ws-character = space-character | newline-character;

Package Format

Binary Package Format

A binary package consists of a zip file containing some or all of the following files and directories:

RiscPkg Required A directory which contains information about the package.
RiscPkg.Control Required The package control file, containing information about the package and its relationship to other packages.
RiscPkg.Copyright Required A text file which states where the package was obtained from, who owns the copyright, and how it is licenced.
RiscPkg.CrossPaths Optional A file containing a list of translation rules which identify files to be made available to the cross compiler and specify where they are to be installed.
RiscPkg.Triggers Optional A directory containing files to be run during the install, remove or upgrade of a package. Apps Optional The root of the hierarchy within which applications are stored. A package in a given section normally uses a subdirectory of Apps named after that section.
Manuals Optional The root of the heirarchy within which manuals and other documentation are stored when no other location (such as an application directory) is more appropriate.
Resources Optional A directory which corresponds to the active Resources directory.
Sprites Optional A directory which contains sprite declarations. This has been deprecated from version 0.4.0.
SysVars Optional A directory which contains system variable definitions. This has been deprecated from version 0.4.0.
System Optional A directory which corresponds to the active !System directory.
ToBeLoaded Optional A directory which corresponds to a location on the Boot$ToBeLoaded path (or Boot$Default$ToBeLoaded path on RISC OS 6).
ToBeTasks Optional A directory which corresponds to a location on the Boot$ToBeTasks path (or Boot$Default$ToBeTasks path on RISC OS 6)
Boot Optional A directory which corresponds to the !Boot directory. It is recommended that this directory is used for OS updates only.
Bootloader Optional A directory which corresponds to the SD card system image for the Raspberry Pi (!Boot.Loader). This is for system updates provided by RISC OS Open only.
Diversions Optional A directory that corresponds to the Diversons directory. This is used for Diversions installed with the RISC OS HardDisc image. Apps.Games should be used in preference where possible.
Documents Optional A directory that corresponds to the Documents directory. This has been added for documents installed with the RISC OS HardDisc image. It is suggested that this is used for non-technical documentation and examples files and Manuals is used for more technical documentation.
Printing Optional A directory which corresponds to the Printing directory. This is usually used for installation of components for the RISC OS printing system.
Utilities Optional A directory which corresponds to the Utilities directory. This is used for utilities installed with the RISC OS HardDisc image. Apps.Utilities should be used in preference where possible.
!Boot Optional An alias for the Boot path above.
!System Optional An alias for the System path above.

Each file has an associated logical path (its location within the package file) and a physical path (its location when installed). Only the logical path is specified within the package file. The package manager (on behalf of the user) is responsible for translating logical paths into physical paths, and it has considerable freedom as to how it does this. The only rule is that the translation must be reasonable. For example:

Packages are expected to cope with reasonable translations, and should not make unnecessary assumptions about where their files have been placed.

(For simple desktop applications, the usual practice of defining a system variable of the form App$Dir then accessing files with respect to that variable is sufficient to meet this requirement.)

Source Package Format

A source package consists of a zip file which includes the following files:

RiscPkg Required A directory which contains information about the package.
RiscPkg.Control Required The package control file, containing basic information about the package and its relationship to other packages.
RiscPkg.Copyright Required A text file which details where the package was obtained from, who owns the copyright, and how it is licenced.
RiscPkg.Rules Required The top-level makefile for building the binary package(s).

Although the RiscPkg.Rules file is stated to be required, it is currently permissible to omit this file if the source package exists only to comply with licensing requirements and is not intended to be automatically buildable. However inclusion of a Rules file is recommended, even if its only purpose is to take a set of pre-compiled binaries and place them in a package file.

Control records

Introduction

A control record is a structure used to record information about a package for use by the package manager. There are two types of control record (source and binary) and two types of file in which they can appear (package control files and package index files):

File Content
Binary control file One binary control record
Source control file One source control record; one binary control record for each resulting binary package
Binary index file One binary control record for each binary package
Source index file One source control record for each source package

Package index files list all of the packages that make up a particular distribution, and are the only information available to the package manager (or the user) when deciding which packages to download. Package control files are located within the packages to which they refer, so are only available once those packages have been downloaded. Unlike index file records they are guaranteed to exist whether or not the package is part of a distribution and whether or not it has been superceded by a new version.

Each control record consists of a sequence of control fields:

control-record = control-field, {control-field};

and each field consists of a name and a value, optionally followed by a number of continuation lines:

control-field = control-field-name, ':', space-character,
  control-field-value, newline, {continuation-line};

For example:

Package: RiscPkg
Priority: Required
Section: Admin
Version: 0.2.0

The fields that are allowed or required in a given control record depend on whether it is a source or binary control record, and whether it is located in a control file or an index file:

Name Source Binary Index only Description
Source Required Optional No The name of the source package
Package Required No The name of the binary package
Section Required Required No A label for classifying packages by purpose
Priority Required Required No A label for classifying packages by importance
Licence Required Required No The type of licence carried by the package
Maintainer Required Required No The name and e-mail address of the maintainer
Autobuild Optional No The platform or platforms on which this package can be built automatically
Standards-Version Required Required No The version of this policy manual to which the package conforms
Version Required Required No The version number
Size Optional Optional Yes The size of the package file
MD5Sum Optional Optional Yes The MD5sum of the package file
URL Optional Optional Yes A URL from which the package may be downloaded
Build-Depends Optional No Packages which must be present for this one to be built
Depends Optional No Packages which must be present for this one to be installed
Recommends Optional No Packages which would normally be wanted when this one is installed
Suggests Optional No Packages which might be wanted because this one is installed
Description Required Required No A brief description and a long description of this package
Components Optional No A list of logical paths to components that may want to be moved or added to the boot options

Field names are not case-sensitive, however they should normally be capitalised as in the table above. They must begin at the start of a line and be followed by a colon and a space.

The end of a control record is indicated either by a blank line or by the end of the file.

Values which span several lines are written using continuation lines. These begin with a space (which is automatically removed by the parser). If a blank line is required as part of the value, it is written as a space followed by a period (also removed by the parser):

continuation-line = space, (control-field-value | '.'), newline;

(The space serves to distinguish a continuation line from the start of a new field. The dot serves to distinguish an otherwise empty continuation line from the end of the control record.)

For example:

Package: RiscPkg
Priority: Required
Section: Admin
Version: 0.2.0
Description: A package manager for RISC OS
 The three main functions of RiscPkg are:
 - to download and install new software packages on request;
 - to update installed software packages when new versions are release; and
 - to remove software packages when they are no longer needed.
 .
 If one package requires another in order to run, a request to install the
 first will also install the second.  If a package has been installed
 automatically but is no longer needed, it is removed.

The 'Section' field

This indicates the purpose of the package. It contains one of the following section names:

Section Content
Administration System administration tools
Archive Programs for archiving or compressing data
Audio Programs which operate on sound recordings or music scores
Chat Programs for chat or instant messaging (including protocols such as IRC and ICQ)
Communication Communication programs (excluding those which relate to networks)
Database Databases (both general-purpose and application-specific)
Demo Demonstration programs
Desktop Programs which relate to the mechanics of the desktop
Development Software development tools (including compilers and interpreters but excluding libraries)
Device Device drivers and control software
Disc Programs which operate on discs or filing systems
Document Programs for creating, editing and processing documents (including wordprocessors and desktop publishing programs)
File Programs which operate on individual files or groups of files
Education Educational programs
Emulation Emulators for other machines or operating systems
Font Fonts and programs which operate on fonts
Games Computer games
Graphics Programs which operate on still images (vector or bitmap)
Library Libraries (for any programming language)
Mail Programs which process electronic mail or news messages
Mathematics Mathematical programs (excluding educational ones)
Miscellaneous Packages which do not readily fit into any other section
Network Programs for managing or using computer networks (including both Internet and non-Internet protocols)
Presentation Programs for editing and viewing presentations
Printing Packages which are part of or relate to the printing system
Spreadsheet Programs which operate on spreadsheets
System Packages which are part of or relate to the core operating system
Text Programs which operate on text files (including plain text and generic structured formats such as CSV and XML)
Video Programs which operate on moving images (vector or bitmap, with or without sound)
Web Programs which operate on HTML and related data types (including XHTML but excluding generic XML)

Where reference is made to programs this should be taken to include files of any type which would be used in conjunction with such programs. A more specific section (such as Mail) should normally take precedence over a less specific one (such as Communication).

It is likely that additional sections will be defined in the future. The 'Misc' section is available for packages which would otherwise be difficult to classify. A package may move from one section to another whenever its version number changes.

The 'Priority' field

This indicates how likely it is that a typical user will want the package if they have not explicitly asked for it. It contains one of the following priority levels:

Priority Meaning
Required Packages which are needed for the system (including the package manager) to function correctly. (Example: RiscPkg.)
Important Packages which a user could reasonably expect to be present on any RISC OS system. (Example: SysLog.)
Standard Default packages for a typical user. These should provide a reasonably small but not too limited RISC OS system. Users will normally need to add to this selection to meet their specific requirements, but should find that many of the smaller and more generic applications they want are already present. (Example: Nettle.)
Optional Default packages for a user who wants to install almost everything, without regard for disc space or installation time. (Example: GCC.)
Extra Packages which have a very narrow audience, or which conflict with other packages of higher priority. (Example: LibPkg.)

Packages are assumed to be optional unless there is a specific reason why they should have a higher or lower priority. A consensus should be reached before choosing a priority higher than optional unless there are clear technical reasons why that priority is necessary or appropriate.

A package declared as a dependency must be of equal or higher priority to the package declaring the dependency.

The 'Licence' field

This provides information about how the package is licenced. It consists of a comma-separated list of licence tags.

licence = licence-tag, {',', licence-tag};

Tag Definition
Free Packages that meet the Open Source Definition, as defined by the Open Source Institute
Non-free Packages that do not meet the Open Source Definition

Additional licence tags may be defined in the future. Unrecognised tags should be ignored. The tag list must be complete with respect to the declared standards-version; however, the fact that a tag is absent should not be taken to imply that the converse is true.

If a package has several components with different licences, the most restrictive combination of terms is applicable. If a package offers a choice of licence, the least restrictive option applies. If there is significant doubt as to which tags apply, the more restrictive interpretation of the licence must be followed.

Since only two tags are available at present and they are exact opposites, it follows that packages working to this version of policy must specify exactly one licence tag.

The 'Maintainer' field

This identifies the package maintainer responsible for the package at the time it was issued.

maintainer = real-name, '<', email-address, '>';

The 'Autobuild' field

This is a comma-separated list of platforms which are, or should be, able to autobuild this package:

autobuild-list = autobuilt-platform, { [ws], ',', [ws], autobuild-platform };

autobuild-platform = 'RISCOS' | 'POSIX';

The characteristics of these platforms are described below as part of the build environment.

The list of platforms is nominally considered to be in order of preference, however this order may and probably will be overridden by the autobuilder software to take account of efficiency and availability. If there is a clear technical reason (other than speed of compilation) why the package should be built on one platform rather than another then you should omit the platforms you wish to avoid.

If the autobuild field is omitted then this currently indicates that the package is not suitable for autobuilding on any platform.

The 'Standards-Version' field

This identifies the most recent version of the policy manual to which the package is thought to comply. There are four numeric components to this version, representing (from left to right):

  1. changes to the package format which make packages incomprehensible to existing tools;
  2. changes to the package format which make packages incompatible with previous versions of the package manager;
  3. substantive changes to policy which do not affect compatibility between packages and the package manager.
  4. non-substantive changes to policy.

Because the fourth component does not indicate substantive change, it is sufficient to specify the first three components in the standards-version field.

For example, if the latest version of the policy manual is '0.1.2.3' and a package complies with that version, the standards-version field of the package should be set to '0.1.2'.

Intentional non-compliance may be disregarded provided it does not affect how the package manager should process the package.

The 'Version' field

This contains the package version. It must increase (with respect to the sort order defined below) whenever the content of a package is upgraded, otherwise that upgrade will not be offered to the user.

Versions are discussed in detail in a separate section below.

The 'Size' field

This contains the size of the package file, expressed as a decimal number of bytes.

size = digit, {digit};

The 'MD5Sum' field

This contains the MD5 message digest of the package file, expressed as a hexadecimal number.

md5sum = 32 * hex-digit;

The 'URL' field

This contains an absolute or relative URL from which this package can downloaded. If the URL is relative then it is resolved with respect to the package index file in which it was specified.

The 'Depends' field

This contains a comma-separated list of other packages which must be installed for this one to function:

depends-list = [ dependency, { [ws], ',', [ws], dependency } ];

Each dependency consists of a package name followed by an optional version predicate:

dependency = package-name, [ws, version-predicate];

The version predicate, if present, specifies which versions of the package are capable of specifying the dependency:

version-predicate = '(', [ws], version-relation, [ws], version, [ws], ')';

version-relation = '=' | '<<' | '>>' | '<=' | '>=';

For example:

Depends: LibPkg, RTK (>=0.5.0), ZLib

would cause installation of any version of LibPkg, version 0.5.0 or later of the RTK, and any version of ZLib.

Note the double '&lt' or '>' for strictly less-than or greater-than (which are required for historical reasons).

Small reductions in functionality are not significant: the dependency must be strong enough that the package is of little use without it. For example:

However:

The 'Recommends' field

This contains a comma-separated list of packages which are usually installed alongside this one but are not strictly essential:

recommends-list = [ dependency, { [ws], ',', [ws], dependency } ];

For example:

The 'Suggests' field

This contains a comma-separated list of packages which the user should consider installing alongside this one but could very reasonably decide not to:

suggests-list = [ dependency, { [ws], ',', [ws], dependency } ];

For example:

The 'Conflicts' field

This contains a comma-separated list of packages which cannot be installed at the same time as this one:

conflicts-list = [ dependency, { [ws], ',', [ws], dependency } ];

In most cases this will be because the packages install a file in the same place. For example:

However:

Do not declare a conflict without first investigating whether it can be avoided.

The 'Components' field

This contains a comma-separated list of the components that have extra configuration options:

components-list = [ component-details, { [ws], ',', [ws], component-details } ]

The component-details consists of the the component logical file/folder name and its options:

component-details = file-name, [ws], component_options ;
component-options = '(', { [ws], component_option {[ws] ' ' component-option } ,[ws], ')'
component-option = 'Movable' , 'LookAt', 'Run', 'AddToApps';

The options are all defaults that the user may override when they install the package.

For example:

Components: Apps.Development.!PackIt (Moveable,LookAt)

Packages with the Standards-Version set to 0.4.0 or later will assume that if the Components field is NOT set there are no movable components in the Package

It is expected the use of the Components field replaces the SysVars and Sprites package control folders. If the package requires system variables and sprites to be loaded you would normally specify the LookAt option so the application is booted when the desktop is started. It is suggested that if the component isn't providing command line utilities or support for a file type that SysVars and Sprites are just removed and the LookAt option is not set.

The Copyright file

Every package shall contain a text file named Copyright in its RiscPkg directory. No specific structure is required, but it must contain the following information:

(Note that without a distribution licence it is highly unlikely that a package can be distributed.)

The Triggers directory

A package can optionally contain runnable files in the Triggers directory in its RiscPkg directory that will be run as part of the commit (installation, removal or upgrade) of a package.

Triggers should be used only when necessary and should be avoided in most cases as:

It is always better to do any special actions when an application is first run rather than relying on triggers.

The following names are used by code in the Triggers directory.

File Description
PreInstallRun before a package is installed.
PreRemoveRun before a package is removed.
PostInstallRun After a package has been installed.
PostRemoveRun After a package has been removed.
It is only necessary to add the files for the triggers required.

Other code can be added to the Triggers directory and this will be available when the triggers are run. This allows for triggers to use shared code etc.

The code can be any executable code and is run in a background TaskWindow with a WimpSlot of 256K. If logging is turned on, any output from the trigger is added to the Log.

A triggers operation should not rely on any other trigger having been run and it should allow for cases where it may be called multiple times.

Information is passed to and from a Trigger using system variables prefixed PkgTrigger$.

At the minimum a trigger must set PkgTrigger$ReturnCode to 0 if a trigger succeeds or to 1 if it fails. On failure PkgTrigger$ReturnText can be set to give the error message, which may then be logged/reported by the package manager.

The full set of variables are:

Variable Description
PkgTrigger$Action The current action, see below:
PkgTrigger$Abort 0 or 1. If set to 1 this trigger is being run to unwind a previous trigger failure.
PkgTrigger$OldVersion The version of the package being removed or "" if it's an install.
PkgTrigger$NewVersion The version of the package being installed or "" if it's being removed.
PkgTrigger$Dir The directory the trigger is being run from. Use this as a prefix if running other code in the Triggers directory.
PkgTrigger$ReturnCode The return code from the trigger, should be set to 0 for success or 1 for failure.
PkgTrigger$ReturnText Set to a brief error message it the trigger fails.
PkgTrigger$Path<n> <n> is a number from 1 upwards. These variables contain the path to the components in the package.
PkgTrigger$S_* Variables prefixed PkgTrigger$S_ are shared variables that exist for the lifetime of the current package commit and are deleted after the commit has finished. They are used so state can be shared between triggers. It is advisable to use the package name in the variable name to avoid clashes with triggers from other packages.

The PkgTrigger$Action can be:

ActionDescription
installThe package is being installed.
removeThe package is being removed.
upgradeThe package is being upgraded.
abort-removeThe trigger is being run as a remove failed.
abort-installThe trigger is being run as an install failed.
abort-upgradeThe trigger is being run as an upgrade failed.

The triggers are called in the following order for an install.

If PreInstall fails the package is not installed. If PostInstall fails the package is still installed, but a warning is shown.

The triggers are called in the following order for a remove.

If PreRemove fails the package is not removed. If PostRemove fails the package is still removed, but a warning is shown.

The triggers are called in the following order for an upgrade

The "old-" prefix indicates the trigger from the old package is run. The "new-" prefix indicates the trigger from the new package is run.

If old-PreRemove fails

If new-PreInstall fails

If old-PostRemove fails and is not part of an abort the upgrade completes, but a warning is shown.

If new-PostInstall fails and is not part of an abort the upgrade completes, but a warning is shown.

The Rules file

Introduction

Every source package should contain a makefile called RiscPkg.Rules containing instructions for building the corresponding binary package(s). These should be placed in the RiscPkg directory and have names of the form:

binary-leafname = binary-package-name, '_', version-number;

for example LibPkg-Dev_0/2/1 (on a RISC OS machine) or LibPkg-Dev_0.2.1 (on a POSIX machine).

All binary packages are to be built when the makefile is invoked with no target or with the target 'all'. (Typically this would be achieved by making 'all' the default target.)

The Rules file should assume that the current working directory is at the root of an unpacked copy of the source package. Typically the command that invokes it will be of the form:

make -C <source-package-root> -f RiscPkg/Rules

It may also assume that it has ownership of all files and directories at or below this root, and that any file permissions are no more restrictive than the following:

Filesystem File permissions Directory permission
AFS rlidwk rlidwk
RISC OS WR/ WR/
POSIX 044 055

It is recommended that the Rules file seek to avoid altering any file that is part of the supplied source package, in order to avoid creating differences which might be inadvertently checked back in to the revision control system; however it is recognised that this may not always be practicable when packaging software that was created by a third party.

The Rules file must not attempt to read or modify any file or directory outside the root of the supplied source package, unless it is either (a) a defined part of the build environment or (b) a file made available by a build-time dependency, in which case it may read from the file but not alter it.

The CrossPaths file

The package file format is primarily designed for installing software on RISC OS machines, however in some cases there is also a need to make it available to a cross-compiler running on a POSIX-based operating system. This is done by including a CrossPaths file in the RiscPkg directory of the relevant binary package.

Each line within the file consists of two pathnames separated by whitespace. The first is a logical pathname which identifies a file or set of files in the binary package which are to be copied. The second pathname specifies where those files are to be placed. It too is a logical pathname, but using a different set of conventions that are better suited to the way files are organised on a POSIX system. The following paths are defined:

include A location that the cross-compiler will search for header files.
lib A location that the cross-compiler will search for libraries.

Wildcard variables may be used to copy many files with a single rule. These consist of a percentage sign followed by a decimal digit, and match any sequence of zero or more characters within a single pathname component (but not sequences which span multiple components). The variable should appear in both the source or the destination path. Wildcards can be used to translate between RISC OS and POSIX-style naming conventions, for example:

Apps/Library/!LibPkg/libpkg/h/%1 include/%1.h
Apps/Library/!LibPkg/a/%1 lib/%1.a

You should include a CrossPaths file within any binary package that contains files which could potentially be needed by the cross-compiler, whether or not that package is itself capable of being built using the cross-compiler.

Versions

Structure

Versions have three components:

version = [epoch, ':'], upstream-version, ['-', package-version];

epoch = {digit};

upstream-version = {letter | digit | '+' | '-' | '.' | ':' | '~'};

package-version = {letter | digit | '+' | '.' | ':' | '~'};

Only the upstream version is required. This should match the version of the upstream project if there is one. (Upstream is the source from which the software was obtained for packaging.) For example, if you are packaging the version of Nettle released as '0.2040r' by the Nettle Developers then the upstream version would be '0.2040r'.

If there is more than one level of upstream development, you should typically choose the furthest upstream version consistent with the name of the package. For example, if you are packaging version 2.95.4 release 3 of the RISC OS GCCSDK and the package is named GCC, the upstream version would be 2.95.4 and the release number would become part of the package version. However, if the package has instead been named GCCSDK then the upstream version would be 2.95.4r3.

Changes can be made to avoid illegal characters or ensure that the sort order is correct. Some common cases are described below.

The package version allowes for the possibility that a given upstream version will be packaged (or ported) more than once. Typically it should start at zero each time the upstream version changes and increment each time there is no change. A more complex scheme can be used if it is considered useful.

The epoch allows for major changes (or mistakes) in the numbering scheme which would otherwise disrupt the sort order. It should notionally begin at zero, then increment each time the upstream version needs to move backwards. While the epoch is equal to zero it should be omitted entirely.

Changes to the epoch should be rare and unplanned events. If the upstream version scheme makes epoch changes inevitable then it must be modified to prevent this happening.

The sort order

The epoch is the most significant component, followed by the upstream version then the package version.

Components are compared by dividing them into an alternating sequence of numeric and non-numeric sections. The first section is defined to be non-numeric (so will be empty if the component begins with a digit).

Non-numeric sections are compared lexicographically using ASCII values, modified so that letters sort earlier than non-letters, and so that the tilde character sorts earlier than anything else (including the empty string). Numeric sections are compared numerically. If a numeric section is empty then it is taken to be equal to zero.

Sections are compared from left to right until a difference is found or until both components are exhausted.

(This sort order is intended to be the same as that specified in version 3.8.0 of the Debian Policy Manual. If any difference is found between dpkg, RiscPkg or the two policy manuals it should be reported as a bug.)

Ensuring the sort order

If the upstream version incorporates a date then the year must precede the month and the month must precede the day. Formats with a suitable sort order include '1999.9.27', '1999.09.27' and '19990927'.

If the upstream version contains a suffix such as '-pre2', '-test5' or '-rc12' then this may be moved out of the upstream version and appended to the package version. It will then have no effect on the sort order (because the remainder of the package version will always take precedence) while remaining visible to the end user.

If the suffix remains attached to the upstream version then it is not possible to remove the suffix when a final release is available without disrupting the sort order. This can lead the user to believe that the package is less mature than is actually the case.

File attributes

Each files in a binary package must have a RISC OS extra information field.

This specifies the file type, timestamp and file attributes. It has a zip file tag of 0x4341. Most zip file compressors written for or ported to RISC OS provide this field automatically. Those intended for other operating systems more likely do not.

File attributes should be set to LR/r for static files and either WR/wr or (preferably) WR/r for variable files. Packages should not assume that the attributes are set to these values when the files are installed.

The purpose of this rule is not to force any particular attribute policy on the installed files, but rather to ensure that the package manager is aware of what permissions are needed for the system to function correctly. If the user wants all files to be writable then it is a straightforward matter for the package manager to force the attributes to WR/wr during installation, whereas it would not be able to do the opposite.

It has not been decided how the package manager will distinguish between files which should disappear when a package is removed and files which should remain until it is purged, however it is possible that file attributes will be used for this purpose.

System variables

The use of System variables has been deprecated with Standards-Version 0.4.0 and above. It is recommended that the LookAt option in the Control files Components field is used to Boot an application to set any variables required.

Ownership and definition

A package may claim ownership of a system variable by including a file named after the variable in its SysVars subdirectory. An escape mechanism is provided to allow for characters which have special meanings in RISC OS pathnames. To use it, replace the character with an equals-sign followed by a two-digit hexadecimal character code.

The following characters (and no others) must be escaped: '.' (full-stop), ':' (colon), '$' (dollar-sign), '&' (ampersand), '@' (at-sign), '^' (caret), '%' (percent-sign), '\' (backslash) and '=' (equals-sign).

The following filetypes are allowed:

Filetype Content
Text A parsed string with which to initialise the system variable.
Data An unparsed string with which to initialise the system variable.

All other filetypes are reserved for future use. If a string is parsed then this is done by OS_GSTrans or an equivalent, with the addition of support for logical pathname references (as described below).

Note that this mechanism does not replace the need to set system variables in !Boot and !Run files.

Use of Run$Path

Packages should not change Run$Path simply because they provide one or more command line programs. Aliases of the form Alias$command should be used instead.

The Run$Path would soon become very long if every command line program were to extend it. This would make the system less efficient and could eventually break it.

Desktop applications

The !Boot file

The !Boot file must be idempotent (meaning that the result after executing it twice is the same as the result after executing it once.)

The actions performed by a !Boot file should be limited to the following:

System variables with previously set values should not be altered.

Ideally the !Boot file would not replace existing sprites either, but it is not obvious how this could be easily achieved.

The !Run file

If the application needs a system variable to be set to a particular value then the !Run file should forcibly set that variable to the appropriate value.

For example, most applications use a variable of the form App$Dir to access support files within their application directories. Ideally applications should not clash — but if they do then the correct behavior is to use the value appropriate to the application that is currently running. The variable is not intended to be user-configurable, so this action is unlikely to override a value set by the user.

If the application needs a system variable to be set to a meaningful value, but there is more than one value to which it could usefully be set, then the !Run should provide a reasonable default but should not overwrite an existing value.

This allows configuration to be performed by setting system variables at boot time, as opposed to editing the !Run file. The latter method is undesirable (a) because the !Run may be shared between several users or machines, (b) because the application directory cannot be made read-only, and (c) because the system variable cannot be shared between applications.

Sprites

The use of the Sprite declarations has been deprecated with Standards-Version 0.4.0 and above. It is recommended that the LookAt option in the Control files Components field is used to Boot an application to load any sprite that are required.

Sprite declarations

The package manager has the ability to load sprites into the Wimp sprite pool at boot time. For this to happen the sprite must be declared. A package can do this by placing a file named after the sprite in its Sprites directory.

At present the file must be a text file, in which case it contains the pathname of the sprite file that contains the sprite. The pathname is parsed using OS_GSTrans or an equivalent, with the addition of support for logical pathname references (as described below).

Only one sprite may be specified per declaration, however any number of declarations may refer to a single sprite file.

Sprite resolution

The sprite file identified by the pathname should be one that is suitable for use as an argument to the IconSprites command. If higher-resolution versions of this file are present then they will be recognised automatically by the package manager, provided that the conventional suffixes are used. For example, if a package provides sprite files called !Sprites, !Sprites22 and !Sprites11 then declarations should refer to the first of these only, but one of the others will be used if it is a better match to the screen mode.

Command line programs

The preferred method for distributing command line programs is to encapsulate each one within a separate application directory, then set an alias of the form Alias$command to make the program available from the command line.

The alternative of placing all command line programs in a central location would work acceptably for stand-alone executables, but provides nowhere for supporting documentation and other files to be located. Use of an application directory was thought to be more in keeping with the RISC OS tradition of keeping associated files together where possible.

Where there would be no advantage in a command having its own graphical front end, it is permissible for it to share an application directory with other programs.

At its simplest, the application directory would contain !Boot and !Run files to set system variables, a !Sprites file to provide an icon, the executable itself, and documentation within or referenced by a !Help file. Other files may be added as required.

Provision of files for use by the FrontEnd module is encouraged. Provided they are reasonably small (as is likely to be the case) they can be bundled into the same package as the executable. More elaborate graphical front ends should in most cases be packaged separately.

Logical Pathname References

When specifying the content of a system variable or the location of a sprite file it may be necessary to translate a logical pathname to a physical pathname. This is done using an extension of the syntax implemented by OS_GSTrans:

logical-pathname-reference = '<', package-name, '$', '@', logical-pathname, '>';

For example, the logical path Apps.Admin.!RiscPkg within the package RiscPkg would be expressed as:

<RiscPkg$@Apps.Admin.!RiscPkg>

Only pathnames can be processed in this way. If a path is required then the trailing period must be placed outside the logical path reference:

<RiscPkg$@Apps.Admin.!RiscPkg>.

Module packages

A module package is a package that just contains a single RISC OS module that will be installed into the !System modules directory.

It can contain a single module in the appropriate subdirectory of !System and optionally some documentation to be installed in the root Manuals directory.

The package name should be the full name of the module (the module title) and the version must match the version number of the module followed by a dash and the package number (starting with 1).

e.g. For a module in file MyMod with a title MyModule and version 1.11, the package name should be MyModule and the version should be 1.11-1.

If the versioning rules are followed the packaging system will detect if a newer existing version of the module already exists on the machine and use that instead of the package when the module package is installed.

Build Environment

Introduction

The build environment is the set of tools, libraries and other resources that are external but available to a source package while it is being built. There are two parts to the build environment:

The latter category is provided so that it is not necessary for large numbers of source packages to declare their need for basic facilities such as Make or GCC. Binary packages which provide such resources are described as 'build-essential&rsqup;.

Two different build platforms are defined, RISC OS and POSIX, and there are differences between them. Ideally source packages should be written so that they can be compiled on either, however it is recognised that this is impractical in many cases.

Build-essential packages

The following packages (or their equivalents) are build-essential when using RISC OS as the build platform:

Name Version Description
DiffUtils 2.7 A set of tools for comparing files
DRLink 0.44 AOF linker
FixDeps 1.0.2 A filter for processing makefile dependencies
FileUtils 4.1 GNU file management utilities
G++ 3.4 The GNU Compiler Collection (C++ compiler)
GCC 3.4 The GNU Compiler Collection (C compiler)
Ld-GCCSDK 0.44 A GNU-compatible front-end for Link or DRLink
LibFile 1.01 ALF creation and maintenance tool
Make 3.80 The GNU Project implementation of Make
Patch 2.5.4 A tool for applying diff files
Perl 5.8.8 The Perl programming language interpreter
RiscPkg-GenControl 0.0.0 Binary control file generator for RiscPkg packages
Sed 4.0.9 The GNU stream editor
UnixLib-Dev 4.6 A C run-time library for RISC OS
Unzip 5.52 A decompressor/dearchiver for zipfiles
Zip 2.3 A compressor/archiver for creating and modifying zipfiles
UUDecode 4.2.1 UU and base-64 file decoder
UUEncode 4.2.1 UU and base-64 file encoder

When using a POSIX-based system as the build platform, equivalent functionality should be provided, typically by installing GCCSDK, with the exception of FixDeps. (The functionality of FixDeps can be achieved using Sed on a POSIX-based system.)

The versions specified are the minimum allowed. Higher versions may be used provided that they are fully backwards-compatible. The method of installation for this software is unspecified: it is not necessary to use RiscPkg (although it would be sensible to do so where the build platform is RISC OS and the necessary packages are available.)

Source packages should not attempt to test whether they are being built on RISC OS or POSIX; instead, they should determine whether the build platform provides the specific feature that is required.

It is not necessary to write fully portable makefiles, as you can assume that Make will be compatible with the GNU Project version.

Environment Variables

The following environment variables may/shall be set by the autobuilder before invoking the Rules file of a source package:

RISCPKG_BUILD_GNU_CPU_FAMILY Required The name used by the GNU toolchain to identify the target CPU family (currently always 'arm').
RISCPKG_BUILD_GNU_CPU_TYPE Required The name used by the GNU toolchain to identify the specific target CPU (for example 'strongarm' or 'xscale'), or undefined to indicate that the compiler defaults should be used.
CPPFLAGS Optional Flags to be passed to the C preprocessor.
CFLAGS Optional Flags to be passed to the C compiler. These will include instances of 'mtune' and 'mcpu' if appropriate.
CXXFLAGS Optional Flags to be passed to the C++ compiler. These will include instances of 'mtune' and 'mcpu' if appropriate.
LDFLAGS Optional Flags to be passed to the linker.

Bugs

If you encounter a bug in a package on which you depend, either at run-time or build-time, then you should either wait for the bug to be fixed or put in place a workaround that allows the package to be built with or without a fix. Do not install a workaround which is likely to break when the bug is corrected, as this will unnecessarily complicate the process of fixing it.

Acknowledgements

Significant aspects of this policy manual are based on the Debian Policy Manual, written by Ian Jackson and Christian Schwarz.

Copyright

This manual is part of the RISC OS Packaging Project.

Copyright © 2004-2016 Graham Shaw.

Update from version 0.4.0 onwards © 2014-2016 Alan Buckley.

Distribution and use are subject to the GNU General Public License, as published by the Free Software Foundation.