Translate C lib using <immintrin.h>

Hi all,
Trying to learn zig for a while now, which is mostly a pleasant experience.
However the build system is something i find hard to coerce to do what i want.
Which is becoming more of an issue with cimport moving to translate-c.

I am trying to build a zig program that is using a very simple C library and includes the <immintrin.h> header.

Here i’ve made a modified version of the translate-c example for using a static library and changed the add.h function to include the <immintrin.h> header and some function using it:

add.h:
#ifndef FOO_ADD_H
#define FOO_ADD_H

#include <immintrin.h>

// Add `x` to `y`, and return the result.
int foo_add(int x, int y);

__m256i foo_add4(__m256i x, __m256i y);

#endif

Building this results in the error: ‘immintrin.h’ not found

❯ zig build 
test 
└─ run exe main 
   └─ compile exe main Debug native 
      └─ translate-c generated failure 
.zig-cache/o/a51102692b8c87bef79a4bbf75c8b622/foo/add.h:4:10: fatal error: 'immintrin.h' not found 
#include <immintrin.h> 
         ^ 
error: FatalError 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Diagnostics.zig:495:39: 0x15cfd6d in addWithLocation (aro.zig) 
    if (copy.kind == .@"fatal error") return error.FatalError; 
                                      ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:1088:5: 0x192ee73 in fatalNotFound (aro.zig) 
    try pp.diagnostics.addWithLocation(pp.comp, .{ 
    ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:3736:9: 0x19332c5 in findIncludeSource (aro.zig) 
        return pp.fatalNotFound(filename_tok, filename); 
        ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:3536:21: 0x1933783 in include (aro.zig) 
        else => |e| return e, 
                    ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:835:25: 0x18ba4ae in preprocessExtra (aro.zig) 
                        try pp.include(&tokenizer, .first); 
                        ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:3566:21: 0x1934205 in include (aro.zig) 
        else => |e| return e, 
                    ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:835:25: 0x18ba4ae in preprocessExtra (aro.zig) 
                        try pp.include(&tokenizer, .first); 
                        ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:508:21: 0x18b44ff in preprocess (aro.zig) 
        else => |e| return e, 
                    ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:498:17: 0x18b0629 in preprocessSources (aro.zig) 
    const eof = try pp.preprocess(sources.main); 
                ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/src/main.zig:423:5: 0x1311460 in translate (main.zig) 
    try pp.preprocessSources(.{ 
    ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/src/main.zig:45:21: 0x1316a70 in main (main.zig) 
        else => |e| return e, 
                    ^ 
error: process exited with code 1 
failed command: ./.zig-cache/o/7f001d8970c784d694afa07e6700a2d1/translate-c -o=./.zig-cache/tmp/9266cd6a0cf9d133/generated.zig -lc --zig-lib=/home/otto/Data/Documents/Programming/git/zig/build/stage3/lib/zig -fmodule-libs -- ./.zig-cache/o/1f7d9a798faf1f4c989ab9
1fcab40298/c.h -MD -MV -MF ./.zig-cache/tmp/9266cd6a0cf9d133/deps.d -w -resource-dir /home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D -I ./.zig-cache/o/a51102692b8
c87bef79a4bbf75c8b622

Note that this error is due to translate-c of the header: If the <immintrin.h> header is only included in the add.c file and the function is changed to not take/return __m256 vars the build succeeds. So clang is finding the header just fine.

Also running zig translate-c on the commandline gives me:

❯ zig translate-c  -lc add.c   > add.zig error: translation failure /home/otto/Data/Documents/Programming/git/zig/build/stage3/lib/zig/include/avx512fintrin.h:4657:19: error: use of unknown builtin ‘__builtin_elementwise_fshr’   return (__m512i)__builtin_elementwise_fshr((__v16su)__A,(__v16su)__A, (__v16su)__B);                   ^ /home/otto/Data/Documents/Programming/git/zig/build/stage3/lib/zig/include/avx512fintrin.h:4657:19: error: invalid conversion between vector type ‘__m512i’ (vector of 8 ‘long long’ values) and integer type ‘int’ of different size   return (__m512i)__builtin_elementwise_fshr((__v16su)__A,(__v16su)__A, (__v16su)__B);                   ^ /home/otto/Data/Documents/Programming/git/zig/build/stage3/lib/zig/include/avx512fintrin.h:4657:19: note: previous definition is here   return (__m512i)__builtin_elementwise_fshr((__v16su)__A,(__v16su)__A, (__v16su)__B);                   ^ /home/otto/Data/Documents/Programming/git/zig/build/stage3/lib/zig/include/avx512fintrin.h:4679:19: error: invalid conversion between vector type ‘__m512i’ (vector of 8 ‘long long’ values) and integer type ‘int’ of different size   return (__m512i)__builtin_elementwise_fshr((__v8du)__A, (__v8du)__A, (__v8du)__B);                   ^ /home/otto/Data/Documents/Programming/git/zig/build/stage3/lib/zig/include/avx512fintrin.h:4769:19: error: use of unknown builtin ‘__builtin_elementwise_fshl’   return (__m512i)__builtin_elementwise_fshl((__v16su)__A, (__v16su)__A, (__v16su)__B);                   ^ /home/otto/Data/Documents/Programming/git/zig/build/stage3/lib/zig/include/avx512fintrin.h:4769:19: error: invalid conversion between vector type ‘__m512i’ (vector of 8 ‘long long’ values) and integer type ‘int’ of different size   return (__m512i)__builtin_elementwise_fshl((__v16su)__A, (__v16su)__A, (__v16su)__B);                   ^ /home/otto/Data/Documents/Programming/git/zig/build/stage3/lib/zig/include/avx512fintrin.h:4769:19: note: previous definition is here   return (__m512i)__builtin_elementwise_fshl((__v16su)__A, (__v16su)__A, (__v16su)__B);                   ^ (and more)
        else => |e| return e, 
                    ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:835:25: 0x18ba4ae in preprocessExtra (aro.zig) 
                        try pp.include(&tokenizer, .first); 
                        ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:3566:21: 0x1934205 in include (aro.zig) 
        else => |e| return e, 
                    ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:835:25: 0x18ba4ae in preprocessExtra (aro.zig) 
                        try pp.include(&tokenizer, .first); 
                        ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:508:21: 0x18b44ff in preprocess (aro.zig) 
        else => |e| return e, 
                    ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D/src/aro/Preprocessor.zig:498:17: 0x18b0629 in preprocessSources (aro.zig) 
    const eof = try pp.preprocess(sources.main); 
                ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/src/main.zig:423:5: 0x1311460 in translate (main.zig) 
    try pp.preprocessSources(.{ 
    ^ 
/home/otto/Data/Documents/Programming/git/trans2/translate-c/src/main.zig:45:21: 0x1316a70 in main (main.zig) 
        else => |e| return e, 
                    ^ 
error: process exited with code 1 
failed command: ./.zig-cache/o/7f001d8970c784d694afa07e6700a2d1/translate-c -o=./.zig-cache/tmp/9266cd6a0cf9d133/generated.zig -lc --zig-lib=/home/otto/Data/Documents/Programming/git/zig/build/stage3/lib/zig -fmodule-libs -- ./.zig-cache/o/1f7d9a798faf1f4c989ab9
1fcab40298/c.h -MD -MV -MF ./.zig-cache/tmp/9266cd6a0cf9d133/deps.d -w -resource-dir /home/otto/Data/Documents/Programming/git/trans2/translate-c/examples/use_static_lib/zig-pkg/aro-0.0.0-JSD1QqO_OABFwQ7sIbrkG_Es077a3egrqA28ontD2e_D -I ./.zig-cache/o/a51102692b8
c87bef79a4bbf75c8b622

Which does find the header, but has some problem with avx512 headers. Not sure what exactly the error is, but its not really a suprise since my system only has avx2.

Adding -mcpu=native still gives the errors on avx512 headers.

Probably i just need to add some includepath in the build script to point it to the location where it can find the header. However i have no idea how to do that. Besides it seems stange to have to do that as the build of the c-lib by clang succeeds without it just as the commandline translate.

The following is not picked up by the ‘Translator’:

// Prepare the `translate-c` dependency.
const translate_c = b.dependency("translate_c", .{});

// Build the C library. In reality this would probably be done via the package manager.
const libfoo = buildLibfoo(b, target, optimize);

// Create a `Translator` for C source code which `#include`s the needed headers.
// If necessary, it could also include different headers, define macros, etc.
const trans_libfoo: Translator = .init(translate_c, .{
    .c_source_file = b.addWriteFiles().add("c.h",
        \\#include <foo/add.h>
        \\#include <foo/print.h>
    ),
    .target = target,
    .optimize = optimize,
});
trans_libfoo.mod.addIncludePath(.{ .cwd_relative = "/usr/local/lib/clang/22/include" });

Any suggestions how to get this to work?

I may be wrong but I am pretty sure that the c_source_file option should point to the actual c file with the implementation rather than the c.h header.

I’m not sure but I also don’t think you need the full translate-c package for this and could use just the built-in addTranslateC methods. I had a question about it a few days ago, it might help you: Error in Zig file Generated from TranslateC

Sorry I couldn’t be more helpful.

This looks like an arocc missing feature. Zig 0.16.0 switched to using arocc for translating c files. My guess is that this builtin is not handled by arocc. Arocc has been focused on gcc compatibility, as far as I can tell, and is missing a lot of Clang stuff. It would be worth filing a report with a minimal repo (like your add.h file).

@Southporter Thanks. Created an issue at:

@Playful Tried that but gives the same error. Also i’m certain i’ve seen posts claiming exact the opposite: that translate-c is only for translating header files.

2 Likes

This is correct. You would add c files to the executable or module that consumes the translate-c output, but the translation should only be on header files.

1 Like

Although this is the ‘advice’ is see in most translate-c posts, translate-c itself does not say this in their readme, and they do actually translate implementation files (main.c) directly to zig in their example:

https://codeberg.org/ziglang/translate-c/src/branch/main/examples/compile_c/build.zig

To a compiler/translator’s core functionality, there is no distinction between a header and source file, it’s just C. If it were complete and bug-free, it would be fine on any source and in fact can for some. In practice, there are some things it can’t translate yet, and it’s better to stick to just headers. You might get better code generation, and certainly better debugging information using a C compiler for the implementation.

1 Like

Just to not leave this topic dangling:

The error was in translate-c (not in aro) and was fixed in commit. (dated Jun 3, 2026, 10:16 AM GMT+2).

5 Likes