RISC OS Build EnvironmentROBE

Reference guide21Build Orchestration and Makefiles

Introduction and Overview

This chapter groups the build-entry commands and shared makefile guidance used to drive most projects in the build environment. It covers the orchestration layer above the individual compilers and linkers, including the shared RISC OS Makefile System and helper commands that shape the build.

Technical Details

Build orchestration

riscos-amu is the normal top-level build command for projects that use Makefile,fe1. It reads the makefile, builds the default or named targets, and honours build-selection macros such as BUILD32=1 and BUILD64=1.

Those makefiles are usually small front-ends to the shared RISC OS Makefile System. A component makefile typically declares the component name, object files, libraries, exports, or resources, and then includes one shared makefile such as LibraryCommand or CModule.

RISC OS Makefile System

The RISC OS Makefile System is the standard shared build framework used by the environment. It exists so that individual components do not need to repeat the mechanical rules for compilation, linking, ROM integration, exporting, and installation. Instead, a component Makefile,fe1 usually sets a small variable set and includes one shared makefile by name.

Basic structure

A minimal command-line component makefile looks like this:

COMPONENT = MyTool
OBJS = o.main
LIBS = ${CLIB}

include LibraryCommand

Variables set before the include line configure the shared makefile. Extra rules placed after the include extend or override the default behaviour. The shared makefiles are located through Makefiles$Path on RISC OS or the AMUFILES environment variable on host systems.

Shared makefile types

The common shared makefile types are:

MakefilePurpose
LibraryCommandBuilds command-line tools and standalone executables written in C, assembly, or experimentally Fortran 90.
CModuleBuilds a relocatable RISC OS module in C, using CMHG or CMunge-generated headers and veneers.
AsmModuleBuilds a relocatable RISC OS module in assembly, either from ObjAsm objects, an AASM source, or a combination.
LibExportBuilds and exports a library and its headers for other components.
CAppBuilds a C desktop application bundle, including !RunImage and resources.
BasicAppBuilds a BBC BASIC desktop application bundle.
DocumentationBuilds PRM-in-XML documentation with no compiled output.
ResourceHandles resource-only components with no compilation step.

Architecture selection

The makefile system supports three build-architecture selections:

SelectionOutput directoriesUse
BUILD26=1o, oz, aif, rm, aofLegacy 26-bit ARM builds for older systems.
BUILD32=1o32, oz32, aif32, rm32, aof32Default 32-bit ARM builds for current RISC OS 5 systems.
BUILD64=1o64, oz64, aif64, rm64, elf6464-bit AArch64 builds with more limited library support.

Only one architecture selection should be active at a time.

Common variables

Most shared makefiles recognise the following variables before the include line:

VariableUseMeaning
COMPONENTRequiredComponent name. Used as the default output name and as a base for export and resource paths.
OBJSCommonSpace-separated object list. Entries are written as o.name; the shared makefile maps the directory prefix to the active architecture.
LIBSCommonLibraries to link against, usually by using pre-defined library variables such as ${CLIB} or ${RLIB}.
TARGETOptionalOverrides the default output filename or application bundle name.
EXPORTSOptionalFiles to export as headers or libraries.
RESOURCESOptionalResources to copy into the ResourceFS staging area for ROM or installation use.
INSTALLOptionalExtra files to copy during installation.
INITTARGETOptionalExtra target run during initialisation before compilation begins.
CLEANTARGETOptionalExtra target run during clean.
DOCSRCOptionalPRM-in-XML source files to build and install as documentation.

Common targets

Most shared makefiles provide the following targets:

TargetEffect
allBuilds the component. This is the usual default for commands, libraries, and applications.
ramBuilds a standalone relocatable module for loading with RMLoad. This is the default for module makefiles.
romBuilds a partially-linked object for inclusion in a ROM image.
installCopies the built output to the installation directory named by INSTDIR.
install_romCopies the ROM object to the ROM build staging area.
exportRuns both export_hdrs and export_libs.
export_hdrsExports header files only.
export_libsExports compiled libraries only.
resourcesCopies resources into the ResourceFS staging area.
cleanRemoves generated files but not exported artefacts.
rom_linkPerforms the final ROM link step at a given base address.

Compilation and library selection

The makefile system also honours several global compilation variables and library-selection variables:

