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.
VersionNum
file (and sometimes a VersionASM
file) in the root directory of what’s considered a component for source control purposes. VersionNum
and VersionASM
files are automatically maintained when you commit changes to the repository using the perl script srccommit
.COMPONENT
variable 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: USBDriver
, OHCIDriver
and EHCIDriver
.
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 “Morris4
”, “RO400
”, “Ursula
” and “Iyonix
”.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 “APCS-32
”.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 assemblerC
: same as ASM
except that rom_link phase is used instead of install_rom phaseRES
: 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 librariesDATA
: after the module chain, a ROM can include one or more binary blobs, typically at fixed addresses; these DATA
components are called with the same build phases, but aren’t linked into the module chainBBE
: use for pure BBE components such as RiscOS/Library
– only ever called by bbe phaseKERNEL
: 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 chainHAL
: may be zero or one of these in a main ROM and none in an expansion ROM – not linked into the module chainLOADER
: expansion card loader – only one of these is allowed, and only in expansion ROMsThe 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.
checkout
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.
prodcommit
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 update
to 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 cvs update
.
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:
BuildHost and BuildHostDev 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.
IOMDHALDev is for building a 32-bit HAL-based ROM for IOMD-class desktop machines: A7000, A7000+ and Risc PC. A work in progress.
Tungsten and TungstenDev are for building a ROM for the Iyonix PC.
OMAP3Dev is for building an OMAP3 ROM image suitable for BeagleBoards and other OMAP3-based machines.
Disc is for building the HardDisc4 disc image.
S3CDev is used for building both the S3C2440 and S3C6410 ROM images. These ROM images are very much a work in progress.
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: