Search code examples
zig

libc headers not available; compilation does not link against libc


I have the below zig library code:

// clib.zig
const std = @import("std");

const format = "Hello, {s} {s}!";

export fn joinStringsSize(firstname: [*:0]const u8, lastname: [*:0]const u8) u64 {
    return std.fmt.count(format, .{ firstname, lastname });
}

// Returns the number of bytes written, or 0 if there was not enough space.
export fn joinStrings(buf_ptr: [*]u8, buf_len: usize, firstname: [*:0]const u8, lastname: [*:0]const u8) u64 {
    var buf = buf_ptr[0..buf_len];
    const written = std.fmt.bufPrint(buf, format, .{ firstname, lastname }) catch return 0;
    return written.len;
}

And compiled it as: $ zig build-lib -dynamic clib.zig

Then I wrote the header file as :

// clib.h
uint64_t joinStringsSize(const char* firstname, const char* lastname);
uint64_t joinStrings(uint8_t* buf_ptr, size_t buf_len, const char* firstname, const char* lastname);

Which I assume is equivalent to the functions used in the library:

fn joinStringsSize(firstname: [*:0]const u8, lastname: [*:0]const u8) u64
fn joinStrings(buf_ptr: [*]u8, buf_len: usize, firstname: [*:0]const u8, lastname: [*:0]const u8) u64

And tried to consume this library using the below zig code:

// cmain.zig
const std = @import("std");
const c = @cImport({
    @cInclude("clib.h");
});

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{ .verbose_log = true }){};

    defer {
        if (gpa.deinit() == .ok) {
            std.debug.print("Memory has been managed correctly.\n", .{});
        } else {
            std.debug.print("Memory has not been managed correctly.\n", .{});
            // CAN I ADD SOMETHING HERE TO SHOW ME MORE DEATILS ABOUT THE LEAKS IN MY CODE?
        }
    }
    const allocator = gpa.allocator();
    const firstname = "Hasan";
    const lastname = "Yousef";
    var buf = try allocator.alloc(u8, c.joinStringsSize(firstname, lastname));
    defer allocator.free(buf);
    const len = c.joinStrings(buf.ptr, buf.len, firstname, lastname);
    const greetings = buf[0..len]; // not really necessary here, because we allocated the correct size from `joinStringsSize`
    std.debug.print("Saved string: {s}\n", .{greetings});
}

And tried to run it using $ zig run -I . cmain.zig I added -I . to enforce linking to the clib.h file that is existing in the same folder of the cmain.zig.

But I got the error:

$ zig run -I . cmain.zig
cmain.zig:2:11: error: C import failed
const c = @cImport({
          ^~~~~~~~
cmain.zig:2:11: note: libc headers not available; compilation does not link against libc
referenced by:
    main: cmain.zig:20:39
    callMain: /usr/lib/zig/std/start.zig:574:32
    remaining reference traces hidden; use '-freference-trace' to see all reference traces
./clib.h:8:40: error: unknown type name 'size_t'
uint64_t joinStrings(uint8_t* buf_ptr, size_t buf_len, const char* firstname, const char* lastname);

Not sure if libc means Igcc/clang is not installed, but I already have it:

$ ldconfig -p | grep libc.so                                                                                                                                                                           libc.so.6 (libc6,x86-64) => /usr/lib/libc.so.6
libc.so.6 (libc6) => /usr/lib32/libc.so.6

$ gcc --version
gcc (GCC) 13.2.1 20230801
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
clang version 16.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Solution

  • libc is installed on your system, but you didn't tell zig to use it.

    zig run -I . cmain.zig -lc