zig creating a C library

3k Views Asked by At

Closed - see the end of the entry

I want to make a C callable library using the zig language. I decided to start with the two examples in the Zig documentation. "Exporting a C Library" and "Mixing Object Files". In each case I copied the three relevant files(from 0.6.0 docs).

  • A C file called test.c,
  • a zig file called respectively mathtest.zig (for the Exporting a C Library example) and base64.zig (for the Mixing Object Files example), and
  • a build.zig file.

Both examples fail to build.

The Exporting a C Library example fails to compile test.c with a message cannot find mathtest.h

The Mixing Object Files example fails to compile test.c with cannot find base64.h

Here are the three files for the Exporting C Libary example:

mathtest.zig

export fn add(a: i32, b: i32) i32 {
    return a + b;
}

test.c

// This header is generated by zig from mathtest.zig
#include "mathtest.h"
#include <stdio.h>

int main(int argc, char **argv) {
    int32_t result = add(42, 1337);
    printf("%d\n", result);
    return 0;
}

build.zig

const Builder = @import("std").build.Builder;

pub fn build(b: *Builder) void {
    const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));

    const exe = b.addExecutable("test", null);
    exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
    exe.linkLibrary(lib);
    exe.linkSystemLibrary("c");

    b.default_step.dependOn(&exe.step);

    const run_cmd = exe.run();

    const test_step = b.step("test", "Test the program");
    test_step.dependOn(&run_cmd.step);
}

Part of the error message

~/Projects/zig/z-c-lib $ zig build test
/home/robert/Projects/zig/z-c-lib/test.c:2:10: fatal error: 'mathtest.h' file not found
#include "mathtest.h"
         ^~~~~~~~~~~~
1 error generated.

The following command failed:
/home/robert/zig/zig clang -c -nostdinc -fno-spell-checking -target x86_64-unknown-linux-gnu -isystem /home/robert/zig/lib/zig/include -isystem /home/robert/zig/lib/zig/libc/include/x86_64-linux-gnu -isystem /home/robert/zig/lib/zig/libc/include/generic-glibc -isystem /home/robert/zig/lib/zig/libc/include/x86_64-linux-any -isystem /home/robert/zig/lib/zig/libc/include/any-linux-any -Xclang -target-cpu -Xclang znver2 -Xclang -target-feature -Xclang -3dnow -Xclang -target-feature -Xclang -3dnowa -Xclang -target-feature -Xclang +64bit -Xclang -target-feature -Xclang +adx -Xclang -target-feature -Xclang +aes -Xclang -target-feature -Xclang +avx -Xclang -target-feature -Xclang +avx2 -Xclang -target-feature -Xclang -avx512bf16 -Xclang -target-feature -Xclang -avx512b

I cannot find a file named mathtest.h on my system so I assume it was not generated, contrary to the claim in the test.c file.

What am I missing ? Help gratefully accepted.

Answers and More questions

I discovered the -femit-h options:

zig build-lib mathtest.zig -femit-h

will create a mathtest.h file and then

zig build

will be successful.

I further discovered that these lines in the build.zig files

const lib = b.addSharedLibrary('mathtest', 'mathtest.zig', b.version(1, 0, 0));
lib.femit_h = true;

will ensure that

zig build test

will be successful and generate the answer 1379 as indicated in the docs.

BUT - this mod to the build.zig file does not leave a mathtest.h file around after it runs.

That seems to be the final hurdle to generating a usable C library from a Zig code.

Final piece in the puzzle

If I add

lib.setOutputDir("build");

to the build.zig file. The mathtest.h and libmathtest.a (or .so) files will be saved into a build dir.

Call this one close

1

There are 1 best solutions below

1
On

Ok so part of the answer is simple, but maybe obscure, the -femit-h options. The command

zig build-lib mathtest.zig -femit-h

will generate a mathtest.h file. But how do I add that options to the

const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));

line in the build.zig file.