Is there a way of deal with "zig.h" from zig cc?

again, I am still in following the example at Documentation - The Zig Programming Language

I have mathtest.h generated

#include "zig.h"
zig_extern int32_t add(int32_t const a0, int32_t const a1);
zig_extern zig_noreturn void abort(void);
zig_extern uint32_t _dyld_image_count(void);
zig_extern struct mach_header__4062 *_dyld_get_image_header(uint32_t const a0);
zig_extern uintptr_t _dyld_get_image_vmaddr_slide(uint32_t const a0);
zig_extern uint8_t const *_dyld_get_image_name(uint32_t const a0);
zig_extern int getcontext(struct ucontext_t__6139 *const a0);
zig_extern void os_unfair_lock_lock(struct os_unfair_lock__2521 *const a0);
zig_extern int pthread_threadid_np(void *const a0, uint64_t *const a1);
zig_extern void *mmap(void *const a0, uintptr_t const a1, unsigned int const a2, unsigned int const a3, int const a4, int64_t const a5);
zig_extern int *__error(void);
zig_extern void os_unfair_lock_unlock(struct os_unfair_lock__2521 *const a0);
zig_extern int sigaction(int const a0, struct Sigaction__2796 const *const a1, struct Sigaction__2796 *const a2);
zig_extern int close$NOCANCEL(int const a0);
zig_extern intptr_t read(int const a0, uint8_t *const a1, uintptr_t const a2);
zig_extern int __ulock_wait2(uint32_t const a0, void const *const a1, uint64_t const a2, uint64_t const a3, uint64_t const a4);
zig_extern int munmap(void const *const a0, uintptr_t const a1);
zig_extern uint8_t *getenv(uint8_t const *const a0);
zig_extern int openat(int const a0, uint8_t const *const a1, unsigned int const a2, ...);
zig_extern int fcntl(int const a0, int const a1, ...);
zig_extern intptr_t write(int const a0, uint8_t const *const a1, uintptr_t const a2);
zig_extern int isatty(int const a0);
zig_extern int msync(void const *const a0, uintptr_t const a1, int const a2);

and copied the test.c from doc

// 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;
}

so if zig cc -c test.c, will see

In file included from test.c:4:
./mathtest.h:1:10: fatal error: 'zig.h' file not found
    1 | #include "zig.h"
      |          ^~~~~~~
1 error generated.

so it is include path problem, I then managed find ‘zig.h’, and do this zig cc -c -I <path-to>/.asdf/installs/zig/0.12.0-dev.1828+225fe6ddb/lib

I will see

In file included from test.c:4:
In file included from ./mathtest.h:1:
/Users/bytedance/.asdf/installs/zig/0.12.0-dev.1828+225fe6ddb/lib/zig.h:1756:26: error: use of undeclared identifier 'ZIG_TARGET_MAX_INT_ALIGNMENT'
 1756 |     uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;
      |                          ^
In file included from test.c:4:
./mathtest.h:8:34: warning: declaration of 'struct ucontext_t__6139' will not be visible outside of this function [-Wvisibility]
    8 | zig_extern int getcontext(struct ucontext_t__6139 *const a0);
      |                                  ^
./mathtest.h:9:44: warning: declaration of 'struct os_unfair_lock__2521' will not be visible outside of this function [-Wvisibility]
    9 | zig_extern void os_unfair_lock_lock(struct os_unfair_lock__2521 *const a0);
      |                                            ^
./mathtest.h:13:46: warning: declaration of 'struct os_unfair_lock__2521' will not be visible outside of this function [-Wvisibility]
   13 | zig_extern void os_unfair_lock_unlock(struct os_unfair_lock__2521 *const a0);
      |                                              ^
./mathtest.h:14:47: warning: declaration of 'struct Sigaction__2796' will not be visible outside of this function [-Wvisibility]
   14 | zig_extern int sigaction(int const a0, struct Sigaction__2796 const *const a1, struct Sigaction__2796 *const a2);
      |                                               ^
4 warnings and 1 error generated.

seems this ZIG_TARGET_MAX_INT_ALIGNMENT is defined by zig build system somehow.

but do we have a way to make this zig cc command line works, or event clang/gcc works?

This looks like a regression in the header generation code IMO. For example I would expect “zig.h” to be installed in the output directory alongside the generated header file.

I’ve tried taking a look at what the build system allows you to do with static libraries and when creating one (with addStaticLibrary), none of the options seem to govern header file generation, nor it seems to perform header file installation automatically. lib.getEmittedH() also doesn’t seem to have a graceful path towards installing header files and I’ve even got a build error when creating a dedicated install step for it:

const x = b.addInstallFile(lib.getEmittedH(), "foo.h");
b.getInstallStep().dependOn(&x.step);
$ zig build
install
└─ install generated to foo.h failure
error: unable to update file from '/Users/kristoff/Documents/bork/test/zig-cache/o/6fae6c22538b927c18e3a8dec50a5b1b/test.h' to '/Users/kristoff/Documents/bork/test/zig-out/foo.h': FileNotFound
Build Summary: 4/6 steps succeeded; 1 failed (disable with --summary none)
install transitive failure
└─ install generated to foo.h failure
error: the following build command failed with exit code 1:
/Users/kristoff/Documents/bork/test/zig-cache/o/ce905243f63d1ec9861a3cbbf0084fcc/build /Users/kristoff/Documents/zig/build/stage3/bin/zig /Users/kristoff/Documents/bork/test /Users/kristoff/Documents/bork/test/zig-cache /Users/kristoff/.cache/zig --seed 0x70e91e4b

I’ll link this thread to the build system development channel to see if anybody else has insight into this problem and report back if I discover anything new.

Apparently it’s still a work-in-progress part of the toolchain.

thanks @kristoff !

I found that for simple interfaces if I remove “zig.h” and “zig_extern” to something like below

#include <stdint.h>

int32_t add(int32_t const a0, int32_t const a1);

will compile and link with no problem. So before there is a better way from upstream zig, I guess I will use some postprocess steps for getting over it.

1 Like

Came to the same conclusion. Just keeping the useful parts (signatures) of the generated include file and adding stdint did the job for me (CGO integration).