Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Global Artifact Caching Breaks Multi-Target Builds #170

Open
ArielBenichou opened this issue Nov 4, 2024 · 3 comments
Open

Global Artifact Caching Breaks Multi-Target Builds #170

ArielBenichou opened this issue Nov 4, 2024 · 3 comments

Comments

@ArielBenichou
Copy link

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:

var _raylib_lib_cache: ?*std.Build.Step.Compile = null;

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! 😊

Not-Nik added a commit that referenced this issue Nov 8, 2024
@Not-Nik
Copy link
Owner

Not-Nik commented Nov 8, 2024

Should be fixed

@Not-Nik Not-Nik closed this as completed Nov 8, 2024
Not-Nik added a commit that referenced this issue Nov 8, 2024
@Not-Nik
Copy link
Owner

Not-Nik commented Nov 8, 2024

The fix I tried broke the build. Maybe we would need to give each artifact a unique name?

@Not-Nik Not-Nik reopened this Nov 8, 2024
@ArielBenichou
Copy link
Author

Well, i don't really know. Can raylib-zig be built without caching the artifact?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants