Zig Got a New Elf Linker and It's Fast
Posted3 months agoActive3 months ago
github.comTechstoryHigh profile
excitedpositive
Debate
20/100
Zig Programming LanguageElf LinkerCross-Compilation
Key topics
Zig Programming Language
Elf Linker
Cross-Compilation
The Zig programming language has a new ELF linker that is significantly faster, sparking enthusiasm and discussion about its potential as a standalone C/C++ compiler and cross-compilation toolchain.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
1h
Peak period
24
0-6h
Avg / period
7.1
Comment distribution50 data points
Loading chart...
Based on 50 loaded comments
Key moments
- 01Story posted
Sep 21, 2025 at 6:40 PM EDT
3 months ago
Step 01 - 02First comment
Sep 21, 2025 at 7:43 PM EDT
1h after posting
Step 02 - 03Peak activity
24 comments in 0-6h
Hottest window of the conversation
Step 03 - 04Latest activity
Sep 24, 2025 at 8:25 AM EDT
3 months ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
ID: 45327318Type: storyLast synced: 11/20/2025, 3:38:03 PM
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
ref: https://ziglang.org/devlog/2025/#2025-06-08
My point was that Zig uses their backends (which includes their homegrown ones), but since `zig cc` is a wrapper around Clang, it always goes through the `LLVM` path and sidesteps the Zig backend(s).
There are other projects that have used it in a similar way too.
[1] https://actually.fyi/posts/zig-makes-rust-cross-compilation-... [2] https://jcbhmr.com/2024/07/19/zig-cc-cmake/
Perhaps you just feel that way because of 10+ years of accreted expectations?
To me, it feels like a reinvention of an interesting idea: Fastbufs
https://www.ucw.cz/libucw/doc/ucw/fastbuf.html
I will concede that the ergonomics of Io in Zig right now are pretty rough sledding.
Awkward relative to what?
Relative to C? Did you look at my link to Fastbufs? Take a look at that and then get back to me how awkward Zig is relative to that.
Zig seems to be aiming to be a better C. Full stop. If you want abstraction, RAII and other higher-level stuff, C++ and Rust exist.
> If they are going to become that fundamental to core features of the language, I think a more ergonomic way to work them needs to be a higher priority.
I don't disagree. However, there have really only been two times so far that significant "interfaces" have churned like this (Allocgate and Writergate). Allocgate was driven by the fact that the previous implementation had real, measurable performance issues. Presumably, Writergate is being driven by similar problems. I'm actually really happy that someone is designing a language while paying very strict attention to the performance of both the compiler and the compiled code.
It's really hard to generalize until you get a couple of concrete examples under your belt. Trying to make an "interface" more ergonomic when it may get nuked from orbit in a couple of versions is kind of pointless.
I have plenty of gripes about Zig, but "interface churn" or "ergonomics" aren't very high on my list. I signed up for a language that is pre-1.0, so, while I may get annoyed, I also have to admit that I did this to myself.
For loops with a capture group. Under the hood Zig is doing bounds checking and binding the result of each iteration to the variable in the capture groups.You can add a range to that and Zig will iterate it for you. One could argue this is a "higher level" abstractation compared to a traditional for loop and accessing an array by index, but it exists because it naturally pushes developers to write more robust code.
The try keyword, being short hand for catch err return err. A Go developer might argue that it's better to be explicit and not have try. But it's a common pattern and it's far more ergonomic to use the try keyword then it is to catch and return every single time.
Shit, you could argue that the entire idea of comp time is an abstraction to allow code generation. Someone like Ginger Bill would argue you're better off writing a separate program to generate source code then use meta programming.
With the upcoming IO interface and the plans for async, it seems to me that interfaces are going to play a much more prominent role in the language. It makes sense they might want to consider abstractions that push developers towards good design when working with them.
Modula-2 and Object Pascal already did that for me, before I cared with C on MS-DOS, unfortunely one did not come with UNIX as selling point, and the other had the two industry giants that cared doing the wrong decisions.
I really like Zig, but I do think you have to accept some rough edges and breaking changes when using it. Give it another decade and I am hopeful it will be much more stable.
This one is fairly minor, but the overly granular namespacing drives me nuts. I shouldn't have to go four or five layers deep to get fairly common functionality. The pattern of returning structs from within structs from within structs just gets old. Maybe that has to do with the way the language handles generics, I don't know.
The attitude to interfaces is also grating. I get that Kelly and the Zig team want to discourage there use, but with the changes to Io it feels a bit like they want to have their cake and eat it to. Before it was mainly just allocators, but now readers, writers, and it sounds like async are all going to be handled through interfaces. But yet the community writ large is still expected to not really use them. Seems like they should have sorted their attitude and approach to interfaces before making these most recent changes.
Let me ask this: hypothetically if they wanted to, would it be possible for Zig to add a language feature called Interface which provided to the user "...an easy way of creating one".
Perl objects worked like this and the ecosystem is a mess as a result. There's a built in `bless` to add a vtable. There's some cool stuff you can do with that like blessing arrays to do array of structs vs struct of arrays and making it look like a regular object in user code. The problem is there are like 4 popular object libraries that provide base stuff like inheritance, meta objects, getters/setters etc and they're not all compatible and they have subtle tradeoffs that get magnified when you have to pull multiple in to get serious work done.
Nobody is going to want to live without proper interfaces or an equivalent in 202x instead of DIY hacks. Its a fundamental, building-block of software development. You will have a gazillion complaining in Zig forums after its 1.0 release.
Interfaces however are far more fundamental. Any app with components and modularization would declare intent through interfaces. Not having interfaces/traits as a language feature is like living without a hand or leg. Sure you can limp and hop, but it will get rather tiresome.
Yeah, I can see that. It's also difficult to put my finger on, but for a language that claims to be simple it seems to make a lot of things needlessly complicated. I'm also not loving how everything is deeply nested structs so I have to do struct.doThefirstThing.doTheSecondThing.doTheThirdThing().etc() all the time.
One annoyance that I've ran into when using Zig as a transpiler backend is the lack of unstructured goto. Many languages don't need that, but if you're dealing with the one that does, converting such code is non-trivial.
Those cases are definitely supported. Here's a reasonably faithful re-interpretation of Duff's device which generates the right assembly. If you'll take my word for it, code and assembly equivalent to goto in the middle of a loop body isn't an issue either. The only thing you're losing is the unreadable syntactic interleaving you can do in C.
The only thing you're really losing is that the goto is bounded by an enclosing function, but that's also the case in C, C++ and other languages written by non-masochists. From a developer ergonomics perspective you _might_ want a proper goto instead of having to rely on a clunky general-purpose transformation as described above (though I've yet to see that use case), but from a transpilation perspective it's extremely easy to just treat labeled switch as a bunch of gotos, replace other control flow with gotos, and lower an entire function into something that compiles optimally.
Eventually, I restructured my IR to allow for more imperative code-generation, which I believe will lead to slightly better optimizations by the compiler.
Does anyone know if it’s reasonably easy to use elf2 as a standalone linker in a c/c++ toolchain? Or is it specially built just for Zig?
https://github.com/jacobly0/zig/tree/4508c2543508e04253471e1... https://github.com/jacobly0/zig/blob/4508c2543508e04253471e1...
I might be mistaken, but the brief look at code shows that the speed up appears to come from combination of async architecture (the selling point of Mold) and intelligent usage of PUNCH_HOLE/INSERT_RANGE fallocate() operations.
Surprisingly enough PUNCH_HOLE and friends have already matured to be production ready, with viable support from ext4 and xfs filesystem. The possibilities!
No kidding. There are also https://github.com/davidlattimore/wild and https://github.com/kubkon/bold.
I'm using it as a cross-compiler for linux-arm64 because its much simpler to download a single archive and extract it somewhere than to waste a bunch of time on guessing how each different Linux distro does ARM64 cross compilers (or doesn't in the case of Fedora).
The more Zig-the-language is hyped, the more I see it doesn't bring anything of interest. Zig-the-toolchain, on the other hand, is neat.