Adding PicolibC (Or Alternative) for Embedded?

Read Andrew’s article on all the hoops that were jumped through to bundle a variety of all different “libc” implementations in a size efficient manner with Zig here:
https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html

Are there any plans to bundle an “embedded friendly” libc variant like picolibc:

ARM is already using it in their Clang/LLVM based toolchain for their chips (along with newlib):

IMO this is the only piece missing from the puzzle in terms of making Zig a super compelling compiler replacement for bare metal systems. Being able to translate the 100+ line vendor-generated eyesore of a Makefile that comes with every “hello world” program into a simple build.zig could gain some serious traction in the embedded community. Thoughts?

5 Likes

Considering that people developing programs that target embedded devices seem to do their development on a normal host (where Zig already runs), I think it would make sense to integrate other libc implementations via packages, that get downloaded automatically when you target specific embedded targets.

Similar to how c/c++ is suspected to be handled when llvm is removed from the compiler, that it gets downloaded as package when you use it.


But I also wonder whether the existing bundled libc implementations could get further “treatment” to add additional tricks used by picolibc?

What makes picolibc smaller, is it removing features, sharing more code, removing optimizations, reducing generality / removing special cases?

Could you get similar results if you started with a normal libc but applied a specific set of optimizations, maybe even specifically written for this purpose to it?

So if picolibc is a set of things you can’t really replicate through some automated process, I think it would be better as a package, if you somehow can replicate it or get similar results, through applying some transformation to a “normal” libc then that would seem more interesting.

I think ultimately somebody would have to be familar with Zigs bundled libcs and how picolibc is implemented, to be able to say whether it makes sense to mix them in any way.

I think it is relatively unlikely that adding picolib to the existing bundle makes sense, from a compressability and similarity to the existing elements viewpoint.
And as soon as it is its own unit, it seems appropriate to make it some package (maybe even an official package that is seen as part of the language).


Another thing I wonder about, is how an embedded libc would look like when you start from scratch, in the context of using it from Zig and using Zigs features.
For example whether comptime or specialized build steps would make its design more flexible / elegant or easier to optimize in some automated manner.

I think an implementation that is written in Zig would have a higher likelihood to end up in the initial language distribution / download (I also think there was an issue for creating a Zig libc implementation).
Personally I think putting things in packages is good and keeping the initial download to the most common things, I don’t think packages should be seen as a lower level of support/importance.

But which package/implementation gets more Zig/community attention and support, then has an effect on which approaches are more supported and better integrated into the language.

I think a libc written in Zig would just naturally lead to more Zig developers working on it, and the compiler is more likely able to create highly optimized builds of it.

Generally speaking, picolibc is derived from the project “newlib”:
https://www.sourceware.org/newlib/

