RISC OS Build EnvironmentROBE

Workflow guides9Porting Existing C Projects

Introduction and Overview

Porting an existing C codebase is a different job from starting a new native RISC OS project. The normal goal is to keep the upstream source layout intact, add a RISC OS-specific build tree alongside it, and make the smallest source-level changes needed for the Norcroft compiler and the RISC OS runtime model.

The build environment provides riscos-cport for the first structural pass. It discovers likely source and header files, creates a RISCOS/ tree, and generates the initial makefiles so that the port can be validated with the normal AMU workflow.

Choosing the workflow

When to use this workflow

Use this workflow when the code already exists in a POSIX-style source tree, whether it is your own code, an upstream open source package, or a library that has never previously been given a RISC OS build layout. In these cases the main task is usually to map the existing layout into the shared RISC OS makefile system, not to invent a new project structure from nothing.

First-pass port generation

The usual starting point is riscos-cport. It creates a conventional RISCOS/ port directory, links the existing source files into RISC OS-style c/ and h/ views, and generates the initial Makefile,fe1 files so that the port can be built with the normal AMU workflow.

The tool is intended as a first pass rather than a complete converter. Its job is to establish the correct project structure quickly, after which you adjust the generated makefiles, build, and only then patch source files if the Norcroft compiler or the RISC OS build model requires it.

For a typical library-style project, start like this:

riscos-cport mylib
Created mylib/RISCOS for library 'mylib'.
Run 'cd mylib/RISCOS && riscos-amu export' to build it.
Report: mylib/RISCOS/RISCOS_PORT.md
cd mylib/RISCOS
riscos-amu export

Autodiscovery only finds headers it is told about. Plain riscos-cport mylib discovers library and command sources automatically, but it does not search a separate headers directory such as include/ unless told to. If your headers live apart from the sources, point both out explicitly:

riscos-cport --source src --header include mylib

Without --header in that layout, the generated RISCOS_PORT.md report lists no exported or compile-time headers, and the subsequent riscos-amu export fails with #include file "mylib.h" wouldn't open.

Porting process

The normal porting process is:

  1. inspect the repository layout and identify the real library sources, public headers, command-line entry points, examples, and tests;
  2. run riscos-cport on the repository root and let it discover the obvious files;
  3. use command-line overrides if autodiscovery picked up the wrong files or missed required defines, include paths, or extra libraries;
  4. build the generated RISCOS/ tree with riscos-amu export for a library port, or the generated command makefile with riscos-amu -f Makefile...,fe1 for a command port;
  5. make narrow source fixes only after the generated layout and makefiles are structurally correct.

This ordering matters. Many initial failures come from the wrong files being in the object list, missing include paths, or a command target being treated as library code. Those are better fixed in the port description than by patching the source too early.

Guiding source discovery

The most common adjustments are:

  • --exclude-source to remove tests, examples, or host-only files from the library object list;
  • --command-source to name command-line tools explicitly;
  • --define and --command-define to enable optional features or compatibility paths;
  • --include to add non-standard header locations;
  • --command-lib when a generated command needs an extra library beyond the main port.

For a command-oriented repository, or one where the repository contains both a library and sample tools, it is often useful to make the intended command sources explicit so that the generated command makefiles are correct from the start.

riscos-cport --exclude-source 'tests/*' --command-source tools/demo.c mylib

The generated report's Entry Points section confirms which sources were kept as commands and which were excluded, which is the quickest way to check that the overrides took effect before building anything.

Validating command ports

If the repository contains command-line tools with main(), riscos-cport can create separate command makefiles for them. Those are then built individually rather than as part of the library export. Each generated command makefile is named Makefile<CommandName>,fe1, where <CommandName> is derived from the command source's basename; a discovered tools/demo.c produces MakefileDemo,fe1:

riscos-cport mylib
cd mylib/RISCOS
ls Makefile*,fe1
Makefile,fe1 MakefileDemo,fe1
riscos-amu -f MakefileDemo,fe1

If the library builds but a command does not, the next thing to check is usually whether the command needs an extra define or library rather than a broader source rewrite.

When source changes are justified

When source changes are justified

Once the generated layout is structurally correct, the remaining work is often one of these:

  • adjusting host-specific include paths so they work with RISC OS headers;
  • supplying a generated or bundled configuration header that the upstream build expected another tool to provide;
  • fixing syntax or declaration order that the Norcroft compiler does not accept;
  • adding narrow compatibility defines or header shims for platform-specific interfaces.

This approach keeps the port close to the upstream layout. The RISC OS-specific tree records the build rules and any compatibility shims, while the original sources remain the main body of code. The formal command reference for riscos-cport is in Project and CI.