Other pages on this website have discussed how you would go about running a build that’s already been perfected, but what if you want to tweak it, or create a new one from scratch? That’s what this page is here to help you with.
Before we start, a quick word about the term component, which you’ll see used all over the place. Broadly speaking, a component is a program built for the target platform, usually a module or an application, although it can also be an executable file (usually a build tool) or a library. The kernel and HAL are two special-case components.
The term is applied slightly differently for source control and building purposes.
VersionNumfile (and sometimes a
VersionASMfile) in the root directory of what’s considered a component for source control purposes.
VersionASMfiles are automatically maintained when you commit changes to the repository using the perl script
COMPONENTvariable passed into the Makefile on the command line (this is all managed by the build system, only the author of the Makefile need be concerned about it).
A good example of both of these is the USB system.
RiscOS/Sources/HWSupport/USB/NetBSD contains the
VersionNum file, and you’ll note that most of the CVS tags are of the form
NetBSD-n_nn. But the Makefile is a level lower than this, in
RiscOS/Sources/HWSupport/USB/NetBSD/build. And the same Makefile is used to build three components:
If this seems complicated, don’t worry – the vast majority of components use neither of these tricks, and the source control component is the same thing as the build component.
The files in
RiscOS/Env are a collection of Obey files; you need to run one of these to set up critical paths and system variables, and load support modules needed to perform a build. When you select an option from the “Environment” menu in !Builder, you’re actually running one of the Env files.
Much of the work is done by
RiscOS/Env/!Common, but it is unlikely that this will need to be changed. Each of the other Env files set up a small number of system variables that define what is unique about the build. These system variables would otherwise end up being build-time options for multiple components, so having them set globally helps maintain consistency across the build.
Locale: determines the language of resources files installed.
Keyboard: which keyboard handlers (layouts) are built in – often “
All” for desktop builds. A bit of an oddity in that it’s really only an option to the InternationalKeyboard module, but placing the option here enables a single Components file to be shared by variants of the same product aimed at different international markets.
Machine: selects a variant file in Hdr:Machine which sets an assembler variable. Used to switch between different IOMD hardware variants, so now deprecated in favour of the HAL. Normally use “
32” here; Tungsten was an exception among HAL machines, because it contains a partial implementation of IOMD for the podule bus.
System: specifies general properties of the kernel (such as stack formats) for the benefit of modules. Generally deprecated, use “
Ursula” if you’re creating a new Env file.
UserIF: specifies a theme for resource files. Each embedded customer generally wants their own theme, ROOL currently only distributes a few distinct desktop themes, called “
Ursula” and “
Display: generally useful only for embedded products. Determines whether 50Hz (
PAL) or 60Hz (
NTSC) TV outputs are selected. Even some embedded products ignore this and read a setting from NVRAM.
ImageSize: sets the size of the ROM image as a whole. All modules in a ROM image must fit within this size, and any spare space is padded out. Not relevant for disc builds.
HALSize: sets the size of the HAL that’s in use. Without this information the HAL won’t know where the OS image is inside the ROM, and the OS image won’t know how large it should report itself as being. Not relevant for disc builds.
Build: sets which Components file to use. See next section. Often of a similar if not identical name to the Env file.
APCS: currently the procedure calling standard should be “
Many of these are used in source code directly – for example, you’ll see widespread use of
GET Hdr:APCS.<APCS> in assembler source files. However, you should generally not do this for
Locale because it’s undesirable to fill the source tree with lots of duplicated resource files when typically only a small number of them need to be translated, especially for embedded products. So instead use
LocalRes: to access non-themable language-specific resource files and
LocalUserIFRes: to access themable language-specific resource files. These paths are both set up by !Common.
All of ROOL’s Env files are stored inside
RiscOS/Env/ROOL for namespacing reasons.
The files in
RiscOS/BuildSys/Components are text files, the input to the
srcbuild program which is the back-end to
!Builder. They are essentially a recipe for a ROM build or disc build – it says which components need to be included, which libraries and header files are required by those components, and what build switches need to be applied to those components.
Because one Makefile can build multiple components, components are not referred to directly by path, but instead by a unique symbolic name. These names are looked up in the file
RiscOS/BuildSys/ModuleDB, which provides not only the location of the Makefile, but information about which build phases should be applied to the component:
ASM: typical assembler module, may be called with any build phase (clean, clean_all, export_hdrs, export_libs, resources, rom, install_rom, install or bbe)
BAS: currently functionally equivalent to
ASM, but used when the component is written in BASIC rather than assembler
C: same as
ASMexcept that rom_link phase is used instead of install_rom phase
RES: only clean, clean_all, resources, install or bbe phases used – intended for components consisting of resources files which don’t need to be compiled or assembled, merely copied into ResourceFS (in the resources phase) or the disc image (install phase)
EXP: only clean, clean_all, export_hdrs and export_libs phases used – intended for components that provide header files and/or libraries
DATA: after the module chain, a ROM can include one or more binary blobs, typically at fixed addresses; these
DATAcomponents are called with the same build phases, but aren’t linked into the module chain
BBE: use for pure BBE components such as
RiscOS/Library– only ever called by bbe phase
KERNEL: there must be exactly one of these in a main ROM build and none in an expansion ROM build – can have a specified position (for use with a HAL) and is not linked into the module chain
HAL: may be zero or one of these in a main ROM and none in an expansion ROM – not linked into the module chain
LOADER: expansion card loader – only one of these is allowed, and only in expansion ROMs
The ModuleDB also specifies subdirectories and filenames within
RiscOS/Install to be used during ROM assembly to hold the relocated but unlinked modules. These are structured to overcome historic 10-character filename and 77-file-per-directory limits.
You will also note that it is possible for a component’s type to be overridden in the Components file. This is most often used to force only the export phases to be executed on a component which would otherwise generate a binary – typically when some other component needs SWI numbers or other definitions from the component’s public header file(s).
The files in the top-level directory
Products are used to perform version control across a complete build. Simply speaking, this is a set of paths to directories within the repository, and symbolic CVS tags with which to check them out. So far, so unremarkable. However, there are a couple of perl scripts that operate on Products files that have useful benefits.
This script is used to check out a complete build tree given a Products file name. However, if you execute it from the root directory of a sandbox that you previously checked out with
checkout, the script will examine the CVS control files in your sandbox and only fetch the components that have changed from the repository. This saves you time and saves ROOL bandwidth costs.
When you are writing a new Products file, the switch
-localfile is useful – this prevents the script from checking out a fresh copy of the Products file from the repository, overwriting your locally modified version.
The checkout script does not currently handle merging the licence-type top-level directories together, which is required before you actually perform a build. This would a nice thing to add if someone fancies tackling it.
Many developers unfamiliar with Acorn’s quirky build process will be used to performing builds with CVS’s control files (versioning information) intact in the build tree. You will probably still find it necessary to run the tool
RiscOS/Apps/!EraseCVS over your build tree before building it if you want it to build correctly – but since you’ll be needing the control files in order to commit your changes back to the repository, it’s usual to keep two copies of the build tree: one which is a record of what you checked out, and another “working” one with the CVS files deleted and your changes in progress.
However, one of the main reasons for this was Acorn’s use of the Every and Makatic tools in some components, which would get confused by the presence of CVS control files and directories. Since these are commercial products, ROOL has weeded these out of the build, so this should no longer be a problem. There is definitely still a problem that many components do a recursive copy of their resources directories into the Messages module during the resources build phase, but this could be addressed by the Messages module stripping CVS control files out of its working directory as part of its rom phase – so there’s another task for someone. That might just be enough to allow the EraseCVS operation to be removed from the build process.
When you are ready to commit a new or updated Products file, use
prodcommit. This will automatically generate a standard format log message for your CVS commit.
This contrasts with the
srccommit script that should normally be used for committing changes to component.
If you look inside the top-level
Products directory, you’ll see that many Products files have two variants, one with a “Dev” suffix. This is because there are two distinct ways you might want to check out the same source tree:
cvs updateto merge other users’ changes with your own, even if you’re not ready to commit your own changes yet. This is only possible if the sources were checked out with a branch tag rather than a revision tag – to CVS, these mean “the latest revision on this branch”. “HEAD” is a special tag that acts just like a branch tag, but for the trunk (the default branch), so you’ll see lots of references to “HEAD” in these Products files.
It’s worth noting that the
checkout script’s trick to avoid needlessly checking out unchanged sources will be fooled by branch tags. If you’re working from a development products file, only re-run
checkout if new components have been added or if a component has changed to a different branch. You’ll need to pull in all other changes using
ROOL has yet to come up with a strategy for automatic builds, but development products files would probably be used for our equivalent of a Debian “unstable” release – they can’t in general even be expected to build every time while active development is going on. A Debian-style “testing” release would be made from the non-development products file and released to beta-testers – when a release appears to be sufficiently bug-free, a “stable” release would be just another CVS tag on the non-development products file.
The code names used for Products files are not always immediately meaningful, so here’s a quick description of the ones currently hosted on ROOL’s site:
BCM2835[Dev] are used with the Broadcom chip for the Raspberry Pi educational platform.
BuildHost[Dev] are for building (as much as possible of) the toolchain that is used to build RISC OS. It is assumed that the build machine is Iyonix class, though the binaries should be compatible with earlier machines. This is a disc build.
CTools[Dev] is a product definition used by the Desktop Development Environment, though a number of components it calls out are closed source due to licence restrictions.
Disc[Dev] is for building the HardDisc4 disc image, there’s also a cut down PlingSystem to support pre RISC OS 5 machines.
IOMDHAL[Dev] is for building a 32-bit HAL-based ROM for IOMD-class desktop machines: A7000, A7000+ and Risc PC.
OMAP3[Dev] is for building an OMAP3 ROM image suitable for BeagleBoards and other OMAP3-based machines.
OMAP4[Dev] is for building an OMAP4 ROM image suitable for PandaBoards and other OMAP4-based machines.
Tungsten[Dev] are for building a ROM for the Iyonix PC.
S3CDev and Batch1to6Dev and TitaniumDev and iMx6Dev are used for building various prototype targets, these are very much a work in progress.
BCM2835Pico and OMAP3Live and are specific products put together for one off special events.
For disc builds, you’d normally use build phases export_hdrs, export_libs and install. The install phase is labelled “Install disc” in !Builder.
For ROM builds, you’d normally use build phases export_hdrs, export_libs, resources, rom, install_rom and join.
In either case, you can often shorten the rebuild time by missing out one or more of the phases from the start of the process – the export phases aren’t needed if you haven’t changed any headers or libraries, and the resources phase isn’t needed if you haven’t changed any resources.
Now you’re familiar with the terminology we use, you should proceed to one of the following pages to learn more about the build system: