ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
32.37k stars 2.36k forks source link

Feature request: libc header import without libc library import #7687

Closed ityonemo closed 1 day ago

ityonemo commented 3 years ago

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.

matu3ba commented 3 years ago

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

ityonemo commented 3 years ago

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

iacore commented 1 year ago

As a workaround, use musl.

matklad commented 2 weeks ago

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"?

andrewrk commented 1 day ago

Expected to be solved by #20630