Providing Overrides For Zig @cImport/C-Translate?

I am stuck for a solution for this, well not “stuck” but stuck in a non-manual override.

I am currently hitting this bug in C-Translate: Support _Atomic in translate-c · Issue #11415 · ziglang/zig · GitHub

Effectively it takes:

typedef struct zend_atomic_bool_s {
    _Atomic(_Bool) value;
} zend_atomic_bool;

And just turns it into an *anyopaque:

pub const struct_zend_atomic_bool_s = opaque {};
pub const zend_atomic_bool = struct_zend_atomic_bool_s;

This is a core struct used in the same namespace, same cImport all over the place. Problem is this creates a compiler error:

/Users/josephmontanez/Documents/GitHub/zig-php-ext/.zig-cache/o/cc86f11777ca8f405ed93dfdd6763ce3/cimport.zig:28545:19: error: opaque types have unknown size and therefore cannot be directly embedded in structs
    vm_interrupt: zend_atomic_bool = @import("std").mem.zeroes(zend_atomic_bool),
                  ^~~~~~~~~~~~~~~~
/Users/josephmontanez/Documents/GitHub/zig-php-ext/.zig-cache/o/cc86f11777ca8f405ed93dfdd6763ce3/cimport.zig:28499:39: note: opaque declared here
pub const struct_zend_atomic_bool_s = opaque {};
                                      ^~~~~~~~~

I have already correct this in Zig’s cImport.zig and it works great…

pub const struct_zend_atomic_bool_s = extern struct {
    value: @import("std").atomic.Value(bool),
};
pub const zend_atomic_bool = struct_zend_atomic_bool_s;

However I must manually patch the cImport.zig file at this time. I’ve tried introducing ZIG_SKIP_ZEND_ATOMIC_BOOL to bypass the struct completely and then tried a manual definition on my end:

const php = @cImport({
    _ = @import("fixes.zig");
    @cDefine("ZIG_SKIP_ZEND_ATOMIC_BOOL", "1");
    @cInclude("php_config.h");
    @cInclude("zend_API.h");
    @cInclude("php.h");
    @cInclude("ext/standard/info.h");
    @cInclude("wrapper.h");
});

However the scope of fixes.zig does not get applied to the c-translate namespace. I tried also using namespace:

const php = @cImport({
    const fixes = @import("fixes.zig");
    pub usingnamespace fixes;

    @cDefine("ZIG_SKIP_ZEND_ATOMIC_BOOL", "1");
    @cInclude("php_config.h");
    @cInclude("zend_API.h");
    @cInclude("php.h");
    @cInclude("ext/standard/info.h");
    @cInclude("wrapper.h");
});

This is not valid Zig code. I already patch the c-codebase with fixes to allow Zig to translate certain things correctly and provide work around for certain functions, but this is a low level type used all over the place and must be available in the same namespace. My last ditch effort is to disable atomic outright in the codebase as it’s already possible but I want this to be the last possible solution.

A temporary solution might be to create a header file with all the includes and define _Atomic as do nothing, then cInclude only the created header file.

#define _Atomic(x) x
#include "php_config.h"
#include "php.h"
...

When zig imports _Atomic(_Bool) value; after preprocessing will see _Bool value;.

NOTE:

  1. If sizeof(_Atomic(_Bool)) == sizeof(_Bool)) then this method is correct, otherwise it is not.
  2. You must not access the _Atomic variables from zig.

Thanks, sadly I can’t do this as there is still a ton of inline c code that expects atomic values and these are all in the header files. So I am stuck either manually overriding or just disable atomics. I really wish there was a way to hook into the build system after c-translate and just do string replace. As dumb as an idea that is, since its brittle, there are over 100+ c-translate bugs, some opened for years and I am already working around 4 other ones. Right now I am using a bash file instead of Zig Build, so I tried looking into the API for that, but not seeing any way to interject other than providing my own cTranslate files, but that’s just to translate c files, not provide pre-computed versions.

Perhaps it is easier to implement .Atomic in transType


For starting:

        .Atomic => {
            const atomic_ty = @as(*const clang.AtomicType, @ptrCast(ty));
            return transQualType(c, scope, atomic_ty.getInnerType(), source_loc);
        },

in clang.zig:

pub const AtomicType = opaque {
    pub const getInnerType = ZigClangAtomicType_getInnerType;
    extern fn ZigClangAtomicType_getInnerType(*const AtomicType) QualType;
};

and then implement the above method, in zig_clang.cpp:

struct ZigClangQualType ZigClangAtomicType_getInnerType(const struct ZigClangAtomicType *self) {
    auto casted = reinterpret_cast<const clang::AtomicType *>(self);
    return bitcast(casted->getInnerType());
}