%% SCRAP: hardware/PLATFORM_BUILD_GUIDE
%% SOURCE: docs/working/hardware/PLATFORM_BUILD_GUIDE.adoc
%% STATUS: CURRENT
%% FITS: dev-guide/ch-build
%% EDITORIAL: lifted — prose rewritten to press voice

\section{Platform Build Guide}

StarForth builds for both POSIX hosts and the L4Re microkernel from a single
codebase, selected by one Makefile switch. The POSIX path is the default; the
L4Re path is enabled with \texttt{L4RE=1}.

\begin{lstlisting}[language=bash]
# POSIX build (Linux/macOS/BSD) -- default
make
make fastest
make pgo

# L4Re/StarshipOS build
make L4RE=1

# Clean switch between platforms
make clean && make L4RE=1
\end{lstlisting}

\subsection{Platform Abstraction Files}

The platform layer isolates timing and clock functionality behind a small set
of files. The remainder of the VM is untouched by the platform choice.

\begin{table}[h]
\centering
\begin{tabular}{lll}
\toprule
File & Purpose & Platform \\
\midrule
\texttt{include/platform\_time.h} & Abstraction API & All \\
\texttt{src/platform/platform\_init.c} & Platform selector & All \\
\texttt{src/platform/time\_posix.c} & POSIX implementation & POSIX \\
\texttt{src/platform/time\_l4re.c} & L4Re implementation & L4Re \\
\bottomrule
\end{tabular}
\caption{Platform abstraction source files.}
\end{table}

Only three core files consume the abstraction: \texttt{src/log.c} (timestamps
via \texttt{sf\_realtime\_ns()} and \texttt{sf\_format\_timestamp()}),
\texttt{src/profiler.c} (monotonic timing via \texttt{sf\_monotonic\_ns()}),
and \texttt{src/main.c} (calls \texttt{sf\_time\_init()} at startup). All other
VM core files, word implementations, and the block I/O system are unchanged.

\subsection{L4Re Time Backend}

The L4Re RTC server provides hardware RTC access (x86 I/O ports, ARM PL031,
I2C chips), nanosecond precision via the CPU timestamp counter, an IPC
interface for getting and setting time, and suspend/resume handling that
refreshes the offset on wakeup. The C API lives in \texttt{librtc.a}:

\begin{lstlisting}[language=C]
l4_uint64_t l4rtc_get_timer(void);
int l4rtc_get_offset_to_realtime(l4_cap_idx_t server, l4_uint64_t *ns);
int l4rtc_set_offset_to_realtime(l4_cap_idx_t server, l4_uint64_t ns);
\end{lstlisting}

StarForth's L4Re backend behaves as follows. Initialization attempts to obtain
the \texttt{"rtc"} capability from the L4Re environment, queries the RTC offset
by IPC when found, and falls back to a zero offset (epoch time) otherwise.
Monotonic time always works without an RTC, reading
\texttt{l4\_kip\_clock\_ns(l4re\_kip())} directly from the Kernel Info Page.
Real time returns the RTC offset plus the KIP clock, or zero when no RTC is
available. Setting time computes a new offset from the desired time minus
uptime and writes it via IPC, which requires write permission on the
\texttt{"rtc"} capability.

L4Re's libc already provides working \texttt{clock\_gettime},
\texttt{time}, \texttt{localtime}, and \texttt{strftime}. The platform
abstraction is retained anyway for direct control over the RTC capability,
explicit handling of a missing RTC, a portable API across all platforms, and
to avoid a libc dependency in minimal builds.

\subsection{Testing}

For the POSIX build, confirm timestamped log output and a non-zero RTC check:

\begin{lstlisting}[language=bash]
make clean && make
./build/starforth --log-info
\end{lstlisting}

For the L4Re build inside the StarshipOS tree, \texttt{make l4} selects the
L4Re backend automatically; running under \texttt{scripts/runos.sh} should
show working profiler timing (always available via the KIP clock) and working
timestamps, which may report 1970 if no RTC server is present. A
syntax-checking script can validate both backends without a full L4Re tree by
compiling \texttt{time\_l4re.c} with \texttt{-fsyntax-only} (a fatal error on
missing L4Re headers is expected) and compiling the POSIX backend and selector
cleanly.

\subsection{Troubleshooting}

\begin{itemize}
  \item \emph{undefined reference to sf\_monotonic\_ns} --- ensure
    \texttt{time\_posix.c} and \texttt{platform\_init.c} are compiled.
  \item \emph{implicit declaration of sf\_time\_init} --- add
    \texttt{\#include "platform\_time.h"}.
  \item \emph{fatal error: l4/re/env.h: No such file or directory} ---
    expected outside the L4Re tree; build through the StarshipOS build system.
  \item \emph{RTC server not found} --- start the RTC server in the loader
    script and provide the \texttt{rtc} capability.
  \item \emph{Timestamps show 1970-01-01} --- the RTC server is not supplying
    an offset; check the vbus configuration and hardware RTC.
\end{itemize}

The result is a complete platform abstraction layer that builds on POSIX and
L4Re alike, with zero runtime overhead from inline functions and a clean
vtable-style separation. Switching platforms requires only \texttt{make
L4RE=1}; the core VM is unchanged.
