Building/installiing an executable produced by a dependency

i have a build.zig.zon dependency on a zig-based project whose own build.zig produces an executable program…

[[ this project is actually a fork of zls, though i think my question is generic ]]

my top-level build.zig contains the following:

    const zls_dep = b.dependency("my-zls", .{});
    const zls_exe = b.addExecutable(.{
        .name = "my-zls",
        .root_source_file = zls_dep.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    b.installArtifact(zls_exe);

when i zig build my top-level project, i receive an error from this particular step:

C:\Users\biosb\AppData\Local\zig\p\1220bd3c80953a714035a595b0e0bcebe449dae0af8add7d25aafb46f0f50085c007\src\main.zig:4:29: error: no module named 'exe_options' available within module root
const exe_options = @import("exe_options");

the "exe_options" module is in fact created within the build.zig found in the my-zls project… it is NOT part of my top-level build.zig

said another way, how do i build my-zls using its associated build.zig under the control of my top-level build.zig???

zls depends on a lot of modules. Some of them are declared in its build.zig.zon but some others --like exe_options-- are created in zls build.zig.
See the addExecutable statement from your zls: zls-em/build.zig at 45eb38e2365c3f9fe7cee5a37a0f8d5c8645f888 · em-foundation/zls-em · GitHub

It is better to not copy the declaration but ensure that the install step of zls runs.

1 Like

If you’re forking ZLS maybe consider using GitHub - kristoff-it/zig-lsp-kit: Implement your own LSP server! which is roughly the same thing (a fork of ZLS) but packaged as a dependency that expects you to implement callbacks.

I used it for the Ziggy language server and for the SuperHTML language server.

Unless your goal is not to create your own LSP, but rather repackage ZLS, in which case nevermind :^)

If your goal is to expose the ZLS executable from your package, you can directly get a reference to it from the ZLS dependency.

Something along the lines of b.dependency("zls", .{}).artifact("zls").

If instead you want to wrap it into an executable of your own, then you will need to basically copy the whole definition of the ZLS executable in their build.zig.

If you can share more about your use case we can be more helpful.

3 Likes

i’ve forked ZLS at the point at which it (first) supported zig 0.13.0, and have made some very minor additions to semantic_tokens.zig… i have a corresponding fork of vscode-zig, which adds some distinct highlighting to these new token types…

for now, i’m looking to simply deliver my ZLS executable (plus my VS Code .vsix extension) with my next release of Zig•EM… given that my user is already doing a zig build on their host computer, why not simply produce the ZLS executable at this time as well???

it sounds like what i “really” want to have happen is to execute zig build as a sub-command on my dependent ZLS repo??? presumably i could pass an option to this instantiation of zig build which would direct the compiled executable to be placed (say) in a tools/ folder at the root of my top-level project… [[ worse case, i could simply add a step to explicitly copy the file ]]

this is quite different from my other zig-based dependencies (eg., zig-cli) which will be imported by my own zig-based app (and are effectively compiled as part of it)…

in summary, i CAN orchestrate a zig build of my ZLS as a sub-command… is this my “least worst” but simplest path forward???

In this case you want to go with my suggestion from before: the build.zig script inside of your ZLS dependency already exposes a way of fetching the executable without needing to do anything complicated.

In your build.zig obtain the zls artifact from your dependency and install it:

b.installArtifact(b.dependency("zls", .{}).artifact("zls"));

You might need to tweak this code a bit to make it work, but that’s the gist of it.

If you push the code somewhere I can clone and try everything out I’ll be able to help you more.

2 Likes

that worked !!!

and the "zls" artifact name came from the build.zig.zon file in the dependency, correct???

No, it is the .name of the executable.

    const exe = b.addExecutable(.{
        .name = "zls",
    ...
    b.installArtifact(exe);
1 Like