Injecting dependency into other dependency causes duplication

I am doing the following:

    const inner_sdl_dep = sdl3.builder.dependency("sdl", .{});

    const mojoal = b.dependency("mojoal", .{
        .target = target,
        .optimize = .ReleaseSmall,
    });
    const mojoal_mod = mojoal.module("mojoal");
    mojoal_mod.addSystemIncludePath(inner_sdl_dep.path("include"));
    mojoal_mod.linkLibrary(inner_sdl_dep.artifact("SDL3"));
    exe.root_module.addImport("mojoal", mojoal_mod);

and it works great, but every time I have to recompile, it will compile two separate versions of SDL3 and I do not know how to make it work otherwise without straight up just moving the mojoal dependency into the project itself instead of having it as a proper dependency :frowning:

Could anyone tell me what’s the right way of doing this?

This is sufficient for exe build:

    const mojoal = b.dependency("mojoal", .{
        .target = target,
        .optimize = .ReleaseSmall,
    });
    const mojoal_mod = mojoal.module("mojoal");
    exe.root_module.addImport("mojoal", mojoal_mod);

In mojoal build ensure that you handle the sdl dependency, either by using addIncludePath and linkLibrary or by delegeting the work to an sdl module.


If you need the sdl dependency for both exe and mojoal then expose the sdl api from mojoal module and don’t add a second dependency to sdl.

Not sure I like this solution, because then removing MojoAL (an audio library) would result in the entire codebase collapsing, the semantics are not very good

Is there really no way of just importing the dependency?

If you import the dependency twice you are going to have two versions of the dependency in your code.
The trick is to re-export SDL from your module.
Somewhere in mojoal you call const sdl = @import("sdl"); or something similar.
Add pub in front of it to export the symbol from mojoal. (i.e. pub const sdl = @import("sdl");).
Then in your exe you can have the dependency using: const sdl = @import("mojoal").sdl;

I mean… not quite, MojoAL is actually a C library, I am writing some Zig-esque bindings for it, yes, but it’s really just C

That’s why I am asking, there should be a way to tell Zig’s build system to link the stuff together

link it to your module, linked libraries propagate through module imports

1 Like

How? It didn’t seem to do that with exe.root_module.addImport()

I don’t like any of the proposed solutiona either. This looks like a deficiency in the build system. The system should recognize that a library is being used by multiple modules and reuse it, unless the library is being compiled with different compiler options.

As a workaround, have you tried enabling link-time optimizations? It should detect the redundancy and remove it.

1 Like

The build runner goes through the import tree and links every thing, duplicating links when adding an import would be the less efficient way to implement this behaviour.

It does, the problem is it does this based on the hash, you need to ensure you and all dependencies use the exact same version.

In the future zig will use semver to pick a compatible version out of all the versions used, if that’s not possible it either doesn’t compile or it duplicates them. You will likely get to choose that behaviour.

You are also able to get the dependencies of your dependencies, to side step this problem, but it’s a little sketchy and unclear if the ability to do so is intended or will be removed.

It also is just not necessary to go that far to solve op’s problem, the build system already supports what they need through modules.

1 Like

oh my god, mojoal was just using symbols that this specific version of sdl3 had not implemented yet :sob:

thanks for the help