Package build.zig.zon

Mendeklarasikan dependensi pada build.zig.zon dengan fingerprint dan memakainya melalui build.zig.

Daftar isi

Proyek Zig mendeklarasikan identitas dan dependensinya pada satu berkas manifest bernama build.zig.zon. Berkas ini ditulis dengan sintaks Zig biasa, memuat nama paket, versi, fingerprint, daftar dependensi, dan daftar berkas yang menyertai paket. Topik ini membangun dua paket, yaitu satu pustaka kecil dan satu program yang memakainya sebagai dependensi jalur lokal, lalu menjelaskan peran setiap field pada manifestnya.

Konsep#

Field wajib pertama adalah .name, ditulis sebagai .{ .nama_paket }, dan field kedua adalah .version berformat semver. Field .fingerprint adalah bilangan yang mengidentifikasi paket secara global, dihasilkan toolchain saat paket pertama kali dibuat, dan tidak boleh diubah di kemudian hari karena paket lain memakainya untuk mengenali paket yang sama. Field .paths menetapkan berkas dan direktori mana yang menyertai paket, dan hanya berkas-berkas itu yang ikut dalam perhitungan hash saat paket didistribusikan.

Dependensi dinyatakan pada field .dependencies, dengan dua bentuk sumber. Bentuk .path menunjuk direktori lokal dan cocok untuk pengembangan paket sendiri, sedangkan bentuk .url beserta .hash dipakai untuk paket daring yang diambil dan dicocokkan isinya secara otomatis. Kedua bentuk itu saling meniadakan pada satu entri dependensi, karena .path mengambil isi langsung dari disk tanpa menghitung hash, sedangkan .url mengunduh arsip lalu memverifikasinya terhadap .hash yang tertulis. Pada kedua bentuk, kunci dependensi, misalnya waktu, adalah nama yang dipakai build.zig untuk mengambil modulnya.

Manifest juga menyediakan field .lazy pada entri dependensi. Dependensi yang ditandai lazily hanya diambil bila benar-benar dirujuk oleh build.zig, sehingga proyek dengan banyak pilihan fitur tidak membayar biaya pengambilan untuk dependensi yang tidak dipakai. Field .minimum_zig_version melengkapi manifestnya dengan menandai batas bawah versi toolchain, dan informasi itu dibaca pustaka pengelola dependensi sebelum mencoba mengompilasi.

Diagram berikut merangkum alur pencocokan tersebut, dari manifest proyek menuju paket dependensinya hingga cache global.

proyek catatbuild.zig.zonpaket-waktubuild.zig.zon + waktu.zig.pathhash isi paketdicocokkan oleh zig buildcache paket global~/.cache/zig/pdisalin sekali
Alur dependensi dari manifest proyek menuju paket pustaka, pencocokan hash, dan cache paket global

Alur pemakaian dependensi berurutan sebagai berikut.

  1. Pustaka menyatakan identitasnya pada build.zig.zon dan mengekspos modul lewat addModule.
  2. Program menyatakan dependensinya pada field .dependencies manifestnya.
  3. build.zig program mengambil dependensi dengan b.dependency lalu menyambungkan modulnya.
  4. Kode program melakukan @import atas nama modul tersebut.

Contoh Lengkap#

Paket pustaka bernama waktu memuat satu fungsi penggolong durasi. Manifestnya hanya memuat identitas dan daftar berkas.

zig paket-waktu/build.zig.zon
// tidak-dijalankan: manifest bukan program, dibaca oleh zig build
.{
    .name = .waktu,
    .version = "0.1.0",
    .fingerprint = 0x21f44624797ecd28,
    .paths = .{ "build.zig", "build.zig.zon", "waktu.zig" },
}
zig paket-waktu/waktu.zig
// tidak-dijalankan: pustaka dipakai melalui graf build paket pemakainya
pub fn durasi(menit: u32) []const u8 {
    if (menit < 60) return "singkat";
    if (menit < 480) return "sedang";
    return "panjang";
}

Pustaka mengekspos modulnya pada build.zig dengan b.addModule("waktu", .{ .root_source_file = b.path("waktu.zig") }).

zig paket-waktu/build.zig
// tidak-dijalankan: berkas build pustaka dieksekusi melalui graf build pemakainya
const std = @import("std");

pub fn build(b: *std.Build) void {
    _ = b.addModule("waktu", .{
        .root_source_file = b.path("waktu.zig"),
    });
}

