Kerzan Sobre mí

¿Cómo usar Raylib con Zig?

En este tutorial, te guiaré paso a paso para instalar y configurar Raylib sin utilizar librerías de bindings, permitiéndote tener un mayor control sobre tu entorno de desarrollo.

Ya hay algunas librerías que hacen esto muy sencillo como raylib-zig pero acá nos vamos a enfocar en aprender cómo hacer este proceso tu mismo(a) y con una configuración en tu build.zig un poco mas simplificada.

Creando el proyecto

Primero que nada vamos a crear nuestro proyecto.

# inicializando el proyecto
mkdir raylib-zig
cd raylib-zig
zig init

# el output de ls deberia quedar asi:
 ls -la
total 20
drwxr-xr-x  3 usuario users 4096 Nov 19 20:03 .
drwxr-xr-x 22 usuario users 4096 Nov 19 19:01 ..
-rw-r--r--  1 usuario users 3829 Nov 19 20:03 build.zig
-rw-r--r--  1 usuario users 3369 Nov 19 20:03 build.zig.zon
drwxr-xr-x  2 usuario users 4096 Nov 19 20:03 src

Ahora vamos a quitar los tests de nuestro build.zig ya que no son necesarios. Eliminaremos las siguiendes lineas.

    //más código arriba...
    
    // This creates a build step. It will be visible in the `zig build --help` menu,
    // and can be selected like this: `zig build run`
    // This will evaluate the `run` step rather than the default, which is "install".
    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);

    //ELIMINA ESTO --------------------------------------------------------------------------->

    // Creates a step for unit testing. This only builds the test executable
    // but does not run it.
    const lib_unit_tests = b.addTest(.{
        .root_source_file = b.path("src/root.zig"),
        .target = target,
        .optimize = optimize,
    });

    const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);

    const exe_unit_tests = b.addTest(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);

    // Similar to creating the run step earlier, this exposes a `test` step to
    // the `zig build --help` menu, providing a way for the user to request
    // running the unit tests.
    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&run_lib_unit_tests.step);
    test_step.dependOn(&run_exe_unit_tests.step);

    //<--------------------------------------------------------------------------- ELIMINA ESTO
}

Con la estructura de nuestro proyecto lista ahora pasamos a ver cómo usar Raylib.

Instalando Raylib

Ahora nos vamos al repositorio de Raylib y vamos a la página de releases para copiar el link de descarga del código fuente en formato tar.gz. Una vez copiado vamos a ejecutar el siguiente comando:

# puedes intercambiar el link con el que hayas copiado tu
zig fetch --save https://github.com/raysan5/raylib/archive/refs/tags/5.5.tar.gz

Asegurate de que tu build.zig.zon tenga algunas lineas parecidas a esta debajo de la propiedad .dependencies:

.raylib = .{
    .url = "https://github.com/raysan5/raylib/archive/refs/tags/5.5.tar.gz",
},

Probablemente verás un error parecido a este:

tu-proyecto/build.zig.zon:29:20: error: dependency is missing hash field
            .url = "https://github.com/raysan5/raylib/archive/refs/tags/5.5.tar.gz",
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: expected .hash = "1220d93782859726c2c46a05450615b7edfc82b7319daac50cbc7c3345d660b022d7",

En ese caso solo tendrías que copiar ese hash y pegarlo debajo de la propiedad .url, se vería de esta manera:

.raylib = .{
    .url = "https://github.com/raysan5/raylib/archive/refs/tags/5.5.tar.gz",
    .hash = "1220d93782859726c2c46a05450615b7edfc82b7319daac50cbc7c3345d660b022d7",
},

Luego de eso simplemente ejecutamos otra vez zig build --fetch para asegurarnos de que nada haya ningún error o problema y si no hay error, pasamos modificar nuestro build.zig.

Configurando el build.zig

Ahora pasamos a modificar nuestro build.zig para que compile Raylib y podamos usar sus header files. Pero primero que nada hay que agregar Raylib como dependencia, así que agregamos las siguientes líneas:

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

    const lib = b.addStaticLibrary(.{
        .name = "raylib-zig",
        .root_source_file = b.path("src/root.zig"),
        .target = target,
        .optimize = optimize,
    });

	//Debajo de la declaracion de la constante "lib"
	//Creamos la dependencia de Raylib
    const raylib = b.dependency("raylib", .{ .target = target, .optimize = optimize });
    lib.addIncludePath(raylib.path("src"));


    //más código abajo...

Ya con eso estamos habilitando los header files de raylib, que luego vamos a poder importar desde nuestro main.zig. El próximo paso es enlazar nuestra dependencia al ejecutable del proyecto:

    //más código arriba...

    const exe = b.addExecutable(.{
        .name = "raylib-zig",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

	//Intalamos los headers de Raylib and nuestro ejecutable
    exe.installLibraryHeaders(raylib.artifact("raylib"));

	//Y enlazamos Raylib al ejecutable
    exe.linkLibrary(raylib.artifact("raylib"));

    //más código abajo...

Y como paso final necesitamos enlazar librerias del sistema para que las funcionalidades de Raylib, pues… funcionen:

    //más código arriba...

	//Asegurate de que cada paquete este instalado en tu equipo sistema operativo (linux)
    exe.linkSystemLibrary("GL");
    exe.linkSystemLibrary("rt");
    exe.linkSystemLibrary("dl");
    exe.linkSystemLibrary("m");
    exe.linkSystemLibrary("X11");

    b.installArtifact(exe);
    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());

    if (b.args) |args| {
        run_cmd.addArgs(args);
    }
    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}

Ahora sí, ya tenemos todo listo para testear Raylib en nuestro proyecto y ver si funciona o no.

Testeando Raylib

¡Ya casi terminamos! Vamos a modificar nuestro main.zig para importar Raylib y renderizar una ventana sencilla. Asegurúte de que tu mai.zig se vea de la siguiente manera:

//main.zig
const std = @import("std");
const ray = @cImport({
    @cInclude("raylib.h");
});

pub fn main() !void {
    std.debug.print("main function working", .{});

    const screenWidth = 800;
    const screenHeight = 450;

    ray.InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");

    ray.SetTargetFPS(60);
    while (!ray.WindowShouldClose()){

        ray.BeginDrawing();
        ray.ClearBackground(ray.RAYWHITE);
        ray.DrawText("Congrats! You created your first window!", 190, 200, 20, ray.LIGHTGRAY);
        ray.EndDrawing();

    }

    ray.CloseWindow();
}

Ok ya es hora de compilar y ejecutar nuestro proyecto con el comando zig build run, y si todo va bien, deberiamos ver una ventana parecida a la siguiente:

Alt text

¡Y listo! Ya con esto estás listo(a) para continuar usando Raylib con Zig.