And you got it, it’s a “bare bones” libc implementation that focuses on small code size, and essentially being able to “run on anything”. Since you don’t have an OS on a bare metal embedded device, all the OS related calls (stuff like printf, fopen, 'write, etc.) are stubbed out and it’s up to the user to provide their own implementation if they need those calls to do something.

Could you get similar results if you started with a normal libc but applied a specific set of optimizations, maybe even specifically written for this purpose to it?

Maybe! “Normal” is sort of in the eye of the beholder I guess. For instance, Zig currently bundles 3 different flavors of libc that through previously described blood + sweat + tears can cross compile for many many targets:

Mingw and glibc are out as contenders, as those are basically libc flavors designed to work with specific OSes. So could you remove stuff from musl and make it “embedded friendly”? Maybe! Or would it just be easier to let someone else do the work for you and make it a list of 4 instead of 3? Also maybe!

I think a libc written in Zig would just naturally lead to more Zig developers working on it, and the compiler is more likely able to create highly optimized builds of it.

There are indeed people doing this! @marler8997 is making one in Zig aiming to be a general purpose libc:

And “xq” from the Zig Embedded Group Discord is making an embedded specific libc, also written in Zig:

Final thoughts, by “package” do you mean something downloaded via Zig’s up and coming package manager (.zon files)? Agreed that could be a good avenue for some of these “less common” flavors of libc rather than bundling it with the language itself.

I guess my dream is a language/compiler that supports freestanding/embedded in a first class fashion “out of the box”. A common refrain you encounter programming firmware is:

  • “Here’s how this thing works when compiling/running on Linux.”
  • “Oh nice! How do I use it if I don’t have an OS? How do I compile this for a 32 bit ARM MCU?”
  • “Oh… IDK read some forums or something…”

The sales pitch of “You can build Zig, C, and C++ code out of the box for your freestanding target, no monkeying around required” is an incredibly powerful one for me personally.

3 Likes

Yes. While the package manager still has rough edges / missing features, I think it is already very useful and practical.

That’s what I was trying to express, I think making something into a package that is downloaded on demand, doesn’t mean that it has only 2nd class support.

I also have the impression that the people working on Zig, envision it, to have this sort of first class support, I think the reasons for it not having this support currently, reduce to other things being prioritized and what people choose to focus on, at least that is how it seemed to me.

Andrew has said, that he doesn’t choose what people work on, so if a group of embedded developers decided to work on better embedded support, I think that could move things forward into that direction.

Without that I still think it will be done eventually, I just think there is a bigger demand/driving force to push the non-embedded things forward.

I am curious how things shift after the incremental compilation is implemented.

I agree and I haven’t even targeted embedded, but I can imagine the pain of not having it, from the things I have read, that people go through to get things working.

Ahh okay got it, it could be an “official” package that is still downloaded on demand only when you target something freestanding since the majority of developers won’t use it (and thus it doesn’t make sense to bundle w/ the base download). Similar to adding a target via rustup target add in Rust. Makes total sense to me!

Andrew has said, that he doesn’t choose what people work on, so if a group of embedded developers decided to work on better embedded support, I think that could move things forward into that direction.

Sign me up for some of that work! Maybe not the forum, but do you know who would be best to contact to start dipping my toes into that category of development?

I don’t know exactly, what I wrote is more based on the general vibe I got, I am still not very deep in my understanding of what is going on in the development side of things. (I sometimes read issues, look at commits, or read some conversations, but currently that is all I have done)

I think you could create another topic in this forum “Looking for zig developers working on zigs embedded support” then also advertise that in the 2 zig discords (the main one and that of the embedded group Community · ziglang/zig Wiki · GitHub)

Personally I would then try to find existing issues with those people that represent features/problems that are relevant to making embedded use better and see if there are any easy or low hanging fruit. And also see whether there are missing issues that describe problems with embedded. Or things that could be done without getting into the way of other things that are currently worked on.

It seems to me that one of the main issues with embedded, is that people are too used to having to brave through things on their own and thus expect that there is low support.

So overall I think the first step may be to bring together different embedded people and build a community of “lets fix this in the compiler” instead of everyone on their own, in their obscure hidden away personal project.


Some libc related things I read:
implement libc in zig #514
andrewrk 514#issuecomment:

Repeating this here:
Currently zig builds musl from source with minimal modifications. The next step will be to also include std/special/libc.zig (which I have not started yet) as the root source file when creating libc.a for musl. And then slowly, we can start deleting C source files from the musl that zig bundles, and porting the code to zig instead.

Another nice optimization/research area would be to not have a separate .a file for libc, but actually export some additional functions from the same object file as the root zig source file. In this way the libc and the zig code could share implementations and shave off bloat. This would probably be helped a lot by an incremental compiler.

provide common implementations where applicable for libc functions #2879

Maybe that issue would make sense to work on? If libcs would share more code than I imagine it would be easier to have better coverage for the things that can’t be shared? (Because you would work on a smaller code base)

But I am not sure, I don’t have the embedded knowledge to be able to tell what would be a big win to make things better.


I think you also could ask in the discord #embedded channel to find other people using embedded (I don’t know if some of them also work on the compiler).

Then you could ask in the #compiler-devel channel if there are issues related to embedded that you could get started with / are beginner friendly, or maybe somebody there could point you into the right direction.

Apparently there are also regular compiler meetings there, if you read the channel description, I haven’t attended yet, but I imagine listening in on those would also be beneficial in getting started.


Of course they also could answer in this forum, it just seems that a lot of the development communication happens in the compiler-devel channel (and issues).

Awesome! Thanks so much for all the info, I’ll start poking around :slight_smile:

1 Like