summaryrefslogtreecommitdiff
path: root/build.zig
diff options
context:
space:
mode:
Diffstat (limited to 'build.zig')
-rw-r--r--build.zig54
1 files changed, 51 insertions, 3 deletions
diff --git a/build.zig b/build.zig
index 3c3c65f2..87df6727 100644
--- a/build.zig
+++ b/build.zig
@@ -2,6 +2,12 @@ const std = @import("std");
const snap_build = @import("build/snap.zig");
pub const Platform = enum { tty, gui, web };
+
+/// The ZLS the language backend links, spelled once. It names the commit
+/// build.zig.zon pins (0.16.x branch) and is passed BOTH to ZLS's own
+/// `-Dversion-string` (its build.zig otherwise shells out to `git describe`,
+/// which fails on a fetched package that has no .git) and to `SPC l i`.
+const zls_version = "0.16.1-dev+3e0d0820";
pub const TreeSitterGrammars = enum { disabled, zig, minimal, full };
const GhosttyArtifact = enum { ghostty, lib };
@@ -131,14 +137,19 @@ pub fn build(b: *std.Build) void {
opts.addOption(bool, "syntax_full_grammars", tree_sitter_grammars == .full);
opts.addOption(bool, "enable_tracy", tracy != null);
opts.addOption(bool, "zls_backend", zls_backend);
+ // Which ZLS is compiled in, for `SPC l i`. Kept next to the dependency it
+ // names: the .zon pins a commit, and a status screen that cannot say WHICH
+ // analyser answered is not worth opening.
+ opts.addOption([]const u8, "zls_version", if (zls_backend) zls_version else "none");
// The stdlib this binary was compiled against, so `gd` on `std.mem.count`
// can open the same mem.zig the compiler used. ZLS resolves `@import("std")`
// through `zig_lib_dir` and nothing else; without it every std symbol is a
// silent miss, and asking the `zig` binary for it is the subprocess this
// whole backend exists to avoid. ZIG_LIB_DIR overrides it at runtime.
opts.addOption([]const u8, "zig_lib_dir", b.graph.zig_lib_directory.path orelse "");
- root_mod.addOptions("pardes_config", opts);
- hx_core_mod.addOptions("pardes_config", opts);
+ // NOTE: `opts` is attached to the modules at the BOTTOM of this function,
+ // after every addImport — the module-import table below is folded out of
+ // root_mod.import_table and would be empty if we attached it here.
if (zls_backend) {
// .target/.optimize are mandatory: createZLSModule bakes them into the
@@ -154,7 +165,7 @@ pub fn build(b: *std.Build) void {
const zls_dep = b.dependency("zls", .{
.target = target,
.optimize = optimize,
- .@"version-string" = @as([]const u8, "0.16.1-dev"),
+ .@"version-string" = @as([]const u8, zls_version),
});
root_mod.addImport("zls", zls_dep.module("zls"));
hx_core_mod.addImport("zls", zls_dep.module("zls"));
@@ -376,6 +387,43 @@ pub fn build(b: *std.Build) void {
root_mod.addImport("uucode", uucode_mod);
hx_core_mod.addImport("uucode", uucode_mod);
+ // --- the dependency module map, for `gd` on `@import("vaxis")` ---
+ //
+ // ZLS resolves an import string three ways: a relative `.zig` path, `std`
+ // (via zig_lib_dir), and everything else — which it can only answer by
+ // running `zig build --build-runner` to learn the module graph. This
+ // backend sets `zig_exe_path = null` on purpose, so that last branch
+ // returns nothing and every `@import("<dependency>")` is a silent miss
+ // while `std` works perfectly. That asymmetry is the whole bug report.
+ //
+ // We do not need the compiler to answer it: THIS FILE *is* the module
+ // graph. Fold the imports we just wired into a name->root-source table and
+ // hand it to the backend, which consults it exactly where ZLS gave up.
+ // Costs one build option and stays correct by construction — a dependency
+ // that is added or renamed above cannot forget to update it.
+ var mod_names: std.ArrayList([]const u8) = .empty;
+ var mod_roots: std.ArrayList([]const u8) = .empty;
+ {
+ var it = root_mod.import_table.iterator();
+ while (it.next()) |e| {
+ const lp = e.value_ptr.*.root_source_file orelse continue;
+ // `generated` is a build artifact (the options modules): it has no
+ // path until make() runs, and pointing an editor at one is useless
+ const abs = switch (lp) {
+ .src_path => |sp| sp.owner.pathFromRoot(sp.sub_path),
+ .cwd_relative => |cr| cr,
+ else => continue,
+ };
+ mod_names.append(b.allocator, e.key_ptr.*) catch @panic("OOM");
+ mod_roots.append(b.allocator, abs) catch @panic("OOM");
+ }
+ }
+ opts.addOption([]const []const u8, "module_names", mod_names.items);
+ opts.addOption([]const []const u8, "module_roots", mod_roots.items);
+
+ root_mod.addOptions("pardes_config", opts);
+ hx_core_mod.addOptions("pardes_config", opts);
+
// SDL3 shell wiring (-Dplatform=gui and web). The sdl package builds SDL3
// from source as a static lib + emits the SDL3/ headers; gui.zig @cImports
// those, plus a small stb_truetype C shim for the glyph atlas, and embeds