Using a single-header C library from Zig

I had the same issue trying to compile the stb_image header only library. Here is what you need to do:
First you need a C wrapper:

/// raygui_impl.c
#define RAYGUI_IMPLEMENTATION
#includes "raygui.h"

Then you need to include it in the compilation:

/// build.zig                     ↓ Could add multiple files           ↓ compilation flags
exe.addCSourceFiles(&[_][]const u8{".../raygui_impl.c"}, &[_][]const u8{"-g", "-O3"});

And finally you still need to include the header, but without the #define:

const c = @cImport({
    @cInclude("raygui.h");
});

If you want there is also a way to avoid creating the extra C file, by adding the define directly to the compile command arguments with -D.


Now this scheme won’t work with your shlib.h because it isn’t a fully functional header-only library. If you were to include shlib.h from 2 different compilation units, you would get a duplicate symbol error. Header-only libraries separate the header from the implementation to avoid this:

#ifndef SHLIB_H
#define SHLIB_H

// C single-header library

int multiply(int a, int b);

typedef struct my_args_struct
{
    int a;
    int b;
} my_args;

int multiply_args(my_args args);

#endif

#ifdef SHLIB_IMPLEMENTATION

int multiply(int a, int b)
{
    return a * b;
}

int multiply_args(my_args args)
{
    return args.a * args.b;
}
#endif
4 Likes