ROBE 64-bit builds from !Sourcery
=================================

!Sourcery (32-bit, on RPCEmu or real hardware) can send a project to the
RISC OS Build Environment (ROBE) and get a 64-bit (AArch64) build back.
ROBE runs in Docker on the host, so a small host program, robe_bridge.py,
does the build and talks to !Sourcery through a directory that both can see.

  !Sourcery  --Req_<id>-->  spool directory  -->  robe_bridge.py serve
             <--Log_<id>, Result_<id>, Out_<id>--        |
                                                riscos-amu BUILD64=1 in
                                                gerph/riscos-build:latest-64bit

Host set-up
-----------
1. Install Docker and pull the image:
     docker pull gerph/riscos-build:latest-64bit
2. Make a spool directory inside the HostFS tree, e.g. <hostfs>/ROBESpool.
3. Start the bridge, mapping the RISC OS name of the HostFS root to the host
   directory (add one --map for each name !Sourcery may use for it):
     python3 robe_bridge.py serve <hostfs>/ROBESpool \
         --map 'HostFS::Tardis.$=<hostfs>'

   To build one project without RISC OS:
     python3 robe_bridge.py build <repo>/Projects/Libraries/HeapMemLib

RISC OS set-up
--------------
1. In !Sourcery's !Run, turn the integration on (it is off by default):
     Set Sourcery$EnableROBE Yes
   Without it the ROBE toolbar button and menu entry are hidden.
2. In !Sourcery's !Run (or your boot sequence):
     Set Sourcery$ROBESpool HostFS::Tardis.$.ROBESpool
   Optionally Set Sourcery$ROBETimeout <seconds> (default 600).
3. New menu entry (already in Resources.Default; copy it into your Choices
   copy, <Choices$Write>.Sourcery, if you already have one):
     Sequences.Menus.Project.robe64     ("Build 64-bit (ROBE)")
4. Click the "64" build button on a project window's toolbar, or choose
   "Build 64-bit (ROBE)" from a project's menu. The task window shows
   the ROBE log; the library or program is left in the spool directory as
   Out_<id>, with the generated Makefile.

Requests from !Sourcery
-----------------------
"Build 64-bit (ROBE)" on the project menu is an internal sequence
(robe64): the RobeRequest class writes Req_<id> itself, then opens a task
window running "ROBE.Wait <id>" to show the log. Besides
project:, the request has
  include:<path>             each include path, expanded for the target
  library:<path>             each library (not used by the bridge yet)
  pathvar:<name>:<value>     <name>$Path for every path variable used
so the bridge stages the folders your own include definitions point at
(e.g. Document: -> Classes.ADocApp.Source, Classes.AWindow.Source). C: and
OSLib: become ROBE's own, and other system paths (OSLibInclude:,
OSLibSupport:, tboxlibs, folders named OSLib, or any folder with an os.h)
are ignored so a 32-bit OSLib cannot hide ROBE's. Other folders are
matched to projects under ...Projects. or through --map.

What the bridge does
--------------------
* Reads Sourcery.Source, Sourcery.Includes and Sourcery.Libraries.
* Copies the sources into a ROBE component (c, c++, h; lower-case aliases
  for headers) and the headers of the include projects into inc.h.
  If both "x" and "x,fff" exist it uses the most recently committed one.
* Maps Sourcery include definitions to ROBE paths (OSLib -> OSLib:, C ->
  C:, Local.General -> the OSSupLib/HeapMemLib/CLibSupport/PList headers,
  ...). Extend the map with --include-map <file.json>.
* Also stages the headers of projects named in the project's existing
  makefiles (-I folders and linked libraries under ...Projects.).
* Then follows #includes: any header still missing that ROBE doesn't
  provide is looked up in the Classes and Libraries projects (anything with
  a Sourcery directory), and that project's headers are staged, repeating
  until nothing new is found. The log names each project it used, e.g.
  "found awindow.h in Classes.AWindow". Headers ROBE provides under a
  different case (e.g. "Event.h") get a small wrapper header.
* Writes a shared-makefile Makefile,fe1 (LibExport for libraries,
  LibraryCommand for commands) with -Dosbool=int, as ROBE's 64-bit OSLib
  has no osbool, and runs riscos-amu BUILD64=1.

Per-project compat files live in compat.<project>:
  exclude   names of sources not built for 64-bit (one per line)
  c, c++, h stand-ins added to the build, e.g. a C version of an
            assembler file. 32-bit ARM assembler (s) is never built.
compat.h holds stand-in headers shared by all projects (e.g. dynamite).

Limits
------
* Libraries and commands only; desktop applications are not handled yet.
* Commands are not linked against other repo libraries yet.
* ROBE's 64-bit OSLib predates OSLib 7: no ole.h, scrolllist.h, textarea.h
  and some newer constants, so files needing them are excluded.
* Pointers passed through int (e.g. regs.r[0] = (int)ptr) compile with
  warnings and need fixing before the code is run on 64-bit RISC OS.
