En el ecosistema de Zig, el proceso de compilar y gestionar dependencias está centralizado en un conjunto de archivos y herramientas que forman lo que denominamos entorno de construcción. Este entorno se compone principalmente de los archivos build.zig y build.zig.zon, junto con el ejecutable zig build, que orquesta la compilación, la vinculación y la ejecución de pruebas.
Arquitectura básica del entorno de construcción de Zig
- build.zig: Script de configuración que define los pasos de construcción.
- build.zig.zon: Archivo de descripción de dependencias y opciones de construcción.
- zig build: Ejecutable que interpreta los archivos anteriores y genera binarios o librerías.
- zig test: Ejecuta pruebas definidas en los módulos.
Configurando un proyecto con build.zig
El archivo build.zig actúa como un pequeño programa Zig que construye tu proyecto. A continuación se muestra un ejemplo completo con explicaciones línea a línea.
// build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
// 1. Definimos la plataforma objetivo: Linux, macOS, Windows, etc.
// La función target() devuelve un Target con la arquitectura y OS deseados.
const target = b.standardTargetOptions(.{});
// 2. Configuramos el modo de construcción: ReleaseFast, Debug, etc.
// standardReleaseOptions() lee la variable de entorno DEPS_MODE o la opción CLI.
const mode = b.standardReleaseOptions();
// 3. Creamos una nueva ejecutable llamado "hello"
// addExecutable() devuelve una referencia al objeto del ejecutable.
const exe = b.addExecutable("hello", "src/main.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
// 4. Añadimos las dependencias externas (si existen).
// Por ejemplo, una librería "mylib" declarada en build.zig.zon.
// Aquí la ignoramos, pero se puede hacer con:
// const mylib = b.dependency("mylib", .{});
// exe.rootModule.addImport("mylib", mylib.module("mylib"));
// 5. Hacemos que el ejecutable sea el objetivo por defecto.
b.installArtifact(exe);
// 6. Definimos un objetivo de prueba (opcional).
const test_step = b.step("test", "Run tests");
const test_exe = b.addTest("src/main.zig");
test_exe.setTarget(target);
test_exe.setBuildMode(mode);
test_step.dependOn(&b.addRunArtifact(test_exe).step);
}
En la sección anterior, cada comentario explica el propósito de la línea de código. El flujo sigue la secuencia habitual: se definen parámetros, se crea el ejecutable y se registra en la fase de instalación.
Estructura de build.zig.zon y manejo de dependencias
El archivo build.zig.zon describe las dependencias externas y opciones de configuración adicionales. A continuación, un ejemplo minimalista:
{<< "build.zig.zon"
version = "0.1.0",
// Dependencia externa (ejemplo: libfoo)
deps = .{
.libfoo = "https://github.com/example/libfoo/archive/refs/tags/v1.2.3.tar.gz",
},
// Otras opciones de compilación (no obligatorias)
options = .{
.optimize = .ReleaseFast,
},
}
Con este archivo, Zig descargará la dependencia libfoo cuando ejecutes zig build. Si la dependencia requiere pasos adicionales (por ejemplo, una librería C), puedes usar addSystemLibrary o addSharedLibrary en tu build.zig.
Compilación, instalación y ejecución
Una vez configurados los archivos anteriores, el flujo de trabajo típico se ve así:
- Compilar:
zig build - Instalar en
zig-out: Se crea el ejecutable enzig-out/bin/hello - Ejecutar:
./zig-out/bin/hello - Probar:
zig build test
Ejemplo práctico: un “Hello World” con pruebas
A continuación se muestra el contenido de los archivos src/main.zig y las pruebas asociadas.
// src/main.zig
const std = @import("std");
// Función principal del ejecutable
pub fn main() !void {
// Imprimimos un saludo en la salida estándar
const stdout = std.io.getStdOut().writer();
try stdout.print("¡Hola, Zig!\n", .{});
}
// Función que será probada
pub fn add(a: i32, b: i32) i32 {
return a + b;
}
// Sección de pruebas: solo se compila cuando se ejecuta "zig build test"
test "suma simple" {
// Usamos assert para verificar el comportamiento de la función add
try std.testing.expect(add(2, 3) == 5);
}
Detalles de cada línea:
const std = @import("std");importa el paquete estándar de Zig.- La función
maindevuelve un!void, lo que significa que puede fallar (por ejemplo, al escribir en la salida). - Obtenemos un escritor de salida estándar con
std.io.getStdOut().writer(). - La llamada a
stdout.printenvía el texto al usuario. - La función
addes una operación básica que sumará dos enteros. - El bloque
testsolo se compila cuando se ejecuta la prueba; aquí verificamos queadd(2,3)devuelva 5 usandostd.testing.expect.
Resumen rápido
- El entorno de construcción de Zig se basa en archivos
build.zigybuild.zig.zon. - El comando
zig buildlee estos archivos, descarga dependencias y construye el proyecto. - Las pruebas se ejecutan con
zig build test, aprovechando la sintaxis de prueba integrada. - El uso de comentarios detallados facilita la comprensión de cada paso, lo que resulta esencial para principiantes.
Con estos conceptos, puedes comenzar a crear tus propios proyectos en Zig y a explorar la potencia del entorno de construcción integrado.