VariableDefaultMeaning
OPTIMISEyesCompiler optimisation policy: no, size, time or yes, and max.
UNALIGNED_LOADSnoControls whether the compiler may emit unaligned load instructions.
ASD(unset)Enables a debug build; output directories gain a trailing d suffix. Not supported for 64-bit builds.
CLIBTYPEnoc99Selects the C library family: noc99, generic, or static. Ignored for 64-bit builds, which use libcrt.
NOCLIB(unset)Suppresses all C library linkage for components that do not need one.
FORTIFY(unset)Enables or advertises Fortify support, depending on value.
PROFILE(unset)Enables ARM profiling support for supported architectures.

The shared _Libraries include also defines a large set of pre-bound library variables, including:

VariableDescription
${CLIB}, ${CLIB_ZM}, ${ROMCLIB}Core C library choices for normal, module-safe, and ROM-link contexts.
${C++LIB}, ${RLIB}, ${TBOXLIBS}, ${DESKLIB}Common C++, desktop, and Toolbox libraries, with _ZM module-safe variants where appropriate.
${TCPIPLIBS}, ${INETLIB}, ${SOCKLIB5}, ${UNIXLIB}, ${RPCLIB}Networking and Unix-compatibility libraries, generally unavailable for 64-bit builds.
${ZLIB}, ${ZIPPERLIB}, ${MD5LIB}, ${CONFIGLIB}, ${RESOLVLIB}, ${OSLIB}, ${THROWBACKLIB}Miscellaneous support libraries used across command, application, and module builds.
${FLIB}GNU Fortran runtime library for 64-bit Fortran builds.

Shared-type specific notes

Some variables only matter to particular shared makefiles:

Makefile typeNotable variables
CModuleVariables such as NOCLIB; NOROMLINK, which if defined means rom_link is not provided because the component handles it itself; LINKTYPE, set to bin to produce a raw binary during install_rom; and module-specific RAM versus ROM behaviour.
AsmModuleVariables such as AASM, a single AASM source file assembled directly to a module; CSOURCES; DEFINES; and ROMSAFE, set to no if the module must be squished for ROM inclusion.
LibExportVariables such as LIBCOMPONENT, the export subdirectory name (defaults to COMPONENT); NOLIBFILE, selecting the library format (unset for a LIBFILE archive, aof for a partial link, or true to copy a single object); NOEXPORTS; NO32BITLIBS, which if defined means 32-bit variants are not built; and NOMODULELIBS, which if defined means module variants are not built.
LibraryCommandVariables such as TYPE; WORKSPACE, the workspace size for relocatable AIF output; and VIAAOF, set to yes to link via an intermediate AOF and avoid weak-symbol pull-in; plus experimental Fortran support.
BasicApp and CAppApplication-bundle installation behaviour, resource copying, and optional squeezing of !RunImage.

In practice, riscos-project is the quickest way to start from a valid baseline for these makefile families.

When to choose which layer

Use riscos-amu for established projects, direct compiler or assembler invocations for experiments and troubleshooting, and the 64-bit wrappers only when a project genuinely targets the 64-bit toolchain.

System Variables

EXPORTS_DIR
Native host destination for riscos-amu export output

Set to /riscos-built/Export. The shared _Directories include resolves the export targets used by export, export_hdrs, and export_libs against this variable when cross-compiling, so headers and libraries exported with riscos-amu export land under $EXPORTS_DIR/Hdr/Interface, $EXPORTS_DIR/C, and $EXPORTS_DIR/Lib on the host side, in addition to the RISC OS-style <Exports$Dir> locations used on a real RISC OS build.

Commands

riscos-amu
Run AMU builds for RISC OS projects
riscos-amu option target-or-macro
-e -Let environment variables override macro definitions from the makefile.
-E -With -e, restore the older precedence order where makefile macro definitions override command-line and environment definitions.
-f -Read the named makefile instead of the default. If the filename is omitted, AMU falls back to Makefile.
-I -Add an include path to the search list for included AMU makefiles.
-i -Ignore command return codes, equivalent to the AMU .IGNORE directive.
-k -Keep building independent branches after a failing command instead of abandoning the whole build immediately.
-n -Do not execute commands; print the commands that would run and the reasons they were selected.
-D -Show the dependency reasons while commands are executed.
-o -Write the generated commands to a command file for later *EXEC or *OBEY use instead of executing them immediately.
-s -Suppress command echoing, equivalent to the AMU .SILENT directive.
-t -Mark targets up to date by adjusting timestamps consistently instead of rebuilding them.
-v -Force each command to be printed before execution, even if the makefile uses .SILENT or prefixes commands with @.
-amuversion -Require a specific AMU version; higher installed versions are treated as an error.
-x -Enable AMU debug tracing flags, given as a number from 0 to 6. These are not severity levels: each value enables a different, specific set of tracing features. The upstream tool's own help text does not enumerate what each value shows, so this entry cannot go beyond what is documented there either.
<target-or-macro>-One or more build targets, or macro assignments of the form name=value. If no target is supplied, AMU builds the first target in the makefile.