Program pemakainya bernama catat, dan manifestnya menyatakan dependensi jalur lokal. Pada contoh ini paket pustaka ditempatkan pada subdirektori paket-waktu di dalam proyek, sehingga nilai .path menunjuk direktori itu dan seluruh contoh berdiri dalam satu direktori proyek.

zig build.zig.zon
// tidak-dijalankan: manifest bukan program, dibaca oleh zig build
.{
    .name = .catat,
    .version = "0.1.0",
    .fingerprint = 0xe35c45a939766c3e,
    .dependencies = .{
        .waktu = .{ .path = "paket-waktu" },
    },
    .paths = .{ "build.zig", "build.zig.zon", "utama.zig", "paket-waktu" },
}

build.zig program mengambil dependensi dan menyambungkannya sebagai import pada modul akar program.

zig build.zig
// tidak-dijalankan: berkas build dieksekusi lewat perintah zig build
const std = @import("std");

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

    const dep_waktu = b.dependency("waktu", .{});
    const mod_waktu = dep_waktu.module("waktu");

    const exe = b.addExecutable(.{
        .name = "catat",
        .root_module = b.createModule(.{
            .root_source_file = b.path("utama.zig"),
            .target = target,
            .optimize = optimize,
            .imports = &.{
                .{ .name = "waktu", .module = mod_waktu },
            },
        }),
    });
    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());
    const run_step = b.step("run", "Jalankan catat");
    run_step.dependOn(&run_cmd.step);
}

Kode program memakai dependensi melalui @import("waktu"), sesuai nama yang terdaftar pada manifest dan build.zig.

zig utama.zig
// tidak-dijalankan: berkas program dieksekusi lewat perintah zig build run
const std = @import("std");
const waktu = @import("waktu");

pub fn main() void {
    std.debug.print("rapat 45 menit: {s}\n", .{waktu.durasi(45)});
    std.debug.print("workshop 180 menit: {s}\n", .{waktu.durasi(180)});
}
bash
zig build run
text Keluaran
rapat 45 menit: singkat
workshop 180 menit: sedang

Angka 45 berada di bawah enam puluh sehingga digolongkan singkat, sedangkan 180 berada di antara enam puluh dan empat ratus delapan puluh sehingga digolongkan sedang. Fungsi penggolong milik paket lain, dan seluruh penyambungannya dinyatakan pada dua berkas manifest serta satu build.zig. Field .paths pada kedua manifest berperan ketika paket hendak didistribusikan, yaitu menentukan berkas mana yang ikut terhitung pada hash paketnya, dan berkas yang tidak terdaftar di sana tidak ikut berpindah saat paket diambil orang lain. Untuk dependensi .path seperti contoh ini, isi direktori yang dirujuk ikut tunduk pada manifest paket dependensinya, sehingga daftar paths pustaka harus sudah memuat waktu.zig sejak awal.

Perubahan isi paket dependensi langsung terasa pada proyek pemakainya, karena tidak ada versi yang disematkan pada dependensi .path. Pola ini memang disengaja untuk pengembangan bersama, sedangkan dependensi yang stabil memakai bentuk .url beserta .hash sehingga isi yang tertaut tetap sama meskipun sumbernya maju.

Kesalahan umum#

Kesalahan kedua berupa fingerprint yang tidak cocok dengan direktori paket. Pesannya berbunyi error: invalid fingerprint: 0x...; if this is a new or forked package, use this value: 0x..., dan perbaikannya berupa memakai nilai kedua tersebut. Nilai pertama adalah identitas paket lama, sedangkan nilai kedua adalah identitas paket baru pada direktori sekarang, dan memaksakan nilai lama pada fork adalah keputusan yang memengaruhi kepercayaan dependen.

Kesalahan ketiga berupa lupa mendaftarkan dependensi pada build.zig. Manifest yang menyatakan waktu belum cukup, karena @import("waktu") hanya dikenali bila build.zig menyambungkan modulnya melalui b.dependency dan field .imports. Gejalanya berupa pesan error: root module of a Compile step must be created with a known 'target' field ketika modul akar dibuat tanpa target, atau import yang tidak ditemukan saat kompilasi.

Ringkasan#

  • build.zig.zon memuat nama, versi, fingerprint, dependensi, dan daftar berkas paket.
  • Dependensi berbentuk .path untuk direktori lokal dan .url beserta .hash untuk paket daring.
  • Penyambungan modul berlangsung di build.zig melalui b.dependency dan field .imports pada modul akar.
  • Fingerprint dihasilkan sekali oleh toolchain dan divalidasi terhadap nama serta direktori paket.

Referensi#