zig icon indicating copy to clipboard operation
zig copied to clipboard

Feature request: libc header import without libc library import

Open ityonemo opened this issue 5 years ago • 3 comments

For FFIs which use C ABI as a least common denominator, but I'm sure also some header-only C libraries, may not use any stdlib externs, but might still need accoutrements of the C stdlib headers (e.g. types.h). It might be nice to provide a way to leverage zig's header resolution logic without doing linkSystemLibrary("c") which would unnecessarily bring in libc into the project.

ityonemo avatar Jan 04 '21 21:01 ityonemo

~~Probably the documenation (#1596) should be finished first.~~ Just curious: Is identifying manually the header files, which dont depend on libc, that difficult?

matu3ba avatar Jan 05 '21 00:01 matu3ba

Yeah, it gets tricky (but not impossible) if you want cross-compilation to be possible.

ityonemo avatar Jan 05 '21 00:01 ityonemo

As a workaround, use musl.

iacore avatar Jun 12 '23 12:06 iacore

Appaerntly, if you don't link to libc, but just have some -I entry, it works?

Here's my "C" library with a header file which doesn't really depend on libc at runtime:

λ bat mylib.h
#include <stdint.h>

int64_t get_number();

λ bat mylib.zig
export fn get_number() u64 {
    return 92;
}

λ zig build-lib mylib.zig

Here's the Zig code which imports the header

λ bat main.zig
const std = @import("std");
const c = @cImport(@cInclude("./mylib.h"));

pub fn main() void {
    std.debug.print("{}", .{c.get_number()});
}

If I just try to compile it, I get the error I expect to get given this issue:

λ zig build-exe main.zig libmylib.a.o
main.zig:2:11: error: C import failed
const c = @cImport(@cInclude("./mylib.h"));
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.zig:2:11: note: libc headers not available; compilation does not link against libc

That is: no cImport if you don't link libc!

But, if I add -I for my header, this somehow gets it to work!

λ zig build-exe main.zig libmylib.a.o -I. && ./main
92
λ ldd ./main
	not a dynamic executable

Notably, not only Zig is able to find my mylib.h, but internal clang is able to find <stdint.h>. looking at --verbose-cimport, it seems that it uses the correct stint.h:

λ bat /home/matklad/tmp/.zig-cache/o/e4d0a93094219ef8a9216d4c64d1b94a/cimport.h.d
cimport.o: \
  /home/matklad/tmp/.zig-cache/o/e4d0a93094219ef8a9216d4c64d1b94a/cimport.h \
  mylib.h /home/matklad/p/tb/work/zig/lib/include/stdint.h

So it looks like this might have been mostly fixed as of Zig 0.13, and only the error message needs to be adjusted: it's not about libc headers, it's about the parcitular header you try to cImport

EDIT: further investigation shows that <stdint.h> works, but <stdio.h> doesn't (it fails with libc headers not available). This seems precisely the behavior we want here, but I am very puzzled about how this could work, I thought that C headers don't make distinction between "this is a stand-alone headers" and "this requires a c runtime library"?

matklad avatar Jun 26 '24 11:06 matklad

Expected to be solved by #20630

andrewrk avatar Jul 14 '24 23:07 andrewrk