How to get ABI-correct libc headers from Zig for Rust bindgen (missing size_t)

Hi,

I’m using the Zig toolchain to cross-compile a Rust project. To guarantee ABI compatibility, I need to obtain the exact libc headers that come with Zig for a specific target. I currently do this by running:

zig libc -includes -target aarch64-linux-gnu

Then I use those include paths with bindgen to generate FFI bindings.

However, there’s a problem:

When I disable system paths using -nostdinc and rely solely on Zig’s include paths, bindgen fails with:

unknown type name 'size_t'

Apparently, Zig’s stddef.h does not define size_t as expected, and I’m not sure what the correct way to include it is.

Have you encountered this issue before?
Do you know a better way to ensure ABI-correct bindings using Zig’s libc?

You could try to use the musl libc which in my experience is more portable:
aarch64-linux-musl

2 Likes

After some investigation, it appears that glibc expects each C compiler to provide freestanding headers (stddef.h, stdarg.h, etc) that conform to its requirements. So stddef.h doesn’t exist in any of the directories output from that zig libc command when the target is gnu. The LLVM freestanding headers (along with many other headers) are provided in the Zig lib/include directory, not in one of the lib/libc/include/... directories.

Musl, on the other hand, appears to provide its own freestanding headers. I don’t know any of the history here…

4 Likes

Yes, it works as expected with musl, thank you.

Would be worth filing an issue for zig libc about this.

1 Like