Build dependencies with global cache dir

I have this QoL build config for building zls from source with a project local Zig compiler:

fn addZls(b: *std.Build) void {
    const run_zls = if (b.systemIntegrationOption("zls", .{ .default = true }))
        // b.addSystemCommand(&.{"zls"})
        return
    else if (b.lazyDependency("zls", .{ .target = b.graph.host, .optimize = .ReleaseFast, .@"version-string" = "0.0.0" })) |dep|
        b.addRunArtifact(dep.artifact("zls"))
    else
        return;

    run_zls.addArg("--config-path");
    run_zls.addFileArg(b.addWriteFiles().add("zls.json", b.fmt(
        \\{{"zig_exe_path": "{s}"}}
    , .{b.graph.zig_exe})));

    if (b.args) |args| run_zls.addArgs(args);

    const step_zls = b.step("tool:zls", "");
    step_zls.dependOn(&run_zls.step);
}

Then, I can tell my editor to use ./zig/zig build -fno-sys=zls tool:zls for running zls, without a global zls installation.

It would be even nicer if I can tell Zig to build this entirely using the global cache dir, so I can avoid rebuilding zls on every project, or on every .zig-cache/ clear.

Does anybody know if there is a way to achieve this? I am on Zig master (0.16.0-dev.3006+94355f192)

I believe you can have zig use a global dir as local cache with little chance of any consequences. That way if a build zls from one project can apply to others, assuming they use matching versions(hashes) of zls.

I think so too, but it is still unclear to me how should I do that. I guess I could pass the flags when invoking zig build (says, zig build --cache-dir $(zig env | grep global_cache_dir) or something…

But I think I found the solution, just now :smiley:

fn addZls(b: *std.Build) void {
    // Use global Zig cache to avoid rebuilding zls
    const local_cache_root = b.cache_root;
    defer b.cache_root = local_cache_root;
    b.cache_root = b.graph.global_cache_root;

    ...

I think Zig build system will use the b.cache_root at configure time (while running b.dependency(...)) so it worked