Distributing software with RiscPkgBy Theo Markettos. Published: 22nd Feb 2005, 15:39:41 | Permalink | Printable
Essential How-to for developersIn a previous article, Graham Shaw outlined what the RISC OS Package Manager is and how it can be useful for finding software and keeping your system up to date. But how do developers package up their software to be used by the system? By packaging and distributing your software with RiscPkg, your users won't have to worry about headaches like installation, downloading the latest support modules and keeping their software up to date. In this article, Theo Markettos aims to find out just how painless it is
Like most RISC OS software, RiscPkg packages are distributed in the form of Zip files. However RiscPkg packages have a fixed structure which enables the package manager to automatically install, upgrade, or remove the contents to or from your machine. This is described in the RiscPkg policy manual which is the ultimate reference on how to create a package, but I shall outline the process here.
In addition RiscPkg supports both binary (the finished program) and source packages. Whilst support for source packages isn't fully complete, in future it will be possible to automatically compile source packages into binary packages, with the result that improvements in compilers or libraries can be rolled out across the entire package database overnight. Imagine how much easier it would have been on the introduction of the Iyonix if all C programs had automatically been rebuilt 32 bit compatible just like that. Of course this doesn't apply to every program (some need human intervention to upgrade the build environment, others in BASIC need no compiling at all), but once finished the feature will be there if it's needed. The Netsurf and Unix Porting projects make use of a similar feature - so updates are automatically reflected in the distribution versions.
Before we start, you'll need a copy of RiscPkg. So download a bootstrap version from RiscPkg Central. Now RiscPkg needs to fetch itself, so run the version you've downloaded, open its window and choose 'Update' from the menu. RiscPkg will fetch a list of packages it knows about. One is RiscPkg - click menu over this and choose "Package 'RiscPkg'->Install". Then choose Commit and a full version of RiscPkg will be installed in Apps.Admin at the same level as !Boot. You can now delete the copy you downloaded earlier. By default RiscPkg puts programs in the <Boot$Dir>.^.Apps - if you don't like the paths where applications go, change them in !RiscPkg.Resources.Paths.
It should be noted that here I describe the full package format - if only trying it out and you don't use the central archive of packages you only need a Control and a Copyright file - but I'll describe some of the features of the full package format along the way. If you want to get involved in packaging, join the mailing list at RiscPkg Central.
A sample package
I've created a sample package based on the classic programming example Hello World. This can be found here. Let's look at the contents of the Zip file. Ours has four directories at the top level: Apps, RiscPkg, Sprites and SysVars.
Firstly we have the program itself, !Hello, which may be found in Apps.Programming in the zipfile. So that RiscPkg can keep track of where everything you've installed has gone, it stipulates certain hierarchies where types of files can go. In this case, Apps indicates it contains an application. Anything below this is specified by the person maintaining the package, so as maintainer I decided that !Hello should go in Programming. If we imagine thousands of packages might be installed by this system, it's best to keep a clean hierarchy.
Layout of our sample RiscPkg package (Download Drawfile version)
If we have documentation which we don't feel should go in the application directory (perhaps our package only contains documentation) we can put it in a top level Manuals directory, but we don't have any in this example.
We must provide information on the licence conditions of our program in a file RiscPkg.Copyright. This states who owns the copyright, where the maintainer obtained the program and the licence it is under.
System variables and sprites
There's nothing special about !Hello, it's just a normal RISC OS program. RiscPkg only cares about the !Run, !Boot and !Sprites files. !Hello does two things: it says hello in a window, and also provides a command *Hello.
So that we don't have to put !Hello on Run$Path, which would cause Run$Path to become very long if every application did it, we set an alias for *Hello to point to the program inside the pplication. RiscPkg specifies that every *command must be implemented in this way. !Hello's !Run file may be seen below
| !Run file for Hello World RiscPkg example
Set Hello$Dir <Obey$Dir>
Set Alias$Hello <Hello$Dir>.!RunImage %*0
TaskWindow -quit -wimpslot 16k <Hello$Dir>.!RunImage
RiscPkg takes special care of system variables and sprites. Applications must specify which variables they use to RiscPkg and their contents by putting them in a textfile in the SysVars directory of the Zip file. This contains one file for each system variable, each holding the value of the variable. For example, Hello's has SysVars.Alias=24Hello which contains:
The idea is that the part in angle brackets is replaced with the actual path of the program on disc when our package is installed, so that we don't have to go around opening Filer windows on hundreds of programs before we can use them. Think of this as RISC OS 4 !Configure's 'Look at' feature, except every program is automatically looked at on startup. Since some characters are not allowed in filenames, we must replace full stop (.), colon (:), dollar ($), ampersand (&), at-sign (@), caret (^), percent (%), backslash () and equals (=) with their hexadecimal value preceded by = as in Alias=24Hello (instead of Alias$Hello).
We do the same for Hello$Dir, the other variable that is set by !Run. !Hello also includes a sprite !hello which we merge into the Wimp sprite pool. RiscPkg also keeps track of sprites, so in the Zip file we have a Sprites directory, which contains one file for every sprite that a package provides to the Wimp pool. So we have a textfile Sprites.!hello (in current versions the filename is case sensitive), which contains:
You might say that RiscPkg managing system variables and sprites is superfluous if they've been properly registered with RISC OS Ltd. On one view it is, but remember that RiscPkg takes care of the bigger picture. What if two applications provide an icon for the same filetype? Or several packages provide different implementations of the same command (BSD Make, GNU Make etc)? RiscPkg needs to know about this.
!Boot is similar to !Run:
| !Boot file for Hello World RiscPkg example
If "<Hello$Dir>"="" Then Set Hello$Dir <Obey$Dir>
If "<Alias$Hello>"="" Then Set Alias$Hello <Hello$Dir>.!RunImage %*0
One thing to ensure is that !Boot never changes variables if they're already defined. There's nothing worse to find that opening a Filer window on an old backup overwrites variables causing the RISC OS 2 copy of an application to run instead of the latest version elsewhere on your system. Ideally this should happen with sprites too, though it's difficult to achieve.
RiscPkg control file
Also in the Zip file lives RiscPkg's control file, which are the key to telling RiscPkg about your application. These is a text file RiscPkg.Control in the Zip - for Hello it has:
Maintainer: Theo Markettos <email@example.com>
Description: A classic program, and an example RiscPkg
Hello provides a classic computer science program. It also demonstrates
how to construct a package for RiscPkg.
These are all detailed in the Policy Manual, but briefly:
- This is the name of the package.
- The importance of the package. This has five levels from Required (necessary for the system to work, eg SharedCLibrary), through Standard (default for a typical user, wanting a small but not too restrictive system, eg Nettle) to Extra (packages with a very narrow audience). Since not that many people are going to want to use !Hello or create packages, we set it to Extra.
- The purpose of the package, which may be Admin, Library (for programming language libraries), Module (RISC OS modules), Programming or Misc (everything else). Other sections may be added in future. !Hello is a programming tool, so goes in Programming.
- The name and email of the person who created the package, who may not be the original software author.
- The version of the RiscPkg Policy Manual referred to when constructing the package. The current version is 0.0.0.0. The last digit refers to insignificant changes in policy (perhaps corrections of spelling errors in the document), so we only specify version 0.0.0.
- The version of the package. This is designed so that when sorted, later version numbers appear after earlier ones. It is composed of three parts as epoch:upstream-package. The upstream version is that of the program as received from the original developers, for example GCC 3.4.4. The package version is the number of the package: you may update the package control file, for example, and this enables you to provide an updated package without altering the upstream version. The sorting ensures that 2.4.9 comes before 2.4.10, and -, +, . and : are allowed in version numbers. The package version is separated from the rest of the rest of the number by a final dash. The epoch is present if it is necessary to replace a larger number with a smaller one - as GCC 2 turned into EGCS 1 which became GCC 3, for example. Here we have !Hello version 1.0 and this is package version 0.
- The name of the source package from which this binary package was generated. In this case we don't have a source package so we omit this line.
- This is either 'Free', meaning packages that meet the Open Source Institute's definition of Open Source, or 'Non-free', that do not. Note that this refers to freedom, not price.
- A short description of what the package is follows this tag. A longer description can be included on successive lines if indented by a space.
Now we get on to one of the key features of RiscPkg. A package can specify other packages on which it Depends (requires), those it Recommends and Suggests. For example:
Depends: WindowManager (>= 3.98), SharedUnixLibrary (= 1.02-1), Tinct
Recommends: Fonts-Unicode (>> 0.01)
Here Netsurf can't work without at least version 3.98 of the WindowManager package (any package version), exactly upstream 1.02 package version 1 of SharedUnixLib and any version of Tinct. Most users will want to install Fonts-Unicode (a later version than 0.01), but it's not obligatory. Finally users could install Printers with it, but Netsurf will work perfectly well without it.
So if you choose to download this Netsurf package, it'll automatically pull in the packages it depends on. RiscPkg can also prompt you whether you want to install the recommended or suggested packages, though it doesn't yet.
On the other hand, there's the Conflicts tag. If we had:
it means that only Justin's MimeMap or only RISC OS Ltd's MimeMap could be present on the system at once. So if you tried to install ROL's, RiscPkg will ask you whether you want to remove Justin's. Imagine you had another package that needed a specific implementation:
Then installing this CDFS would pull in ROL's MimeMap too. But if you already had Justin's installed, RiscPkg would have to uninstall that before it unpacked ROL's. And since dependencies are recursive, CDFS installing MimeMap will bring in SysLog too.
The idea being that you don't have to remember to get all the programs a package needs. RiscPkg is heavily based on Debian Linux, where you can just type...
apt-get install mozilla
...and it goes away and gets the many packages that make up Mozilla, installs them and configures them, asking any pertinent setup questions along the way.
So we zip all that lot up and put it on a webserver. It's a good idea to call the zipfile by the package name and include the version, so I have Hello_1.0-0.zip Now we have to tell RiscPkg what packages we have available. We do this by creating a text file Packages which contains the concatenated Control files of each package separated by blank line. You can see RiscPkg's master Packages list at www.riscpkg.org/pkg/Unstable. So RiscPkg knows where to find the packages we add three lines to each entry in the Package file:
...other entries in the Control file...
This tells us the URL of the package file and its MD5 sum so we can check it hasn't been corrupted on download. The command line tool md5sum can be found in the CLI section of the Unix Porting Project.
Installing our package
We could get our package list integrated into the main RiscPkg packages file, so everyone can download them. But RiscPkg can cope with multiple places to look for package lists, so instead we can upload our package list to a website, say http://www.drobe.co.uk/extra/riscpkg/Testing and add a line in !RiscPkg.Resources.Sources like:
Next time we tell RiscPkg to update, it'll fetch this file and allow us to download the Hello package. To do this, load RiscPkg and then use exactly the same process as you did to install the full copy of RiscPkg itself. You'll find Hello in $.Apps.Programming as we told it.
If I release a new version of Hello, or any other maintainer releases new software, an upgrade is simple. Run RiscPkg, choosing Update, then Upgrade then Commit. Three menu clicks to keep your entire system up to date. What could be easier?
Previous: Acorn Cybervillage update shocker
Next: South West show warm up
DiscussionViewing threaded comments | View comments unthreaded, listed by date | Skip to the end
Please login before posting a comment. Use the form on the right to do so or create a free account.
Search the archives
Today's featured article
Iyonix Review Part One
The hardware, the alternatives, the history.
16 comments, latest by Martyn Fox on 22/4/03 1:01PM. Published: 5 Dec 2002
STRing: Free OCR for RISC OS
Discuss this. Published: 16 Oct 2000
News and media:
RISCOS Ltd •
RISC OS Open •
MW Software •
Advantage Six •
CJE Micros •
Liquid Silicon •
Chris Why's Acorn/RISC OS collection •
The Register •
The Inquirer •
Apple Insider •
BBC News •
Sky News •
Google News •