Compiling openCV with Zig CC/C++

Hi all!
( I am very excited to use Zig to make fast image processing libraries and apps, but I’m not sure how to use Zig to import popular libraries like openCV or DarkNet. I have tons of questions about that, but I’ll try to ask small and specific questions. I have experience working with Python, but compiling these things is a real challenge for me, that’s why I created an account just today. )

So I have a dev Docker image with different compilers and dev libraries, on Ubuntu.
I cloned openCV and ran cmake + make using gcc and clang, no problems, hovever I can’t get it to compile in Zig.
Maybe I’m doing something very stupid.

export CC="zig cc" CXX="zig c++"

cmake -DBUILD_opencv_java_bindings_generator=OFF -DBUILD_opencv_js_bindings_generator=OFF -DBUILD_opencv_python_bindings_generator=OFF -DBUILD_opencv_video=OFF -DBUILD_opencv_videoio=OFF -DCMAKE_BUILD_TYPE=Release ..

ERROR
[ 20%] Linking CXX shared library ../../lib/libopencv_core.so
error: unsupported linker arg: --exclude-libs
make[2]: *** [modules/core/CMakeFiles/opencv_core.dir/build.make:1824: lib/libopencv_core.so.4.9.0] Error 1
make[1]: *** [CMakeFiles/Makefile2:1425: modules/core/CMakeFiles/opencv_core.dir/all] Error 2
make: *** [Makefile:166: all] Error 2

Is there a better way to tell cmake how to use Zig?
( I actually tried to compile DarkNet with Zig in the same way, by defining the CC and CXX variables and I made it work all the way until the last step. )

Thank you for your time!

It seems that there is a related open issue.

1 Like

Thank you for your response!

It looks like this PR is responsible for this: [all linkers] fail hard on unsupported flags by motiejus · Pull Request #11906 · ziglang/zig · GitHub
And other ppl are also complaining about this: Filter unsupported linker args · Issue #96 · rust-cross/cargo-zigbuild · GitHub

I always thought that Zig is a drop-in replacement for Clang.

Suppose I want to make this work and compile openCV…
is there another flag that I can use to exclude those libraries ? or a flag to ignore the excluding of libraries ?

OK I found another PR related to this: [elf] add --exclude-libs by motiejus · Pull Request #11916 · ziglang/zig · GitHub

It was rejected, but I don’t understand why…
To me, it makes sense to be able to use Zig in the same way you would use clang, in a build process like cmake.

I suppose the idea is to rewrite all your build process in build.zig ? In the case of openCV, it looks like a massive task, so maybe there’s a better way ?

Sorry that you’re hitting a wall there - that’s a bummer. If I was in your position, I’d probably just build the cmake file and link it as whatever type of library it produces in Zig build. You can also add a step in build to run that cmake file directly. Here’s an example of adding a step to run a command on zig build:

pub fn compileSingleFile(
    allocator: std.mem.Allocator,
    source_path: []const u8,
    target_path: []const u8,
) void {
    std.log.info("Creating device utilities...\n", .{});
    
    const libgen_utils_argv: []const []const u8 = &.{  
        "nvcc",
        "--shared",
        "-o", 
        target_path, 
        source_path,
        "-O3",
        config.gpu_architecture,
        "--compiler-options",
        "-fPIC", 
        "-I/usr/local/cuda/include",
        "-L/usr/local/cuda/lib",
        "-lcudart",
        "-lcuda"
    };

    const result = std.ChildProcess.run(.{
        .allocator = allocator, .argv = libgen_utils_argv
    }) catch |e| {
        std.log.err("Error: {}", .{e});
        @panic("Failed to create libdev_utils.so");
    };

    if (result.stderr.len != 0) {
        std.log.err("Error: {s}", .{result.stderr});
        @panic("Failed to create libdev_utils.so");
    }
}}

You can change that out for your cmake commands so it would be like running cmake directly from the console. If memory serves, CMake caches stuff so I don’t know what the effect of running the same command multiple times has so I’d test that out. I have code written to detect if a file exists (such as a library file) if need be. Again, not a perfect solution, but it does work.

When you say import into Zig, I take it that you’re building a Zig front end for this stuff? I’m just trying to be clear about what you mean when you say import. If so, you’ll need to add a build step to link against the libraries.

2 Likes

Thank you for your answer @AndrewCodeDev !
I see what you mean.

I want to import C/C++ code in Zig so that I can (ideally) cross-compile a self contained CLI app. Basically I don’t want to ask users to install openCV so they can run my app.

I don’t have enough experience with compiling C languages and linking them. From what I understand from your answer, I could compile obj files with a different compiler then link them with Zig? Basically I could define some external functions in Zig and they would be found in the linking step? Not sure if that’s possible.

I wrote a bit more documentation on using C++ implementation files here: C/C++ Include Compatibility with @cImport

I’ll cover linking at some point in the future.

3 Likes

Super useful document! Thanks for sharing!

1 Like