MMotor OS
Developing

C/C++ on Motor OS

Rust is the preferred language on Motor OS, but C and C++ are fully supported. Motor OS has a working C library (mlibc), the LLVM C++ runtime (libc++, libc++abi, libunwind), and a Clang/LLVM toolchain that targets Motor OS directly. The developer image compiles C and C++ natively, the same toolchain cross-compiles on Linux, and Lua ships on the developer image as a stock C program built with it.

How it fits together

C or C++ program
  libc++ / libc++abi / libunwind          (C++ only)
  mlibc: stdio, malloc, pthreads, sockets, dirent, poll, locale, ...
    Motor OS sysdeps                       (mlibc's OS layer, written for Motor)
      libmoto_rt_cabi: a C ABI over the Motor runtime   (<moto_rt.h>)
        rt.vdso  ->  kernel / sys-io

mlibc is a portable C library also used by managarm and other operating systems. It was chosen because it already provides what real programs and compilers need, pthreads, a POSIX-shaped filesystem API, posix_spawn, sockets, and locales, so the port consists of an OS layer for Motor and a C ABI shim over the same runtime that Rust's standard library uses. The C library is built with mlibc's ANSI and POSIX option groups. Its runtime configuration, resolv.conf and hosts, lives in /system/cfg/libc, which sys-io maintains and which every image carries, so a C program runs on the standard image too, not only on the developer image.

The target

x86_64-unknown-motor is a real Clang target, not a set of flags to remember:

mlibc is implemented in C++ internally, so even a pure C program links libc++abi and libunwind; the driver does this automatically.

What is supported

AreaSupported
C standard librarystdio including memory streams, printf/scanf with correct float round trips, stdlib, string, math, locale, wide characters, setjmp/longjmp, abort (exit status 134), atexit.
Memorymalloc and friends, aligned_alloc, posix_memalign, anonymous mmap.
Files and directoriesopen, read, write, lseek, stat/fstat, dirent, getcwd/chdir, mkdir, rename, unlink, ftruncate, fsync, temporary files and directories, isatty. Permissions follow the three-role model (see Filesystem).
Threadspthreads: threads, mutexes, condition variables, read-write locks, pthread_once, keys with destructors; thread-local storage.
NetworkingBSD sockets over TCP and UDP, IPv4 and IPv6; getaddrinfo using the same resolv.conf and hosts files as the Motor DNS service; poll and select, bridged onto the runtime's readiness interface.
Processesposix_spawn, waitpid, system and popen (through /system/bin/sh, which is rush), getenv, getpid, exit codes.
SignalsSynchronous only: signal, sigaction, and sigprocmask record dispositions, raise runs the handler in the calling thread, kill terminates a child. Nothing is delivered asynchronously; Ctrl+C is handled as described under Terminals.
Timeclock_gettime with real-time and monotonic clocks, nanosleep, strftime.
C++libc++ with exceptions and RTTI on; <iostream>, containers, <thread>, <filesystem>, <random>, <chrono>, locales, wide characters, aligned new, static constructors and destructors in the right order.
Motor-specific calls<moto_rt.h> exposes the runtime's C ABI (files, sockets, memory, futexes, arguments and environment, random bytes, logging, terminal status) for programs that need something POSIX does not express.

Differences from Unix, by design

Motor OS is not Unix, and the C library does not pretend otherwise. The differences below are deliberate properties of the system, described in detail on the Processes, Filesystem, and Terminals pages; for a C program they mean:

Building

On the developer image

cc and c++ in /devtools/bin are short scripts over the LLVM multicall binary in /devtools/llvm/bin; headers are under /devtools/llvm/include and the libraries under /devtools/llvm/lib. The samples in /devtools/src build like this:

cd /devtools/src
cc -O2 hello.c -o /devtools/tmp/hello && /devtools/tmp/hello
c++ -O2 hello.cpp -o /devtools/tmp/hello-cpp && /devtools/tmp/hello-cpp

A freshly linked program is executable by its creator and by higher roles, so it can be run at once. The developer image has no make; small projects are built from a rush script or by listing the sources on one cc line. Compiler temporary files go to /devtools/tmp.

On Linux

The Motor OS build produces the same Clang for the Linux host together with a sysroot and two wrappers, motor-clang and motor-clang++, that run it with --target=x86_64-unknown-motor and the sysroot:

motor-clang -O2 hello.c -o hello
motor-clang++ -O2 hello.cpp -o hello-cpp

Because the result is static, it runs on any Motor OS image; copy it in with scp as in Hello Motor OS. The host toolchain and the wrappers are described on the Toolchains page.

Lua

Lua 5.4.8 ships on the developer image as /devtools/bin/lua: the interpreter and its interactive REPL, built with the Motor toolchain from the unmodified upstream sources, with no source patches, using Lua's POSIX configuration. It was the first real C program brought up on the C library, and its acceptance script is part of the libc test suite.

lua -e 'print(_VERSION)'
lua script.lua

How it is tested

The C library was brought up milestone by milestone, with a test program for each: toolchain, the runtime shim, mlibc bring-up, stdio and malloc, the filesystem, threads and TLS, sockets, poll/select and signals with Lua as the real program, and the C++ stack. The plan and the record of each step are in docs/porting-libc/ in the repository. The developer-image test run (src/tests/full-test-dev.sh) compiles and runs the shipped C and C++ samples natively in a VM, including a check that fstat answers correctly for files, sockets, and terminal descriptors and that the temporary-directory contract holds for both C and std::filesystem.