| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Compile unmodified Rust crates into fully-static, libc-free Linux binaries.
fullrust is a patched Rust toolchain whose standard library talks to the Linux kernel through raw syscall instructions instead of libc. An ordinary crate — no code changes, no attributes, no fullrust dependency — compiles to a static x86_64-unknown-linux-fullrust ELF that links no libc and no C runtime: no interpreter (PT_INTERP), no .dynamic section, zero NEEDED libraries. The only thing the binary needs to run is the Linux kernel.
You use it as a GitHub Action or a Docker image — no local toolchain to install, no nightly, no -Z build-std, no target JSON.
// src/main.rs — a completely ordinary program
use std::collections::BTreeMap;
fn main() {
let mut counts = BTreeMap::new();
for w in "the quick brown fox the fox".split_whitespace() {
*counts.entry(w).or_insert(0) += 1;
}
println!("{counts:?}");
}$ file target/x86_64-unknown-linux-fullrust/release/wordcount
ELF 64-bit LSB executable, x86-64, statically linked
$ ldd target/x86_64-unknown-linux-fullrust/release/wordcount
not a dynamic executable
$ readelf -d target/x86_64-unknown-linux-fullrust/release/wordcount
There is no dynamic section in this file.Anything that reaches for a C library fails at link time — pure-Rust code links, FFI into a .so does not. That's an intended guard-rail, not a bug.
One step. It runs the fullrust toolchain image against your checked-out crate and leaves the binary under target/x86_64-unknown-linux-fullrust/release/.
- uses: actions/checkout@v6
- uses: KarpelesLab/fullrust@master
with:
args: --release --bin myappname: Release
on:
push:
tags: ["v*"] # or: release: { types: [published] }
permissions:
contents: write # required to upload release assets
jobs:
linux-x86_64-static:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build the libc-free static binary
uses: KarpelesLab/fullrust@master
with:
args: --release --bin myapp
- name: Package + attach
run: |
tar -C target/x86_64-unknown-linux-fullrust/release \
-czf "myapp-${{ github.ref_name }}-linux-x86_64-static.tar.gz" myapp
- uses: softprops/action-gh-release@v2
with:
files: myapp-*-linux-x86_64-static.tar.gz| input | default | meaning |
|---|---|---|
| command | build | cargo subcommand: build, test, run, clippy, … |
| args | --release | extra cargo args, e.g. --release --bin myapp --no-default-features |
| working-directory | . | the crate to build |
| image | ghcr.io/karpeleslab/fullrust:1.88 | pin a Rust version (see Versions) |
| no-ecosystem | false | skip the getrandom/socket2 [patch.crates-io] injection |
The image bakes the toolchain into its environment (RUSTC, CARGO_BUILD_TARGET, a CARGO_HOME carrying the ecosystem [patch]), so a plain cargo build is already a fullrust build — the same static, libc-free binary the action produces:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/karpeleslab/fullrust:latest
steps:
- uses: actions/checkout@v6
- run: cargo build --releaseNo toolchain install — mount your crate and build:
docker run --rm -v "$PWD":/src ghcr.io/karpeleslab/fullrust:latest build --release
# `test`, `run`, `clippy` work the same way; run `bash` for an interactive shell.The binary lands in your crate's target/x86_64-unknown-linux-fullrust/release/.
Images are published per Rust minor, plus latest (the newest):
ghcr.io/karpeleslab/fullrust:1.88 … :1.95 :latest
They're public — no login to pull. Pin one via the action's image: input, the container: image, or the docker run tag. The action currently defaults to :1.88; for the newest Rust, set image: ghcr.io/karpeleslab/fullrust:1.95 (or :latest).
An unmodified crate gets the real standard library, with its platform backend rewritten on raw syscalls:
fullrust gives the standard library its own platform backend on Linux syscalls, instead of routing it through the platform libc. This is the same architecture as the Go runtime: Go issues syscalls itself and only touches libc when you opt into cgo. fullrust is, in effect, Rust with cgo off — the binary's only boundary to the outside world is the syscall instruction. It is still the real std, so ordinary crates compile unchanged.
The deciding principle is keeping Rust's guarantees end-to-end, all the way to the kernel — which a pure-Rust libc shim (the Eyra / c-scape model) gives up at a C-shaped wall in the middle of every OS interaction:
The one accepted cost, like Go: programs target fullrust's std rather than being able to link arbitrary C libraries. (Pure no_std + alloc crates still work as-is; only code that needs OS services through libc is excluded — on purpose.)
fullrust is a source overlay on the Rust compiler that adds the built-in x86_64-unknown-linux-fullrust target and a std::sys backend on raw syscalls (the allocator, native TLS, threads, fs/net/process, the pure-Rust unwinder and backtraces), packaged as a thin Docker image around the prebuilt toolchain. It tracks released Rust versions (currently 1.88–1.95).
See toolchain/README.md for the design, the syscall-backed platform layer, and how the overlay is built and ported across Rust versions.
MIT OR Apache-2.0.
| Back | FazBrowse Home | New Git URL |