# Porting a C program to Foundry OS *Status: groundwork only (milestone M2 adds the first C programs to the image).* ## The toolchain Rustbelt 0.19.0 loads **static-PIE** programs (`ET_DYN` with no `PT_INTERP`), so C programs need no special link tricks any more. Every C program and port is built as a static-PIE: ```sh make musl # once: musl into out/sysroot (+ musl-pie.specs) toolchain/foundry-cc -O2 c/hello-musl.c -o out/hello-musl readelf -l out/hello-musl | grep INTERP # must print nothing ``` `toolchain/foundry-cc` is three lines: `gcc -specs out/sysroot/lib/musl-pie.specs -static-pie "$@"`. The specs file (`toolchain/musl/musl-pie.specs.in`, from Clarke's 0.19.0 re-test) points gcc at our musl headers and libraries and, for `-static-pie`, uses musl's self-relocating start file **`rcrt1.o`** and links with **`--no-dynamic-linker`**. **The gotcha:** the `musl-gcc` wrapper that musl itself installs (into `out/sysroot/bin`) uses upstream `musl-gcc.specs`, and with `-static-pie` that makes a *dynamic* PIE: it still has a `PT_INTERP` (`/lib/ld-musl-x86_64.so.1`). Rustbelt refuses that with `ENOEXEC`. So use `foundry-cc`, not that `musl-gcc`. Debian's `musl-gcc -static-pie` (package `musl-tools`) also works; the kernel builds its own musl fixtures with it. The binaries also run on the Linux host, which is handy because configure scripts run their test programs. The old `rb-cc` wrapper from the proposal (crt1.o, `-Ttext-segment`, `--defsym=_DYNAMIC`, `--no-relax`, for `ET_EXEC` at Rustbelt's high user base) is retired. The kernel keeps one program built that way (`vdsotest`) as a loader test. ## Adding a port ``` ports//.sha256 "SHA256 " ports//.url where to download it ports//patches/ 0001-*.patch ... ports//build.sh unpack from cache/, patch, CC=toolchain/foundry-cc ./configure --host=x86_64-linux-musl, make, install into out/staging (busybox/sbase: under /usr/lib/busybox) ``` Then boot it (`make test` / `make run`), try it, and note any missing syscall in [syscall-gaps.md](syscall-gaps.md). `run --trace prog` in rbsh shows every syscall, and `syscall_N(...) = -38 ENOSYS` marks the ones Rustbelt doesn't have.