¿Qué es un zig build system plugin?

¿Qué es un zig build system plugin?





Plugins del sistema de build en Zig

Plugins del sistema de build en Zig

Zig ofrece un sistema de construcción (build system) muy flexible que permite a los desarrolladores automatizar la compilación, la generación de binarios y la gestión de dependencias. Un plugin en este contexto es un módulo de Zig que se integra dentro del proceso de construcción para añadir funcionalidades personalizadas, como la generación de código, la configuración de opciones de compilación o la creación de artefactos específicos.

¿Qué es el sistema de build de Zig?

En Zig, el archivo build.zig actúa como script de configuración. Este archivo utiliza el paquete std.build para definir objetivos (targets), enlaces (linkers) y tareas (steps). El flujo típico sigue estos pasos:

  • Definir un Build con std.build.Builder.
  • Crear un Exe o Lib con builder.addExecutable o builder.addLibrary.
  • Agregar archivos fuente con exe.addSourceFile o lib.addSourceFile.
  • Especificar opciones de compilación y de enlazado.
  • Invocar builder.build() para generar el binario.

Plugins: ¿Qué aportan?

Un plugin permite:

  • Extender el comportamiento del build system sin modificar el núcleo.
  • Reutilizar código de construcción en múltiples proyectos.
  • Encapsular tareas complejas (por ejemplo, generación de código de protobuffers).
  • Proveer una interfaz de configuración clara y reutilizable.

Estructura básica de un plugin

Un plugin típico es un paquete Zig que exporta una función llamada build. Esta función recibe una referencia al builder y devuelve un *std.build.Step que representa la tarea añadida.

Ejemplo 1: Plugin que imprime la versión de Zig

// plugin_zig_version.zig
const std = @import("std");

/// Exporta la función de inicialización del plugin.
/// El parámetro build es el builder del proyecto que lo llama.
pub export fn build(build: *std.build.Builder) !void {
    // Creamos un Step personalizado que solo ejecuta un comando.
    const step = build.step("print_zig_version", "Imprime la versión de Zig");

    // El comando que se ejecutará.
    step.dependOn(&build.exec("zig", "build", "version"));
}

Detalle línea por línea:

  • const std = @import("std"); importa el paquete estándar.
  • La firma pub export fn build(build: *std.build.Builder) es obligatoria; el build system lo invocará automáticamente.
  • build.step crea un nuevo paso de construcción con nombre y descripción.
  • step.dependOn añade una dependencia a un paso existente; aquí usamos build.exec para ejecutar un comando externo.

Ejemplo 2: Plugin que genera un archivo fuente a partir de un esquema

// plugin_generate_source.zig
const std = @import("std");

pub export fn build(build: *std.build.Builder) !void {
    // Ruta donde se guardará el archivo generado
    const outPath = build.path("src/generated.zig");

    // Paso de generación: ejecutamos un script de Python
    const generateStep = build.step("generate_schema", "Genera código Zig a partir de esquema");
    generateStep.dependOn(&build.exec("python", "generate_schema.py", "--out", outPath));

    // Añadimos el archivo generado al objetivo
    const exe = build.addExecutable("my_app", "src/main.zig");
    exe.addSourceFile(outPath);

    // Dependencia: la generación debe completarse antes de compilar
    exe.root_module.root_source_file = &outPath;
    exe.step.dependOn(&generateStep);
}

Detalle línea por línea:

  • Se crea un outPath con build.path que será usado por el paso de generación.
  • El paso generateStep ejecuta un script externo (python generate_schema.py) que escribe el archivo generated.zig.
  • El ejecutable my_app incluye el archivo generado mediante addSourceFile.
  • Se establece una dependencia explícita: exe.step.dependOn(&generateStep), garantizando que la generación ocurra antes de la compilación.

Cómo usar un plugin en un proyecto

Para emplear un plugin, el proyecto debe declarar el paquete y llamar a su función build desde su propio build.zig.

Estructura de carpetas recomendada

project/
├─ build.zig
├─ src/
│  ├─ main.zig
│  └─ generated.zig (generado por plugin)
└─ plugins/
   ├─ plugin_zig_version/
   │  └─ plugin_zig_version.zig
   └─ plugin_generate_source/
      └─ plugin_generate_source.zig

Archivo build.zig del proyecto

// build.zig
const std = @import("std");

// Importamos los plugins (suponiendo que están en plugins/)
const ZigVersionPlugin = @import("plugins/plugin_zig_version/plugin_zig_version.zig");
const GenerateSourcePlugin = @import("plugins/plugin_generate_source/plugin_generate_source.zig");

pub fn build(b: *std.build.Builder) void {
    // Llamamos a cada plugin
    ZigVersionPlugin.build(b);
    GenerateSourcePlugin.build(b);

    // Configuraciones adicionales del proyecto...
}

El flujo de ejecución:

  1. El build system llama a build del proyecto.
  2. Dentro de esta función se invocan las funciones build de los plugins.
  3. Los plugins crean sus propios pasos y añaden depend

Comments

No comments yet. Why don’t you start the discussion?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *