build: phase 1 — library domains become packages
Each library domain (kernel, device, client, protocol, csv, xkeyboard-config) now owns a build.zig + build.zig.zon that wires and exports its modules, with a standalone `zig build test` per domain. The kernel package also exports abi (source stays in system/abi.zig) so every consumer names one module instance. The root build swaps its createModule calls for b.dependency(...).module(...) — no binary moves; the root is the pilot consumer (docs/build-packages-plan.md). Path dependencies deduplicate by resolved location, so the diamond (root -> device -> kernel, root -> kernel) yields a single instance of each module. Boot-image file list unchanged.
This commit is contained in:
@@ -221,76 +221,41 @@ pub fn build(b: *std.Build) void {
|
|||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
// The library domain packages (docs/build-packages-plan.md, phase 1): each
|
||||||
|
// domain owns a build.zig/zon that wires and exports its modules, and this
|
||||||
|
// root build is a consumer — a library interface change now happens in the
|
||||||
|
// domain's own build file, not here. The per-module commentary lives with
|
||||||
|
// each domain's build.zig.
|
||||||
|
const kernel_library = b.dependency("kernel", .{});
|
||||||
|
const device_library = b.dependency("device", .{});
|
||||||
|
const client_library = b.dependency("client", .{});
|
||||||
|
const protocol_library = b.dependency("protocol", .{});
|
||||||
|
const csv_library = b.dependency("csv", .{});
|
||||||
|
const xkeyboard_config_library = b.dependency("xkeyboard-config", .{});
|
||||||
|
|
||||||
// The three shared contracts, each with its own audience so every import
|
// The three shared contracts, each with its own audience so every import
|
||||||
// declares which one it speaks (no target is set, so each inherits the target of
|
// declares which one it speaks (no target is set, so each inherits the target of
|
||||||
// whichever binary imports it). See docs/coding-standards.md.
|
// whichever binary imports it). See docs/coding-standards.md.
|
||||||
// boot-handoff : loader <-> kernel (BootInformation, framebuffer, VM layout)
|
// boot-handoff : loader <-> kernel (BootInformation, framebuffer, VM layout)
|
||||||
// abi : kernel <-> runtime, core (SystemCall, mmap prot flags, page_size)
|
// abi : kernel <-> runtime, core (SystemCall, mmap prot flags, page_size)
|
||||||
// device-abi : kernel <-> user, devices (DeviceDescriptor, DeviceClass, ...)
|
// device-abi : kernel <-> user, devices (DeviceDescriptor, DeviceClass, ...)
|
||||||
|
// boot-handoff stays a root module (a system/ source the loader <-> kernel
|
||||||
|
// pair speaks); abi is exported by the kernel library package (its source
|
||||||
|
// also lives in system/), device-abi by the device package.
|
||||||
const boot_handoff_module = b.addModule("boot-handoff", .{
|
const boot_handoff_module = b.addModule("boot-handoff", .{
|
||||||
.root_source_file = b.path("system/boot-handoff.zig"),
|
.root_source_file = b.path("system/boot-handoff.zig"),
|
||||||
});
|
});
|
||||||
const abi_module = b.addModule("abi", .{
|
const abi_module = kernel_library.module("abi");
|
||||||
.root_source_file = b.path("system/abi.zig"),
|
const device_abi_module = device_library.module("device-abi");
|
||||||
});
|
const pci_class_module = device_library.module("pci-class");
|
||||||
// The devices sub-project's public interface (the flat wire types), exposed as
|
const csv_module = csv_library.module("csv");
|
||||||
// its own module like vfs-protocol — importable by user space, unlike the
|
const device_registry_module = device_library.module("device-registry");
|
||||||
// kernel-internal device model it also feeds (system/kernel/device-model.zig).
|
const aml_module = device_library.module("aml");
|
||||||
const device_abi_module = b.addModule("device-abi", .{
|
const acpi_ids_module = device_library.module("acpi-ids");
|
||||||
.root_source_file = b.path("library/device/model/device-abi.zig"),
|
const usb_abi_module = device_library.module("usb-abi");
|
||||||
});
|
const usb_ids_module = device_library.module("usb-ids");
|
||||||
// PCI class-code decoding (class/subclass/prog-IF -> names). Pure reference data,
|
const usb_transfer_protocol_module = protocol_library.module("usb-transfer-protocol");
|
||||||
// shared by kernel discovery (the device-tree dump) and any user-space PCI tool.
|
const block_protocol_module = protocol_library.module("block-protocol");
|
||||||
const pci_class_module = b.addModule("pci-class", .{
|
|
||||||
.root_source_file = b.path("library/device/pci/pci-class.zig"),
|
|
||||||
});
|
|
||||||
// Shared CSV helpers (comment stripping, field iteration) for the /etc/*.csv
|
|
||||||
// config files — the device registry and the init service list both parse them.
|
|
||||||
const csv_module = b.addModule("csv", .{
|
|
||||||
.root_source_file = b.path("library/csv/csv.zig"),
|
|
||||||
});
|
|
||||||
// The device registry: parse /etc/devices.csv into match rules and bind a
|
|
||||||
// reported device to a driver — the data-driven, authoritative replacement for
|
|
||||||
// the manager's hand-written switch tables. Pure logic (no hardware, no
|
|
||||||
// syscalls), so it unit-tests on the host; the manager imports it.
|
|
||||||
const device_registry_module = b.addModule("device-registry", .{
|
|
||||||
.root_source_file = b.path("library/device/registry/device-registry.zig"),
|
|
||||||
.imports = &.{.{ .name = "csv", .module = csv_module }},
|
|
||||||
});
|
|
||||||
// ACPI/PnP hardware-ID (_HID) names — the flat analog of pci-class for acpi_device
|
|
||||||
// nodes. Also shared reference data.
|
|
||||||
// The AML interpreter, a build module so the ring-3 acpi service can run the
|
|
||||||
// same parser the kernel does (docs/discovery.md — the shared AML module).
|
|
||||||
// Pure Zig, no kernel imports — one source, two builds.
|
|
||||||
const aml_module = b.addModule("aml", .{
|
|
||||||
.root_source_file = b.path("library/device/acpi/aml/aml.zig"),
|
|
||||||
});
|
|
||||||
|
|
||||||
const acpi_ids_module = b.addModule("acpi-ids", .{
|
|
||||||
.root_source_file = b.path("library/device/acpi/acpi-ids.zig"),
|
|
||||||
});
|
|
||||||
|
|
||||||
// The USB device-framework wire ABI (chapter-9 set-up packets, standard +
|
|
||||||
// class requests, descriptors) and the USB class-code taxonomy — the flat
|
|
||||||
// reference the xHCI bus driver, the USB class drivers, and the device
|
|
||||||
// manager's identity matcher all share. Pure data, like pci-class/acpi-ids.
|
|
||||||
const usb_abi_module = b.addModule("usb-abi", .{
|
|
||||||
.root_source_file = b.path("library/device/usb/usb-abi.zig"),
|
|
||||||
});
|
|
||||||
const usb_ids_module = b.addModule("usb-ids", .{
|
|
||||||
.root_source_file = b.path("library/device/usb/usb-ids.zig"),
|
|
||||||
});
|
|
||||||
// The USB transfer protocol: what a USB class driver says to the xHCI bus
|
|
||||||
// driver to drive its device (open / control / interrupt / bulk). A protocol
|
|
||||||
// module like vfs-protocol, shared by the bus driver and every class driver.
|
|
||||||
const usb_transfer_protocol_module = b.addModule("usb-transfer-protocol", .{
|
|
||||||
.root_source_file = b.path("library/protocol/usb-transfer/usb-transfer-protocol.zig"),
|
|
||||||
});
|
|
||||||
// The block-device protocol: read/write of fixed-size blocks, spoken between a
|
|
||||||
// filesystem and a block driver (usb-storage). A protocol module like the rest.
|
|
||||||
const block_protocol_module = b.addModule("block-protocol", .{
|
|
||||||
.root_source_file = b.path("library/protocol/block/block-protocol.zig"),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Kernel tunables (maximum_cpus, stack sizes, tick rate). A dependency-free module of
|
// Kernel tunables (maximum_cpus, stack sizes, tick rate). A dependency-free module of
|
||||||
// compile-time constants, imported wherever a knob is read; keeps the trade-offs
|
// compile-time constants, imported wherever a knob is read; keeps the trade-offs
|
||||||
@@ -332,208 +297,35 @@ pub fn build(b: *std.Build) void {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// The VFS wire protocol: the vfs sub-project's public interface, exposed as its
|
// The wire protocols, all exported by the protocol package.
|
||||||
// own module. Both the vfs server and the runtime's file layer (unistd/stdio)
|
const vfs_protocol_module = protocol_library.module("vfs-protocol");
|
||||||
// depend on this contract by name — neither reaches into the other's files. This
|
const input_protocol_module = protocol_library.module("input-protocol");
|
||||||
// is the first "protocol module" (see docs/driver-model.md); usb/block will
|
const device_manager_protocol_module = protocol_library.module("device-manager-protocol");
|
||||||
// expose theirs the same way.
|
const display_protocol_module = protocol_library.module("display-protocol");
|
||||||
const vfs_protocol_module = b.addModule("vfs-protocol", .{
|
const scanout_protocol_module = protocol_library.module("scanout-protocol");
|
||||||
.root_source_file = b.path("library/protocol/vfs/vfs-protocol.zig"),
|
const power_protocol_module = protocol_library.module("power-protocol");
|
||||||
});
|
|
||||||
|
|
||||||
// The input wire protocol: the input service's public interface, exposed as its own
|
// The library/kernel concern modules (the userspace private-ABI library),
|
||||||
// module the same way vfs-protocol is. Shared by the input service, the runtime's
|
// the device-domain driver libraries, and the service clients.
|
||||||
// `input` helper (subscribe/publish), and every source and subscriber.
|
const mmio_module = device_library.module("mmio");
|
||||||
const input_protocol_module = b.addModule("input-protocol", .{
|
const system_call_module = kernel_library.module("system-call");
|
||||||
.root_source_file = b.path("library/protocol/input/input-protocol.zig"),
|
const ipc_module = kernel_library.module("ipc");
|
||||||
});
|
const time_module = kernel_library.module("time");
|
||||||
|
const thread_module = kernel_library.module("thread");
|
||||||
// The danos-native user-space runtime: system_call wrappers, the C-convention
|
const logging_module = kernel_library.module("logging");
|
||||||
// heap, IPC helpers, the process start shim, device access. This is the stable
|
const process_module = kernel_library.module("process");
|
||||||
// application ABI; POSIX compatibility is a separate library on top (see below).
|
const file_system_module = kernel_library.module("file-system");
|
||||||
// Compiled into every user binary (see addUserBinary), so it inherits each exe's
|
const memory_module = kernel_library.module("memory");
|
||||||
// `.large` code model — do NOT set a target/code_model here. It imports `abi`
|
const service_module = kernel_library.module("service");
|
||||||
// for the shared SystemCall numbers / mmap flags, `device-abi` for the device
|
const start_module = kernel_library.module("start");
|
||||||
// types its `device` helper wraps, and re-exports `vfs-protocol` for the VFS
|
const driver_module = device_library.module("driver");
|
||||||
// server. It never touches `boot-handoff` — user space has no business with the
|
const block_client_module = device_library.module("block");
|
||||||
// loader↔kernel handoff.
|
const display_client_module = client_library.module("display");
|
||||||
// Wire-protocol modules the kernel-library client wrappers (device-manager/block/display)
|
const input_client_module = client_library.module("input");
|
||||||
// and the services speak. The `runtime` module itself is defined below, after the
|
const pci_module = device_library.module("pci");
|
||||||
// library/kernel concern modules it shims over.
|
const usb_module = device_library.module("usb");
|
||||||
const device_manager_protocol_module = b.addModule("device-manager-protocol", .{
|
const xkb_layouts_module = xkeyboard_config_library.module("layouts");
|
||||||
.root_source_file = b.path("library/protocol/device-manager/device-manager-protocol.zig"),
|
const xkeyboard_config_module = xkeyboard_config_library.module("xkeyboard-config");
|
||||||
});
|
|
||||||
const display_protocol_module = b.addModule("display-protocol", .{
|
|
||||||
.root_source_file = b.path("library/protocol/display/display-protocol.zig"),
|
|
||||||
});
|
|
||||||
|
|
||||||
// The scanout protocol: the compositor's outbound present channel to a native scanout
|
|
||||||
// driver (virtio-gpu), separate from the client-facing display protocol (docs/display-v2.md).
|
|
||||||
// No runtime client speaks it — imported directly by the compositor and the scanout driver.
|
|
||||||
const scanout_protocol_module = b.addModule("scanout-protocol", .{
|
|
||||||
.root_source_file = b.path("library/protocol/scanout/scanout-protocol.zig"),
|
|
||||||
});
|
|
||||||
|
|
||||||
// The power protocol: system power's domain-named surface (docs/power.md). No runtime
|
|
||||||
// client speaks it — imported directly by init and the acpi discovery service.
|
|
||||||
const power_protocol_module = b.addModule("power-protocol", .{
|
|
||||||
.root_source_file = b.path("library/protocol/power/power-protocol.zig"),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Typed volatile MMIO register access + memory-ordering barriers, for drivers on
|
|
||||||
// top of an mmio_map grant. Depends only on `builtin` (arch-conditional barriers);
|
|
||||||
// no target set, so it inherits each driver's. See library/device/mmio/mmio.zig.
|
|
||||||
const mmio_module = b.addModule("mmio", .{
|
|
||||||
.root_source_file = b.path("library/device/mmio/mmio.zig"),
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- library/kernel: the userspace private-ABI library (kernel32-style), split by
|
|
||||||
// concern into directly-importable modules. `system.zig` (the old dumping ground) and
|
|
||||||
// `runtime.zig` (the old aggregator) are compatibility shims re-exporting these until the
|
|
||||||
// consumers migrate to direct imports (reorg C1–C5). The graph is a DAG: memory depends on
|
|
||||||
// thread (heap needs Thread.Mutex), and thread does its own raw mmap so there is no cycle.
|
|
||||||
const system_call_module = b.addModule("system-call", .{
|
|
||||||
.root_source_file = b.path("library/kernel/system-call.zig"),
|
|
||||||
.imports = &.{.{ .name = "abi", .module = abi_module }},
|
|
||||||
});
|
|
||||||
const ipc_module = b.addModule("ipc", .{
|
|
||||||
.root_source_file = b.path("library/kernel/ipc.zig"),
|
|
||||||
.imports = &.{ .{ .name = "abi", .module = abi_module }, .{ .name = "system-call", .module = system_call_module } },
|
|
||||||
});
|
|
||||||
const time_module = b.addModule("time", .{
|
|
||||||
.root_source_file = b.path("library/kernel/time.zig"),
|
|
||||||
.imports = &.{.{ .name = "system-call", .module = system_call_module }},
|
|
||||||
});
|
|
||||||
const thread_module = b.addModule("thread", .{
|
|
||||||
.root_source_file = b.path("library/kernel/thread.zig"),
|
|
||||||
.imports = &.{ .{ .name = "abi", .module = abi_module }, .{ .name = "system-call", .module = system_call_module } },
|
|
||||||
});
|
|
||||||
const logging_module = b.addModule("logging", .{
|
|
||||||
.root_source_file = b.path("library/kernel/logging.zig"),
|
|
||||||
.imports = &.{ .{ .name = "abi", .module = abi_module }, .{ .name = "system-call", .module = system_call_module } },
|
|
||||||
});
|
|
||||||
const process_module = b.addModule("process", .{
|
|
||||||
.root_source_file = b.path("library/kernel/process.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "abi", .module = abi_module },
|
|
||||||
.{ .name = "system-call", .module = system_call_module },
|
|
||||||
.{ .name = "ipc", .module = ipc_module },
|
|
||||||
.{ .name = "time", .module = time_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const file_system_module = b.addModule("file-system", .{
|
|
||||||
.root_source_file = b.path("library/kernel/file-system.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "abi", .module = abi_module },
|
|
||||||
.{ .name = "system-call", .module = system_call_module },
|
|
||||||
.{ .name = "ipc", .module = ipc_module },
|
|
||||||
.{ .name = "vfs-protocol", .module = vfs_protocol_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const memory_module = b.addModule("memory", .{
|
|
||||||
.root_source_file = b.path("library/kernel/memory/memory.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "abi", .module = abi_module },
|
|
||||||
.{ .name = "system-call", .module = system_call_module },
|
|
||||||
.{ .name = "ipc", .module = ipc_module },
|
|
||||||
.{ .name = "thread", .module = thread_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const service_module = b.addModule("service", .{
|
|
||||||
.root_source_file = b.path("library/kernel/service.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "abi", .module = abi_module },
|
|
||||||
.{ .name = "ipc", .module = ipc_module },
|
|
||||||
.{ .name = "process", .module = process_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const start_module = b.addModule("start", .{
|
|
||||||
.root_source_file = b.path("library/kernel/start.zig"),
|
|
||||||
.imports = &.{ .{ .name = "process", .module = process_module }, .{ .name = "logging", .module = logging_module } },
|
|
||||||
});
|
|
||||||
// The driver author's interface (library/device/driver): device access + the
|
|
||||||
// device-manager hello handshake, folded together.
|
|
||||||
const driver_module = b.addModule("driver", .{
|
|
||||||
.root_source_file = b.path("library/device/driver/driver.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "abi", .module = abi_module },
|
|
||||||
.{ .name = "device-abi", .module = device_abi_module },
|
|
||||||
.{ .name = "system-call", .module = system_call_module },
|
|
||||||
.{ .name = "ipc", .module = ipc_module },
|
|
||||||
.{ .name = "time", .module = time_module },
|
|
||||||
.{ .name = "device-manager-protocol", .module = device_manager_protocol_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// The block-device client — a device type, so library/device/block.
|
|
||||||
const block_client_module = b.addModule("block", .{
|
|
||||||
.root_source_file = b.path("library/device/block/block.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "ipc", .module = ipc_module },
|
|
||||||
.{ .name = "time", .module = time_module },
|
|
||||||
.{ .name = "block-protocol", .module = block_protocol_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// Userspace-service clients live in library/client (they talk to services, not the kernel).
|
|
||||||
const display_client_module = b.addModule("display", .{
|
|
||||||
.root_source_file = b.path("library/client/display/display.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "ipc", .module = ipc_module },
|
|
||||||
.{ .name = "time", .module = time_module },
|
|
||||||
.{ .name = "display-protocol", .module = display_protocol_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const input_client_module = b.addModule("input", .{
|
|
||||||
.root_source_file = b.path("library/client/input/input.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "ipc", .module = ipc_module },
|
|
||||||
.{ .name = "time", .module = time_module },
|
|
||||||
.{ .name = "input-protocol", .module = input_protocol_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// A device driver's view of its claimed PCI function: config-space header fields, BAR
|
|
||||||
// decode + map, capability walks (legacy + extended), MSI/MSI-X programming, power
|
|
||||||
// state, and function-level reset (library/device/pci/pci.zig). The generic PCI
|
|
||||||
// mechanics every leaf PCI driver used to re-derive inline. Imports the driver (device
|
|
||||||
// access) client + mmio + the pci-class data module (config-space layout constants) +
|
|
||||||
// time (the D0 and FLR settle delays).
|
|
||||||
const pci_module = b.addModule("pci", .{
|
|
||||||
.root_source_file = b.path("library/device/pci/pci.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "driver", .module = driver_module },
|
|
||||||
.{ .name = "mmio", .module = mmio_module },
|
|
||||||
.{ .name = "pci-class", .module = pci_class_module },
|
|
||||||
.{ .name = "time", .module = time_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// The USB class-driver transfer client (library/device/usb/usb.zig): open a device on
|
|
||||||
// the xHCI bus and drive it (control / interrupt / bulk). Bus-family logic a class
|
|
||||||
// driver imports directly — over ipc + time. Re-exports usb-abi / usb-ids as
|
|
||||||
// usb.abi / usb.ids for a single USB import.
|
|
||||||
const usb_module = b.addModule("usb", .{
|
|
||||||
.root_source_file = b.path("library/device/usb/usb.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "ipc", .module = ipc_module },
|
|
||||||
.{ .name = "time", .module = time_module },
|
|
||||||
.{ .name = "usb-transfer-protocol", .module = usb_transfer_protocol_module },
|
|
||||||
.{ .name = "usb-abi", .module = usb_abi_module },
|
|
||||||
.{ .name = "usb-ids", .module = usb_ids_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Keyboard layouts compiled from the X11 xkeyboard-config database into native Zig
|
|
||||||
// (keycode + modifiers -> keysym/character). The `layouts` tables are generated by
|
|
||||||
// tools/make-xkeyboard-config.py; `xkeyboard-config` is the hand-written API over them.
|
|
||||||
// No target set, so each inherits its importer's. See library/xkeyboard-config/.
|
|
||||||
const xkb_layouts_module = b.addModule("layouts", .{
|
|
||||||
.root_source_file = b.path("library/xkeyboard-config/generated/layouts.zig"),
|
|
||||||
});
|
|
||||||
const xkeyboard_config_module = b.addModule("xkeyboard-config", .{
|
|
||||||
.root_source_file = b.path("library/xkeyboard-config/xkeyboard-config.zig"),
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "layouts", .module = xkb_layouts_module },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// The initial_ramdisk container format, shared by the kernel (unpacks it) and
|
// The initial_ramdisk container format, shared by the kernel (unpacks it) and
|
||||||
// the EFI loader (packs it in RAM from the boot volume's /system tree). No
|
// the EFI loader (packs it in RAM from the boot volume's /system tree). No
|
||||||
|
|||||||
@@ -35,6 +35,13 @@
|
|||||||
// The danos build API — the shared user-binary recipe every build file
|
// The danos build API — the shared user-binary recipe every build file
|
||||||
// (root and per-binary packages) consumes (docs/build-packages-plan.md).
|
// (root and per-binary packages) consumes (docs/build-packages-plan.md).
|
||||||
.@"build-support" = .{ .path = "build-support" },
|
.@"build-support" = .{ .path = "build-support" },
|
||||||
|
// The library domains, each a package exporting its modules.
|
||||||
|
.kernel = .{ .path = "library/kernel" },
|
||||||
|
.device = .{ .path = "library/device" },
|
||||||
|
.client = .{ .path = "library/client" },
|
||||||
|
.protocol = .{ .path = "library/protocol" },
|
||||||
|
.csv = .{ .path = "library/csv" },
|
||||||
|
.@"xkeyboard-config" = .{ .path = "library/xkeyboard-config" },
|
||||||
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
|
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
|
||||||
//.example = .{
|
//.example = .{
|
||||||
// // When updating this field to a new URL, be sure to delete the corresponding
|
// // When updating this field to a new URL, be sure to delete the corresponding
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//! The "client" library domain (library/client): userspace-service clients —
|
||||||
|
//! they talk to services over IPC, not to the kernel.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const kernel = b.dependency("kernel", .{});
|
||||||
|
const protocol = b.dependency("protocol", .{});
|
||||||
|
|
||||||
|
const ipc = kernel.module("ipc");
|
||||||
|
const time = kernel.module("time");
|
||||||
|
|
||||||
|
_ = b.addModule("display", .{
|
||||||
|
.root_source_file = b.path("display/display.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "ipc", .module = ipc },
|
||||||
|
.{ .name = "time", .module = time },
|
||||||
|
.{ .name = "display-protocol", .module = protocol.module("display-protocol") },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
_ = b.addModule("input", .{
|
||||||
|
.root_source_file = b.path("input/input.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "ipc", .module = ipc },
|
||||||
|
.{ .name = "time", .module = time },
|
||||||
|
.{ .name = "input-protocol", .module = protocol.module("input-protocol") },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
.{
|
||||||
|
.name = .client,
|
||||||
|
.version = "0.0.0",
|
||||||
|
.fingerprint = 0xc74404553e73d4ff, // Changing this has security and trust implications.
|
||||||
|
.minimum_zig_version = "0.16.0",
|
||||||
|
.dependencies = .{
|
||||||
|
// The clients converse over ipc with time-bounded waits.
|
||||||
|
.kernel = .{ .path = "../kernel" },
|
||||||
|
// Each client speaks its service's wire protocol.
|
||||||
|
.protocol = .{ .path = "../protocol" },
|
||||||
|
},
|
||||||
|
.paths = .{""},
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
//! The "csv" library domain: shared CSV helpers (comment stripping, field
|
||||||
|
//! iteration) for the /etc/*.csv config files — the device registry and the
|
||||||
|
//! init service list both parse them.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
_ = b.addModule("csv", .{ .root_source_file = b.path("csv.zig") });
|
||||||
|
|
||||||
|
// Standalone `zig build test` for this domain alone; the root build keeps
|
||||||
|
// its aggregate test step.
|
||||||
|
const test_step = b.step("test", "Run the csv unit tests");
|
||||||
|
const csv_tests = b.addTest(.{
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path("csv.zig"),
|
||||||
|
.target = b.resolveTargetQuery(.{}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
test_step.dependOn(&b.addRunArtifact(csv_tests).step);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
.{
|
||||||
|
.name = .csv,
|
||||||
|
.version = "0.0.0",
|
||||||
|
.fingerprint = 0x8a4525791f4e5b6, // Changing this has security and trust implications.
|
||||||
|
.minimum_zig_version = "0.16.0",
|
||||||
|
.dependencies = .{},
|
||||||
|
.paths = .{""},
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
//! The "device" library domain (library/device): what a driver author imports.
|
||||||
|
//! The flat reference data (device-abi, pci-class, acpi-ids, usb-abi, usb-ids),
|
||||||
|
//! typed MMIO access, the driver-side client libraries (driver, pci, usb,
|
||||||
|
//! block), the AML interpreter, and the data-driven device registry.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const kernel = b.dependency("kernel", .{});
|
||||||
|
const protocol = b.dependency("protocol", .{});
|
||||||
|
const csv = b.dependency("csv", .{});
|
||||||
|
|
||||||
|
const abi = kernel.module("abi");
|
||||||
|
const system_call = kernel.module("system-call");
|
||||||
|
const ipc = kernel.module("ipc");
|
||||||
|
const time = kernel.module("time");
|
||||||
|
|
||||||
|
// The devices sub-project's public interface (the flat wire types),
|
||||||
|
// importable by user space, unlike the kernel-internal device model it
|
||||||
|
// also feeds (system/kernel/device-model.zig).
|
||||||
|
const device_abi = b.addModule("device-abi", .{
|
||||||
|
.root_source_file = b.path("model/device-abi.zig"),
|
||||||
|
});
|
||||||
|
// PCI class-code decoding (class/subclass/prog-IF -> names). Pure reference
|
||||||
|
// data, shared by kernel discovery and any user-space PCI tool.
|
||||||
|
const pci_class = b.addModule("pci-class", .{
|
||||||
|
.root_source_file = b.path("pci/pci-class.zig"),
|
||||||
|
});
|
||||||
|
// ACPI/PnP hardware-ID (_HID) names — the flat analog of pci-class.
|
||||||
|
_ = b.addModule("acpi-ids", .{
|
||||||
|
.root_source_file = b.path("acpi/acpi-ids.zig"),
|
||||||
|
});
|
||||||
|
// The AML interpreter, a build module so the ring-3 acpi service can run
|
||||||
|
// the same parser the kernel does (docs/discovery.md). Pure Zig, no kernel
|
||||||
|
// imports — one source, two builds.
|
||||||
|
_ = b.addModule("aml", .{
|
||||||
|
.root_source_file = b.path("acpi/aml/aml.zig"),
|
||||||
|
});
|
||||||
|
// The USB device-framework wire ABI (chapter-9 set-up packets, standard +
|
||||||
|
// class requests, descriptors) and the USB class-code taxonomy.
|
||||||
|
const usb_abi = b.addModule("usb-abi", .{
|
||||||
|
.root_source_file = b.path("usb/usb-abi.zig"),
|
||||||
|
});
|
||||||
|
const usb_ids = b.addModule("usb-ids", .{
|
||||||
|
.root_source_file = b.path("usb/usb-ids.zig"),
|
||||||
|
});
|
||||||
|
// Typed volatile MMIO register access + memory-ordering barriers, for
|
||||||
|
// drivers on top of an mmio_map grant. Depends only on `builtin`.
|
||||||
|
const mmio = b.addModule("mmio", .{
|
||||||
|
.root_source_file = b.path("mmio/mmio.zig"),
|
||||||
|
});
|
||||||
|
// The driver author's interface: device access + the device-manager hello
|
||||||
|
// handshake, folded together.
|
||||||
|
const driver = b.addModule("driver", .{
|
||||||
|
.root_source_file = b.path("driver/driver.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "abi", .module = abi },
|
||||||
|
.{ .name = "device-abi", .module = device_abi },
|
||||||
|
.{ .name = "system-call", .module = system_call },
|
||||||
|
.{ .name = "ipc", .module = ipc },
|
||||||
|
.{ .name = "time", .module = time },
|
||||||
|
.{ .name = "device-manager-protocol", .module = protocol.module("device-manager-protocol") },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// A device driver's view of its claimed PCI function: config-space header
|
||||||
|
// fields, BAR decode + map, capability walks (legacy + extended), MSI/MSI-X
|
||||||
|
// programming, power state, and function-level reset — the generic PCI
|
||||||
|
// mechanics every leaf PCI driver used to re-derive inline.
|
||||||
|
_ = b.addModule("pci", .{
|
||||||
|
.root_source_file = b.path("pci/pci.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "driver", .module = driver },
|
||||||
|
.{ .name = "mmio", .module = mmio },
|
||||||
|
.{ .name = "pci-class", .module = pci_class },
|
||||||
|
.{ .name = "time", .module = time },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// The USB class-driver transfer client: open a device on the xHCI bus and
|
||||||
|
// drive it (control / interrupt / bulk). Re-exports usb-abi / usb-ids as
|
||||||
|
// usb.abi / usb.ids for a single USB import.
|
||||||
|
_ = b.addModule("usb", .{
|
||||||
|
.root_source_file = b.path("usb/usb.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "ipc", .module = ipc },
|
||||||
|
.{ .name = "time", .module = time },
|
||||||
|
.{ .name = "usb-transfer-protocol", .module = protocol.module("usb-transfer-protocol") },
|
||||||
|
.{ .name = "usb-abi", .module = usb_abi },
|
||||||
|
.{ .name = "usb-ids", .module = usb_ids },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// The block-device client — a device type, so it lives here.
|
||||||
|
_ = b.addModule("block", .{
|
||||||
|
.root_source_file = b.path("block/block.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "ipc", .module = ipc },
|
||||||
|
.{ .name = "time", .module = time },
|
||||||
|
.{ .name = "block-protocol", .module = protocol.module("block-protocol") },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// The device registry: parse /etc/devices.csv into match rules and bind a
|
||||||
|
// reported device to a driver. Pure logic (no hardware, no syscalls), so it
|
||||||
|
// unit-tests on the host; the device manager imports it.
|
||||||
|
_ = b.addModule("device-registry", .{
|
||||||
|
.root_source_file = b.path("registry/device-registry.zig"),
|
||||||
|
.imports = &.{.{ .name = "csv", .module = csv.module("csv") }},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Standalone `zig build test` for this domain alone; the root build keeps
|
||||||
|
// its aggregate test step.
|
||||||
|
const test_step = b.step("test", "Run the device library unit tests");
|
||||||
|
for ([_][]const u8{
|
||||||
|
"model/device-abi.zig", // wire-type sizes
|
||||||
|
"pci/pci-class.zig", // class/subclass/prog-IF name decoding
|
||||||
|
"acpi/acpi-ids.zig", // _HID name decoding
|
||||||
|
"acpi/aml/aml.zig", // AML parse + interpret, incl. Notify dispatch
|
||||||
|
"usb/usb-abi.zig", // wire sizes + bit packings + set-up packet encodings
|
||||||
|
"usb/usb-ids.zig", // class/subclass/protocol code assignments
|
||||||
|
"mmio/mmio.zig", // barriers assemble + registers round-trip
|
||||||
|
}) |root| {
|
||||||
|
const device_tests = b.addTest(.{
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path(root),
|
||||||
|
.target = b.resolveTargetQuery(.{}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
test_step.dependOn(&b.addRunArtifact(device_tests).step);
|
||||||
|
}
|
||||||
|
// The registry needs its csv import wired, so it doesn't fit the loop.
|
||||||
|
const registry_tests = b.addTest(.{
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path("registry/device-registry.zig"),
|
||||||
|
.target = b.resolveTargetQuery(.{}),
|
||||||
|
.imports = &.{.{ .name = "csv", .module = csv.module("csv") }},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
test_step.dependOn(&b.addRunArtifact(registry_tests).step);
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
.{
|
||||||
|
.name = .device,
|
||||||
|
.version = "0.0.0",
|
||||||
|
.fingerprint = 0x92fb68eace23a4f, // Changing this has security and trust implications.
|
||||||
|
.minimum_zig_version = "0.16.0",
|
||||||
|
.dependencies = .{
|
||||||
|
// driver/block/usb/pci build on the kernel library's concern modules.
|
||||||
|
.kernel = .{ .path = "../kernel" },
|
||||||
|
// driver speaks device-manager-protocol; block/usb their transfer protocols.
|
||||||
|
.protocol = .{ .path = "../protocol" },
|
||||||
|
// device-registry parses /etc/devices.csv with the shared csv helpers.
|
||||||
|
.csv = .{ .path = "../csv" },
|
||||||
|
},
|
||||||
|
.paths = .{""},
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
//! The "kernel" library domain (library/kernel): the userspace private-ABI
|
||||||
|
//! library (kernel32-style), split by concern into directly-importable
|
||||||
|
//! modules. The graph is a DAG: memory depends on thread (heap needs
|
||||||
|
//! Thread.Mutex), and thread does its own raw mmap so there is no cycle.
|
||||||
|
//!
|
||||||
|
//! This package also exports `abi` — the kernel <-> user contract (SystemCall
|
||||||
|
//! numbers, mmap prot flags, page_size). Its source lives with the kernel in
|
||||||
|
//! system/abi.zig, outside this directory, but userspace's one view of it is
|
||||||
|
//! exported here so every consumer names the same module instance.
|
||||||
|
//!
|
||||||
|
//! The root shim (root.zig) and the user link script (user.ld) are plain
|
||||||
|
//! files, not modules; build-support reaches them through this package's
|
||||||
|
//! directory (Dependency.path).
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const protocol = b.dependency("protocol", .{});
|
||||||
|
|
||||||
|
const abi = b.addModule("abi", .{
|
||||||
|
.root_source_file = b.path("../../system/abi.zig"),
|
||||||
|
});
|
||||||
|
const system_call = b.addModule("system-call", .{
|
||||||
|
.root_source_file = b.path("system-call.zig"),
|
||||||
|
.imports = &.{.{ .name = "abi", .module = abi }},
|
||||||
|
});
|
||||||
|
const ipc = b.addModule("ipc", .{
|
||||||
|
.root_source_file = b.path("ipc.zig"),
|
||||||
|
.imports = &.{ .{ .name = "abi", .module = abi }, .{ .name = "system-call", .module = system_call } },
|
||||||
|
});
|
||||||
|
const time = b.addModule("time", .{
|
||||||
|
.root_source_file = b.path("time.zig"),
|
||||||
|
.imports = &.{.{ .name = "system-call", .module = system_call }},
|
||||||
|
});
|
||||||
|
const thread = b.addModule("thread", .{
|
||||||
|
.root_source_file = b.path("thread.zig"),
|
||||||
|
.imports = &.{ .{ .name = "abi", .module = abi }, .{ .name = "system-call", .module = system_call } },
|
||||||
|
});
|
||||||
|
const logging = b.addModule("logging", .{
|
||||||
|
.root_source_file = b.path("logging.zig"),
|
||||||
|
.imports = &.{ .{ .name = "abi", .module = abi }, .{ .name = "system-call", .module = system_call } },
|
||||||
|
});
|
||||||
|
const process = b.addModule("process", .{
|
||||||
|
.root_source_file = b.path("process.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "abi", .module = abi },
|
||||||
|
.{ .name = "system-call", .module = system_call },
|
||||||
|
.{ .name = "ipc", .module = ipc },
|
||||||
|
.{ .name = "time", .module = time },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
_ = b.addModule("file-system", .{
|
||||||
|
.root_source_file = b.path("file-system.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "abi", .module = abi },
|
||||||
|
.{ .name = "system-call", .module = system_call },
|
||||||
|
.{ .name = "ipc", .module = ipc },
|
||||||
|
.{ .name = "vfs-protocol", .module = protocol.module("vfs-protocol") },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
_ = b.addModule("memory", .{
|
||||||
|
.root_source_file = b.path("memory/memory.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "abi", .module = abi },
|
||||||
|
.{ .name = "system-call", .module = system_call },
|
||||||
|
.{ .name = "ipc", .module = ipc },
|
||||||
|
.{ .name = "thread", .module = thread },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
_ = b.addModule("service", .{
|
||||||
|
.root_source_file = b.path("service.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "abi", .module = abi },
|
||||||
|
.{ .name = "ipc", .module = ipc },
|
||||||
|
.{ .name = "process", .module = process },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
_ = b.addModule("start", .{
|
||||||
|
.root_source_file = b.path("start.zig"),
|
||||||
|
.imports = &.{ .{ .name = "process", .module = process }, .{ .name = "logging", .module = logging } },
|
||||||
|
});
|
||||||
|
|
||||||
|
// Standalone `zig build test` for this domain alone; the root build keeps
|
||||||
|
// its aggregate test step. time and thread pull in the syscall wrappers,
|
||||||
|
// which need the `abi` module; their danos seams fall back to host
|
||||||
|
// primitives off the danos target, so they run with real host threads.
|
||||||
|
const test_step = b.step("test", "Run the kernel library unit tests");
|
||||||
|
for ([_][]const u8{
|
||||||
|
"time.zig", // Instant/Duration arithmetic
|
||||||
|
"thread.zig", // Mutex/Condition/RwLock/WaitGroup state machines
|
||||||
|
}) |root| {
|
||||||
|
const kernel_tests = b.addTest(.{
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path(root),
|
||||||
|
.target = b.resolveTargetQuery(.{}),
|
||||||
|
.imports = &.{.{ .name = "abi", .module = abi }},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
test_step.dependOn(&b.addRunArtifact(kernel_tests).step);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
.{
|
||||||
|
.name = .kernel,
|
||||||
|
.version = "0.0.0",
|
||||||
|
.fingerprint = 0x5dd29aab36503453, // Changing this has security and trust implications.
|
||||||
|
.minimum_zig_version = "0.16.0",
|
||||||
|
.dependencies = .{
|
||||||
|
// file-system speaks the VFS wire protocol.
|
||||||
|
.protocol = .{ .path = "../protocol" },
|
||||||
|
},
|
||||||
|
.paths = .{""},
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
//! The "protocol" library domain: the wire protocols — each service's public
|
||||||
|
//! interface, exposed as its own module (docs/driver-model.md). Both sides of
|
||||||
|
//! every conversation depend on the contract by name; neither reaches into the
|
||||||
|
//! other's files. Pure flat wire types: no protocol module imports anything.
|
||||||
|
//!
|
||||||
|
//! vfs-protocol : the VFS server <-> the file layer (unistd/stdio)
|
||||||
|
//! input-protocol : the input fan-out service <-> sources + subscribers
|
||||||
|
//! block-protocol : a filesystem <-> a block driver (usb-storage)
|
||||||
|
//! usb-transfer-protocol : a USB class driver <-> the xHCI bus driver
|
||||||
|
//! device-manager-protocol : the device manager <-> drivers + discovery
|
||||||
|
//! display-protocol : the compositor's client-facing surface
|
||||||
|
//! scanout-protocol : the compositor -> a native scanout driver (docs/display-v2.md)
|
||||||
|
//! power-protocol : system power's domain-named surface (docs/power.md)
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
for ([_]struct { name: []const u8, root: []const u8 }{
|
||||||
|
.{ .name = "vfs-protocol", .root = "vfs/vfs-protocol.zig" },
|
||||||
|
.{ .name = "input-protocol", .root = "input/input-protocol.zig" },
|
||||||
|
.{ .name = "block-protocol", .root = "block/block-protocol.zig" },
|
||||||
|
.{ .name = "usb-transfer-protocol", .root = "usb-transfer/usb-transfer-protocol.zig" },
|
||||||
|
.{ .name = "device-manager-protocol", .root = "device-manager/device-manager-protocol.zig" },
|
||||||
|
.{ .name = "display-protocol", .root = "display/display-protocol.zig" },
|
||||||
|
.{ .name = "scanout-protocol", .root = "scanout/scanout-protocol.zig" },
|
||||||
|
.{ .name = "power-protocol", .root = "power/power-protocol.zig" },
|
||||||
|
}) |protocol| {
|
||||||
|
_ = b.addModule(protocol.name, .{ .root_source_file = b.path(protocol.root) });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standalone `zig build test` for this domain alone; the root build keeps
|
||||||
|
// its aggregate test step.
|
||||||
|
const test_step = b.step("test", "Run the protocol unit tests");
|
||||||
|
for ([_][]const u8{
|
||||||
|
"vfs/vfs-protocol.zig", // NodeKind / DirectoryEntry sizes + op values
|
||||||
|
"display/display-protocol.zig", // pack(): native pixel encoding per format
|
||||||
|
}) |root| {
|
||||||
|
const protocol_tests = b.addTest(.{
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path(root),
|
||||||
|
.target = b.resolveTargetQuery(.{}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
test_step.dependOn(&b.addRunArtifact(protocol_tests).step);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
.{
|
||||||
|
.name = .protocol,
|
||||||
|
.version = "0.0.0",
|
||||||
|
.fingerprint = 0xc8c0bc4c4d551283, // Changing this has security and trust implications.
|
||||||
|
.minimum_zig_version = "0.16.0",
|
||||||
|
.dependencies = .{},
|
||||||
|
.paths = .{""},
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
//! The "xkeyboard-config" library domain: keyboard layouts compiled from the
|
||||||
|
//! X11 xkeyboard-config database into native Zig (keycode + modifiers ->
|
||||||
|
//! keysym/character). The `layouts` tables are generated by
|
||||||
|
//! tools/make-xkeyboard-config.py; `xkeyboard-config` is the hand-written API
|
||||||
|
//! over them.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const layouts = b.addModule("layouts", .{
|
||||||
|
.root_source_file = b.path("generated/layouts.zig"),
|
||||||
|
});
|
||||||
|
_ = b.addModule("xkeyboard-config", .{
|
||||||
|
.root_source_file = b.path("xkeyboard-config.zig"),
|
||||||
|
.imports = &.{.{ .name = "layouts", .module = layouts }},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Standalone `zig build test` for this domain alone; the root build keeps
|
||||||
|
// its aggregate test step. The keycode->character assertions are the
|
||||||
|
// end-to-end proof that the xkb-data -> generator -> Zig-lookup pipeline
|
||||||
|
// is correct.
|
||||||
|
const test_step = b.step("test", "Run the xkeyboard-config unit tests");
|
||||||
|
const xkb_tests = b.addTest(.{
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path("xkeyboard-config.zig"),
|
||||||
|
.target = b.resolveTargetQuery(.{}),
|
||||||
|
.imports = &.{.{ .name = "layouts", .module = layouts }},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
test_step.dependOn(&b.addRunArtifact(xkb_tests).step);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
.{
|
||||||
|
.name = .xkeyboard_config,
|
||||||
|
.version = "0.0.0",
|
||||||
|
.fingerprint = 0xea5abe82f08b6eae, // Changing this has security and trust implications.
|
||||||
|
.minimum_zig_version = "0.16.0",
|
||||||
|
.dependencies = .{},
|
||||||
|
.paths = .{""},
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user