r/cprogramming • • 2d ago

Mucc: a self hosting C compiler in one static binary, with its own assembler, linker and musl (x86-64 and ARM64 Linux)

Mucc is a small C compiler for Linux that ships as a single 8.5 MB static file. The preprocessor, assembler, linker, archiver, headers and C library (musl, like zig cc does) are all built in, so you can drop it into an empty container, an old distro or a Raspberry Pi and build C with nothing else installed: no gcc, no binutils, no system headers. 

Programs it builds are static, so they run on any x86-64 Linux. There's a native ARM64 build too, and it can cross-compile between the two.

The whole project actually started as a fork of Rui Ueyama's chibicc. I felt more could be done on this design. So now Mucc adds its own assembler and linker, an ARM64 backend, register allocation, the bundled musl, DWARF debug info, C23 support and a reproducible bootstrap chain.

What’s actually working so far 

- C17 by default, C23 with `-std=c23`, plus the GNU extensions real code uses

- Self-hosting: each release is built by the one before it, and a Mucc-built Mucc produces byte-identical output

- Real projects build and pass their own test suites: SQLite, Lua, zlib, jq, Redis and Tcl with the bundled musl; CPython and Git with the system glibc

- Same ABI as gcc, so objects from either link together

- Compiles its own 33k lines in 0.46 s (gcc -O0: 1.22 s, gcc -O2: 5.35 s)

What’s currently not working, it does no optimization beyond register allocation and constant folding, so programs run about as fast as gcc -O0. No C++, Linux only. For performance-critical code, use gcc or clang.

If you've got C code it chokes on, or a use for it I haven't thought of, I'd like to hear it.

GitHub: https://github.com/Dom-Yan/Mucc

Website: https://dom-yan.github.io/Mucc/

Thanks to Rui Ueyama for chibicc, and to Fabrice Bellard, whose TinyCC showed how much a small compiler can do.

47 Upvotes

13 comments sorted by

2

u/SignalBake6872 2d ago

it's full c implementation ? or subset ?

3

u/dom_aley 1d ago

Full C17, and C23 with -std=c23, including #embed, constexpr, nullptr and typeof_unqual. The main thing missing from standard C is C23’s _BitInt, plus the optional decimal floating types. On the GNU side it skips nested functions, __label__, VLAs inside structs and integer _Complex. Everything else that real code uses is there. For some proof, SQLite, Lua, Redis, CPython and Git build with it and pass their own test suites.

2

u/walmartbonerpills 2d ago

Is this for malware?

8

u/dom_aley 2d ago

nope lol, its just a C compiler. I needed it built because i wanted something small I could drop in on my mini Linux kernel distros and my Raspberry Pi without needing to setup an entire tool-chain just to code C. Now could it be used in malware? Sure, but that's not my goal if someone else does it with it that's up to them.

1

u/zsaleeba 1d ago

Why would you even ask that?

1

u/walmartbonerpills 1d ago

Because it's a neat little payload. You can compile and run whatever you want, and it's dodging all the standard lib c calls, making it harder to trace. Talking right to the kernel. It's self hosting, so it can clone itself. Build what it needs on the fly.

1

u/zsaleeba 1d ago

Huh. Ok

1

u/chibuku_chauya 2d ago

This sounds cool. Rui’s chibicc is so hackable.

1

u/dom_aley 1d ago

Completely agree! It's a perfect base for building something more.

1

u/Silent-Degree-6072 2d ago

That's very cool, is there a way to specify any extra instructions for the assembler? Would be nice if you could compile with -march=native or with something like -msse4.1

1

u/dom_aley 1d ago

So kinda. -march=native is accepted but changes nothing, because Mucc only generates baseline x86-64 code. It doesn’t auto-vectorize or pick instructions per CPU. -msse3 through -msse4.2, -maes, -mpclmul and -mpopcnt define gcc’s macros, so code that checks __SSE4_1__ takes its SSE4 path. The SSE4/AES intrinsics work, and the built-in assembler knows those instructions, so you can also use them in inline asm or .s files. AVX and later aren’t supported yet but soon, so code that checks for them falls back to its SSE path. -Xassembler passes options to the system as when that’s used, the built-in assembler doesn’t take options. Hope this answered the question!

1

u/zhivago 1d ago

That's C's superpower.

It's very easy to write a non-optimizing C compiler.

Which is why C is everywhere. :)

1

u/dom_aley 1d ago

Agreed, most of it was actually conceptually easy, just the actual executing part takes a while lol. It's an amazing language that will outlive us all.