Builds the default or named makefile targets for the current project. This is the normal top-level build command in the environment.

It reads the component Makefile,fe1, honours macro assignments such as BUILD32=1, BUILD26=1, or BUILD64=1, and drives the shared makefile system via the makefile include selected by the project.

Arguments of the form name=value are treated as macro definitions rather than targets. In this environment that is the normal way to select architecture or makefile behaviour at invocation time.

riscos-amu BUILD32=1
riscos-makegen
Generate AMU makefiles from an older nested source-tree layout
riscos-makegen -26bit -32bit -v -d -l lib-or-link -L libraries -p project-name -m makefile-name -f viafile-name -shared -O build-option -s source-directory
-26bit -Generate the 26-bit object set and target.
-32bit -Generate the 32-bit object set and target.
-v -Enable verbose progress output.
-d -Enable debug tracing.
-l -Select the final build action. The accepted values are lib and link.
-L -Library list to use for -l link.
-p -Project or component name to write into the generated file.
-m -Name of the makefile to create.
-f -Name of the via file to create. This is required for the standard makefile format and must not be used with -shared.
-shared -Generate a shared-format makefile using the RISC OS Makefile System includes instead of a fully expanded makefile.
-O -Select an extra build option. The live tool currently documents only NOEXPORTS.
-s -Root directory to scan for build units.

riscos-makegen scans a source tree whose immediate child directories represent build units and writes either a fully expanded AMU makefile or a shared-format makefile for the RISC OS Makefile System.

It is intended for older Toolbox-style source layouts and generated interface trees. A top-level c or s directory is treated specially and builds directly into the top-level object directories, while other multi-character directories are expected to contain one nested c/ or s/ directory.

If neither -26bit nor -32bit is supplied, the tool defaults to 26-bit output only. The live parser accepts only lib and link for -l, even though older diagnostics still mention libfile.

In standard mode, the tool writes explicit object rules and creates object directories as a side effect. In shared mode, it mainly emits the variables and targets expected by the shared makefile includes, and does not accept -f.

The tool's built-in usage path is reached by running it with no arguments or with -h; the GNU long-option spelling --help is not supported by the live command.

riscos-makegen -l lib -26bit -32bit -p MyLib -m src/makefile -f src/ViaFile -s src
riscos-ifthere
Conditionally execute commands based on file existence
riscos-ifthere file Then then-command Elseelse-command
<file>-File whose existence will be tested. Wildcards are not supported.
<then-command>-Command line to execute when the file exists.
<else-command>-Optional command line to execute when the file does not exist.

riscos-ifthere is a small build-script helper that checks whether a named file exists, then runs one of two command lines according to the result.

The keywords Then and Else are matched case-insensitively. All remaining arguments after Then are joined with spaces to form the true command, and any remaining arguments after Else are joined in the same way for the false command.

The characters ;, <, >, $, ", ', and \ are escaped before the selected command is passed to the host command interpreter, so literal values such as $PATH are preserved.

If no Else clause is supplied and the file is absent, no real command is run and the result is success. If the filename contains a wildcard character, the tool reports an error and runs neither branch.

This output is from a plain command skeleton, which has c.main but no c.module; the Else branch runs.

riscos-ifthere c.module Then echo Present Else echo Missing Missing
make
Choose between GNU make and riscos-amu according to the current project's makefile
make make-option target
<make-option>-Ordinary make option passed through to the selected backend. The wrapper itself inspects -C, --directory, -f, and compact forms such as -Cdir or -fMakefile while deciding which backend to use.
<target>-Build target, macro assignment, or other positional argument passed through unchanged to GNU make or riscos-amu.

make is a convenience wrapper for mixed projects and routine shell use. It tries to detect whether the current directory is really a RISC OS AMU project and, if so, runs riscos-amu; otherwise it falls back to the host's normal GNU make.

This means the same short command usually does the sensible thing in both kinds of source tree. In a normal POSIX project it behaves like ordinary make. In a project built around Makefile,fe1 or the shared RISC OS Makefile System, it switches over to riscos-amu automatically and forwards the original arguments there.

