Toolchains
Motor OS has one compilation target, x86_64-unknown-motor, and
two toolchains for it. On Linux, a cross toolchain (Rust with Cargo, and Clang) builds
Motor OS itself and any program for it. On the developer image, a native toolchain
(rustc with a full sysroot, Clang/LLVM with a C and C++ sysroot, and Lorry as the build
driver) builds programs on Motor OS. Both come from the same forks of Rust, LLVM, and
mlibc.
Components and lineage
| Component | Source | What Motor OS adds |
|---|---|---|
| Rust | moturus/rust, based on the upcoming Rust release (1.99 at the time of writing) with LLVM 23 | The x86_64-unknown-motor target, a Tier-3 target upstream; the standard library's Motor OS layer, which calls the moto-rt crate (0.17.x); a few compiler patches, all on one development branch per upstream baseline (motor-os-1.99.0-beta-f47d5bb today), from which both the cross and the native toolchain are built. |
| Cargo, Clippy, rustfmt | Upstream, at the revisions the Rust fork specifies | Nothing; they run on Linux only. |
| LLVM | moturus/llvm-project, LLVM 23 | A Motor OS target in Clang: the driver knows the link line, the defaults (emulated TLS, static PIE, lld, compiler-rt, libc++), and the sysroot layout. Built twice: for the Linux host, and natively for Motor OS. |
| mlibc | moturus/mlibc | The Motor OS sysdeps and a build configuration that reads its runtime files from /system/cfg/libc. It sits on moto-rt-cabi, a C ABI over the Motor runtime (see C/C++ on Motor OS). |
| Small crate forks | moturus/libc, moturus/stacker, moturus/rust_libloading, moturus/rust-ctrlc | Patched into the Rust fork's own dependency graph; Cargo fetches them, nothing is cloned by hand. |
| Lua, ripgrep | Lua 5.4.8 from lua.org, unmodified; moturus/ripgrep | Built with the toolchain as the first real C program and the first large Rust program; shipped as /devtools/bin/lua and /system/bin/rg. |
The target
The target specification in the Rust fork describes what every Motor OS program
looks like: a static position-independent executable, linked self-contained (no
dynamic linking, no system linker libraries), panic = abort, entry point
motor_start, thread-locals provided by the runtime rather than ELF TLS, and
full RELRO. Clang's Motor target applies the same rules to C and C++: emulated TLS,
-static-pie, lld, and a link line that adds crt1.o, the runtime shim,
libc++abi, libunwind, libc, and the compiler builtins. A program built by either compiler
runs on any Motor OS image, because it carries everything it needs except the runtime
object that the OS maps into every process.
The cross toolchain on Linux
Rust
The Motor OS build installs the Rust fork's output as one rustup toolchain whose name
carries the upstream baseline and a key derived from every input,
motor-1.99.0-beta-f47d5bb-dev.1-<key> today. It contains
rustc and rustdoc, its own Cargo, Clippy, and rustfmt, the
standard library for the Linux host, the standard library for
x86_64-unknown-motor under lib/rustlib/x86_64-unknown-motor, and
the library sources; nothing is borrowed from another rustup channel. The repository's
rust-toolchain.toml names that exact toolchain, so everything in the
repository is built with
cargo build --target x86_64-unknown-motor [--release]
and nothing more: the standard library is prebuilt, so ordinary programs do not use
-Zbuild-std. Only the bare-metal pieces, the kernel and the boot stages, use
custom JSON targets and build core and alloc themselves from the
toolchain's library sources. The Makefile applies the same command to every component,
keeps each crate's Cargo output under build/obj/<toolchain-key>/, and
copies stripped binaries into build/bin/debug or
build/bin/release for the imager; make -j$(nproc) builds the debug
tree and BUILD=release the release tree. See
Building Motor OS.
A pure-Rust program needs no linker configuration: rustc links it with its bundled
lld. A crate that compiles C code (curl, Lorry) points Cargo at the Motor Clang instead,
with CARGO_TARGET_X86_64_UNKNOWN_MOTOR_LINKER set to motor-clang
(from the selected assembly's sysroot/bin) and
CC_x86_64_unknown_motor to the same compiler, so that the C parts are built
against the Motor sysroot.
Cross-compiling your own program
cargo new hello, and write the program against the standard library, as on any other platform.- If it uses Tokio, mio, rustls with ring, crossterm, or the ctrlc crate, add the Motor
OS forks to
[patch.crates-io]inCargo.toml, as the in-tree programs do; the table in Rust on Motor OS lists them. cargo build --release --target x86_64-unknown-motor. The repository'srust-toolchain.tomlapplies to projects inside the checkout (the recipe usesbuild/examples/); for a project elsewhere, copy that file next to itsCargo.toml. The result istarget/x86_64-unknown-motor/release/hello.- Copy it into a running VM with
scpand run it; see Hello Motor OS for the whole sequence.
C and C++
The host Clang is the LLVM fork's own build, with a configuration file next to it
that turns every link for x86_64-unknown-motor into a raw static-PIE link
(-fuse-ld=lld -static-pie -nostdlib -Wl,-e,motor_start); that raw form is what
the build uses to construct the sysroot itself. For compiling programs, the build also
produces, under the selected assembly ($MOTORH/assemblies/<key>/sysroot),
a sysroot directory with mlibc's headers and the static libraries, and three small
wrappers in its bin:
| Wrapper | What it does |
|---|---|
motor-clang | Runs the host Clang with --target=x86_64-unknown-motor and the sysroot, letting the driver's Motor target add the runtime link line; motor-clang -O2 prog.c -o prog is a complete build. |
motor-clang++ | The same for C++, with libc++. |
motor-rust-cc | The linker Cargo uses for Rust crates with C parts: adds the runtime group (crt1.o, the shim, libc++, libc++abi, libunwind, libc, the builtins) to a rustc-driven link. |
A C program cross-compiled this way is the same static executable the native compiler produces, and runs on any image. What the C library and libc++ support is on the C/C++ on Motor OS page.
The native toolchain on the developer image
Nothing on the developer image compiles itself into existence: the native compilers are cross-built on Linux and staged into the image. Once there, they compile Motor OS programs on Motor OS, with no host involved.
rustc
/devtools/rust/bin/rustc is the Rust fork's compiler built with Motor OS as
the host (x.py build --stage 2 compiler --host x86_64-unknown-motor): a single
static executable of about 100 MB with its own LLVM inside. Its sysroot,
/devtools/rust/lib/rustlib/x86_64-unknown-motor/lib, is the complete set of
prebuilt crates: std, core, alloc,
proc_macro, test, panic_abort, the compiler builtins,
moto_rt, and their dependencies, each as an .rlib with its
metadata. /devtools/bin/rustc, the command on PATH, is a two-line
script that sets TMPDIR=/devtools/tmp and runs it.
rustc -O hello.rs -o /devtools/tmp/hello && /devtools/tmp/hello
No linker option is needed: rustc's default linker driver is cc, which on
the image is /devtools/bin/cc, the native Clang, which links with lld. There is
no Cargo, Clippy, rustfmt, or rustdoc on the image; packages with dependencies are built
with Lorry, below, which also runs procedural macros as separate static executables
because Motor OS has no dynamic loading.
Clang/LLVM
/devtools/llvm/bin/llvm is one static executable of about 107 MB that
contains the whole LLVM toolchain as subcommands: clang, clang++,
lld (and its ld.lld flavor), ar, ranlib,
nm, objcopy, strip, objdump,
readelf, size, addr2line, cxxfilt,
dwp, and more, invoked as llvm clang ... or llvm ar ....
It was configured with Motor OS as its host and default target, lld as the default linker,
compiler-rt as the runtime library, libc++ as the C++ standard library, and
/devtools/cfg/llvm as its configuration directory, where
x86_64-unknown-motor.cfg points it at its resource directory,
/devtools/llvm/lib/clang/23. /devtools/bin/cc and
/devtools/bin/c++ are two-line scripts over it.
The sysroot is under /devtools/llvm: include holds mlibc's
headers, libc++'s c++/v1, and moto_rt.h; lib holds
crt1.o, libc.a, libc++.a, libc++abi.a,
libunwind.a, libmoto_rt_cabi.a, the compiler-rt builtins, and empty
libm, libpthread, libdl, librt,
libresolv, libutil, and libssp archives so that
-lm and friends in existing build systems link. The C library reads its
runtime files from /system/cfg/libc.
Lorry
Lorry is the Rust build driver on the image, and a smaller, stricter Cargo replacement
for security-sensitive environments: it takes the same Cargo.toml and
Cargo.lock and aims for byte-identical binaries, never invokes Cargo, admits
dependencies once and explicitly with lorry vendor, and then builds, runs, and
tests packages offline using
/devtools/bin/rustc and, for crates with C parts, /devtools/bin/cc
and llvm ar. It builds red and itself natively in the developer-image test.
It has its own page: Lorry: the package manager.
lorry new hello && cd hello
lorry vendor --accept-all # once, with network access
lorry build --release
lorry run
Also on the image
/devtools/bin/lua (Lua 5.4.8), /system/bin/curl (the HTTPS
client Lorry fetches with), /devtools/bin/mdbg, the test suites under
/devtools/tests, and source snapshots under /devtools/src; see
Developer image.
How the pieces are produced
The build script (src/build-motor-os.sh) produces everything above in a
fixed order, on Ubuntu, in one to two hours, from the exact source revisions declared in
src/toolchain-versions.sh. The order matters because each layer is built with
the one before it:
- The Rust and mlibc forks are checked out at their declared commits; LLVM and Cargo come in as the Rust checkout's submodules, so one LLVM tree serves every LLVM build.
- The host Clang and lld are built from that LLVM tree.
- One
x.pyrun from the Rust fork builds and installs the cross toolchain: rustc, rustdoc, Cargo, Clippy, rustfmt, both standard libraries, and the library sources, into an immutable directory named by its key, which is registered with rustup. Every later step and every Motor OS component uses it. - The runtime shim (
moto-rt-cabi) is built with the cross toolchain, then the compiler-rt builtins, then mlibc against the shim, then libunwind, libc++abi, and libc++ against mlibc. - The native LLVM multicall binary is built for Motor OS against that sysroot, and Lua is cross-compiled against the same sysroot as a check that a real C program links and runs.
- A second
x.pyrun from the same Rust revision produces the native rustc with Motor OS as host; the installed cross toolchain is verified to be unchanged by it. - The results are staged under
$MOTORH/assemblies/<key>/images/, with the manifest, from which the imager places them into the developer image.
The steps are listed so the relationships are clear; the procedure, the directory layout, and the test suites are on the Building Motor OS page.
Versioning
The toolchain is defined by source revisions, not by branch tips: one file in the
repository, src/toolchain-versions.sh, declares the upstream Rust release and
commit, the LLVM commit that release uses, the Motor Rust and LLVM commits on top of them,
the Cargo and mlibc commits, and the moto-rt version. Every version change is
a reviewed diff to that file; a normal build never advances a branch or runs
cargo update.
- One toolchain, one name. rustc, rustdoc, Cargo, Clippy, rustfmt, the
library sources, and both standard libraries live in one rustup toolchain, built from
one Rust revision, with no host nightly involved. The repository's
rust-toolchain.tomlselects it, and the Makefile refuses to run with a toolchain that does not carry a Motor key. - Exact lineage. The toolchain's identifier carries the upstream version
and commit (
1.99.0-beta-f47d5bb-motor.dev.1during the beta), andrustc -vVreports the Motor Rust commit it was built from. Two keys derived from the inputs name the local outputs: the toolchain key covers the compilers and their libraries, and the assembly key adds the C sysroot inputs, so amoto-rtor mlibc change produces a new assembly without a new compiler. - A manifest everywhere. The installed toolchain, every assembly, and
the developer image (as
/devtools/toolchain/manifest) carry a manifest with the revisions, keys, and hashes they were built from. - The same C wrappers.
motor-clang,motor-clang++, andmotor-rust-ccare generated into each assembly's sysroot. - A stable baseline to come. The current toolchain is built from the
Rust 1.99 beta, and Cargo reports
1.99.0-dev. The first stable release,1.99.0-motor.1, is planned on the exact Rust 1.99.0 tag once it ships (scheduled for October 2026): the Motor patches are rebased onto it, everything is rebuilt and revalidated, and only then are the source tags published in the forks. Binaries are not published; the toolchain is built locally from the tagged sources.