raylib-zig icon indicating copy to clipboard operation
raylib-zig copied to clipboard

Global Artifact Caching Breaks Multi-Target Builds

Open defaultgnome opened this issue 1 year ago • 3 comments

Hey o, 👋 I'm pretty new to both Zig and raylib-zig, and I think I stumbled upon a bug while trying to build my project for different platforms. I've discussed this in the Zig Discord server, and they suggested I should report it.

What's Happening

I'm trying to build a simple project for multiple targets (like macOS and Windows), but it seems there's an issue with how artifacts are being cached. From what I understand after discussing it in Discord, the problem is that raylib-zig is using global variables to cache build artifacts, which doesn't play well with Zig's build system when trying to build for multiple targets.

How to Reproduce

I created a minimal test project to demonstrate the issue. Here's how you can try it yourself:

  1. First, create a new project with this structure:
my-project/
├── build.zig
└── build.zig.zon
└── src/
    └── main.zig
  1. Here's my build.zig.zon:
.{
    .name = "raylib-test",
    .version = "0.1.0",
    .dependencies = .{
        .raylib = .{
            .url = "https://github.com/Not-Nik/raylib-zig/archive/19db777449c0f56ca621121a00087d341eb77080.tar.gz",
            .hash = "1220608d53a1e0e295f8367be3aa7b1439d044af1551ae64cf5ae6ce9edb05858e73",
        },
    },
    .paths = .{
        "build.zig",
        "build.zig.zon",
        "src",
    },
}
  1. My build.zig:
const std = @import("std");

const Target = struct {
    query: std.Target.Query,
    name: []const u8,
};

const targets = [_]Target{
    .{ .query = .{ .cpu_arch = .aarch64, .os_tag = .macos }, .name = "aarch64-macos" },
    .{ .query = .{ .cpu_arch = .x86_64, .os_tag = .windows }, .name = "x86_64-windows" },
};

pub fn build(b: *std.Build) !void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // =================
    // ==== INSTALL ====
    // =================
    const exe = try createExecutable(b, target, optimize);
    b.installArtifact(exe);

    // =================
    // ==== RELEASE ====
    // =================
    const release_step = b.step("release", "Create release builds for all targets");

    for (targets) |t| {
        const target_query = b.resolveTargetQuery(t.query);
        const release_exe = try createExecutable(b, target_query, .ReleaseFast);

        const release_dir_name = try std.fmt.allocPrint(
            b.allocator,
            "{s}.{s}",
            .{ "raylib-test", t.name },
        );

        // Create release directory
        const release_path = try std.fs.path.join(b.allocator, &.{ "releases", release_dir_name });
        const install_step = b.addInstallArtifact(release_exe, .{
            .dest_dir = .{ .override = .{ .custom = release_path } },
        });
        release_step.dependOn(&install_step.step);
    }
}

fn createExecutable(
    b: *std.Build,
    target: std.Build.ResolvedTarget,
    optimize: std.builtin.OptimizeMode,
) !*std.Build.Step.Compile {
    const exe = b.addExecutable(.{
        .name = "raylib-test",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    exe.linkLibCpp();

    // Raylib & Raygui
    const raylib_dep = b.dependency("raylib", .{
        .target = target,
        .optimize = optimize,
    });
    const raylib = raylib_dep.module("raylib");
    const raygui = raylib_dep.module("raygui");
    const raylib_artifact = raylib_dep.artifact("raylib");
    exe.linkLibrary(raylib_artifact);
    exe.root_module.addImport("raylib", raylib);
    exe.root_module.addImport("raygui", raygui);

    return exe;
}
  1. And a simple src/main.zig:
const rl = @import("raylib");

pub fn main() !void {
    rl.initWindow(800, 450, "Test");
    defer rl.closeWindow();

    rl.setTargetFPS(60);

    while (!rl.windowShouldClose()) {
        rl.beginDrawing();
        defer rl.endDrawing();

        rl.clearBackground(rl.Color.white);
    }
}

The Error

When I run zig build, I get this error:

thread 31355508 panic: unable to find artifact 'raylib'

From what I learned in the Discord discussion, this happens because the caching system is reusing the first cached artifact instead of creating new ones for different targets.

What Should Happen

The build system should create separate artifacts for each target, allowing us to successfully build for multiple platforms.

Additional Context

The issue seems to be related to the global caching in build.zig here: https://github.com/Not-Nik/raylib-zig/blob/c191e12e7c50e5dc2b1addd1e5dbd16bd405d2b5/build.zig#L100

I'm still learning Zig and raylib, so please let me know if you need any additional information or if I should test something else! 😊

defaultgnome avatar Nov 04 '24 00:11 defaultgnome