When deciding which directory and makefile to inspect, the wrapper honours -C and --directory, and it honours -f or compact -fname forms when an explicit makefile is supplied. Without an explicit makefile, it looks for Makefile, makefile, Makefile,fe1, and makefile,fe1. If the named file does not exist but the same name with a ,fe1 suffix does exist, the wrapper automatically uses that typed form instead.

A project is treated as an AMU build when the selected makefile name ends in ,fe1, when its first line mentions env riscos-amu, or when it includes one of the common shared makefile families AsmModule, CModule, LibraryCommand, or LibExport. When that detection succeeds and riscos-amu is available, the wrapper executes it directly. If the project looks like a RISC OS build but riscos-amu is unavailable, the wrapper warns and then falls back to standard GNU make.

The wrapper is intended to be reliable for normal day-to-day use, but it is still only a selector layer. Detection is based on the makefile path and contents described above, and backend-specific options are not reinterpreted beyond what is needed to decide which backend should receive them.

With no INSTDIR set, the default null:$ discards the copy harmlessly, which is why this is a safe example to try as written. riscos-copy also prints warnings about the f and r flags it does not support; these are expected and do not indicate a failed install.

make -f Makefile,fe1 install riscos-ifthere Resources.UK.Help Then riscos-cdir null:$.Help riscos-copy aif32.MyTool null:$.MyTool ~cfr~v riscos-copy null:$.MyTool null:$.MyTool riscos-ifthere Resources.UK.Help Then riscos-vtranslate VersionNum Resources.UK.Help null:$.Help.MyTool MyTool: Command installed {Disc}
riscos64-amu
Run the normal AMU build command with 64-bit selection enabled
riscos64-amu target-or-macro additional-target-or-macro
<target-or-macro>-Build target, AMU option, or make-style macro assignment passed through to riscos-amu.
<additional-target-or-macro>-Further targets, options, or macro assignments.

riscos64-amu is only a convenience wrapper. It invokes riscos-amu with BUILD64=1 inserted before your other arguments, so shared makefiles select the 64-bit object, library, and output paths.

All real parsing, target selection, and makefile handling still come from riscos-amu. Use this wrapper when a project already understands the standard makefile-system architecture variables and you simply want the 64-bit selection without spelling the macro yourself.

riscos64-amu clean all
riscos64-make
Run GNU make with the 64-bit wrapper tools preselected for the usual build variables
riscos64-make make-option variable-assignment target
<make-option>-Ordinary GNU make option such as -f or --file.
<variable-assignment>-Make-style command-line variable assignment. These still override the wrapper defaults when you supply the same variable yourself.
<target>-Build target to pass through to GNU make.

riscos64-make runs ordinary GNU make but predefines the usual build-tool variables so that a Unix-style makefile can target the RISC OS 64-bit wrapper family without being edited.

The wrapper currently injects AR=aarch64-unknown-linux-gnu-ar, AS=riscos64-as, LD=riscos64-link, CC=riscos64-cc, and CXX=riscos64-c++. It preserves normal make option handling, including explicit makefile selection with -f, --file, or --makefile.

Your own command-line variable assignments still win if you need to override one of those defaults. This tool is therefore most useful for simple or imported GNU-make projects; projects already using the RISC OS Makefile System normally stay with riscos-amu or riscos64-amu instead.

The wrapper calls the plain make command internally, and that name resolves to the make selector wrapper described above, not directly to GNU make. If the current directory also contains an AMU project (for example a stray Makefile,fe1 left over from another build), that selector detects it and silently redirects the whole invocation to riscos-amu instead, ignoring the GNU makefile and target you asked for. Run riscos64-make from a directory that contains only the intended GNU makefile to avoid this.

riscos64-make all CC=riscos64-cc CXX=riscos64-c++ AS=riscos64-as LD=riscos64-link AR=aarch64-unknown-linux-gnu-ar

Examples

Previewing a make build without executing commands

This is useful when checking what a shared makefile is about to do.

riscos-amu -n BUILD32=1
docs_init is a phony target
true
.INIT is a phony target
riscos-cdir aif32
riscos-cdir o32
o32/main does not yet exist
riscos-cc -c -Wc -fa -IC: -za1 -Otime -apcs 3/32/fpe2/swst/fp -D__CONFIG=32 -o o32/main c/main
aif32/MyTool does not yet exist
riscos-link -rescan -C++ -aif -o aif32.MyTool o32.main C:o.stubsGS
all does not yet exist
echo MyTool: All built {Disc}